Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion libs/@local/hashql/mir/src/body/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! Operands represent the inputs to MIR operations. They can either reference
//! a storage location (place) or contain an immediate constant value.

use super::{constant::Constant, place::Place};
use super::{constant::Constant, local::Local, place::Place};

/// An operand in a HashQL MIR operation.
///
Expand Down Expand Up @@ -59,6 +59,12 @@ impl<'heap> Operand<'heap> {
}
}

impl From<Local> for Operand<'_> {
fn from(local: Local) -> Self {
Operand::Place(Place::local(local))
}
}

impl<'heap> From<Place<'heap>> for Operand<'heap> {
fn from(place: Place<'heap>) -> Self {
Operand::Place(place)
Expand Down
5 changes: 3 additions & 2 deletions libs/@local/hashql/mir/src/body/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,10 +315,11 @@ impl<'heap> Place<'heap> {
/// This is the simplest form of a place, representing direct access to a local variable
/// without navigating through any structured data. The resulting place has an empty
/// projection sequence.
pub fn local(local: Local, interner: &Interner<'heap>) -> Self {
#[must_use]
pub const fn local(local: Local) -> Self {
Self {
local,
projections: interner.projections.intern_slice(&[]),
projections: Interned::empty(),
}
}

Expand Down
89 changes: 39 additions & 50 deletions libs/@local/hashql/mir/src/body/terminator/switch_int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,20 +74,17 @@ pub enum SwitchIntValue {
/// let targets = SwitchTargets::new(
/// &heap,
/// [
/// (0, Target::block(bb0, &interner)),
/// (1, Target::block(bb1, &interner)),
/// (2, Target::block(bb2, &interner)),
/// (0, Target::block(bb0)),
/// (1, Target::block(bb1)),
/// (2, Target::block(bb2)),
/// ],
/// Some(Target::block(otherwise, &interner)),
/// Some(Target::block(otherwise)),
/// );
///
/// // Values are automatically sorted
/// assert_eq!(targets.values(), &[0, 1, 2]);
/// assert_eq!(targets.target(1), Some(Target::block(bb1, &interner)));
/// assert_eq!(
/// targets.target(99),
/// Some(Target::block(otherwise, &interner))
/// );
/// assert_eq!(targets.target(1), Some(Target::block(bb1)));
/// assert_eq!(targets.target(99), Some(Target::block(otherwise)));
/// ```
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SwitchTargets<'heap> {
Expand Down Expand Up @@ -131,11 +128,11 @@ impl<'heap> SwitchTargets<'heap> {
/// let targets = SwitchTargets::new(
/// &heap,
/// [
/// (10, Target::block(BasicBlockId::new(0), &interner)),
/// (20, Target::block(BasicBlockId::new(1), &interner)),
/// (30, Target::block(BasicBlockId::new(2), &interner)),
/// (10, Target::block(BasicBlockId::new(0))),
/// (20, Target::block(BasicBlockId::new(1))),
/// (30, Target::block(BasicBlockId::new(2))),
/// ],
/// Some(Target::block(BasicBlockId::new(3), &interner)),
/// Some(Target::block(BasicBlockId::new(3))),
/// );
///
/// assert_eq!(targets.values(), &[10, 20, 30]);
Expand All @@ -158,11 +155,7 @@ impl<'heap> SwitchTargets<'heap> {
/// let heap = Heap::new();
/// let interner = Interner::new(&heap);
///
/// let targets = SwitchTargets::new(
/// &heap,
/// [(0, Target::block(BasicBlockId::new(0), &interner))],
/// None,
/// );
/// let targets = SwitchTargets::new(&heap, [(0, Target::block(BasicBlockId::new(0)))], None);
///
/// assert_eq!(targets.otherwise(), None);
/// assert_eq!(targets.target(99), None); // No otherwise, so None for unmatched values
Expand Down Expand Up @@ -214,8 +207,8 @@ impl<'heap> SwitchTargets<'heap> {
/// let heap = Heap::new();
/// let interner = Interner::new(&heap);
///
/// let then_block = Target::block(BasicBlockId::new(1), &interner);
/// let else_block = Target::block(BasicBlockId::new(2), &interner);
/// let then_block = Target::block(BasicBlockId::new(1));
/// let else_block = Target::block(BasicBlockId::new(2));
///
/// let targets = SwitchTargets::new_if(&heap, then_block, else_block);
///
Expand Down Expand Up @@ -261,8 +254,8 @@ impl<'heap> SwitchTargets<'heap> {
/// let heap = Heap::new();
/// let interner = Interner::new(&heap);
///
/// let then_block = Target::block(BasicBlockId::new(1), &interner);
/// let else_block = Target::block(BasicBlockId::new(2), &interner);
/// let then_block = Target::block(BasicBlockId::new(1));
/// let else_block = Target::block(BasicBlockId::new(2));
///
/// // Binary switch can be converted
/// let binary = SwitchTargets::new_if(&heap, then_block, else_block);
Expand Down Expand Up @@ -316,11 +309,11 @@ impl<'heap> SwitchTargets<'heap> {
/// let heap = Heap::new();
/// let interner = Interner::new(&heap);
///
/// let default = Target::block(BasicBlockId::new(99), &interner);
/// let default = Target::block(BasicBlockId::new(99));
///
/// let with_otherwise = SwitchTargets::new(
/// &heap,
/// [(1, Target::block(BasicBlockId::new(0), &interner))],
/// [(1, Target::block(BasicBlockId::new(0)))],
/// Some(default),
/// );
/// assert_eq!(with_otherwise.otherwise(), Some(default));
Expand Down Expand Up @@ -353,9 +346,9 @@ impl<'heap> SwitchTargets<'heap> {
/// let heap = Heap::new();
/// let interner = Interner::new(&heap);
///
/// let bb0 = Target::block(BasicBlockId::new(0), &interner);
/// let bb1 = Target::block(BasicBlockId::new(1), &interner);
/// let otherwise = Target::block(BasicBlockId::new(99), &interner);
/// let bb0 = Target::block(BasicBlockId::new(0));
/// let bb1 = Target::block(BasicBlockId::new(1));
/// let otherwise = Target::block(BasicBlockId::new(99));
///
/// let targets = SwitchTargets::new(&heap, [(10, bb0), (20, bb1)], Some(otherwise));
///
Expand Down Expand Up @@ -417,8 +410,8 @@ impl<'heap> SwitchTargets<'heap> {
/// let mut targets = SwitchTargets::new(
/// &heap,
/// [
/// (1, Target::block(BasicBlockId::new(0), &interner)),
/// (2, Target::block(BasicBlockId::new(1), &interner)),
/// (1, Target::block(BasicBlockId::new(0))),
/// (2, Target::block(BasicBlockId::new(1))),
/// ],
/// None,
/// );
Expand Down Expand Up @@ -459,10 +452,10 @@ impl<'heap> SwitchTargets<'heap> {
/// let targets = SwitchTargets::new(
/// &heap,
/// [
/// (10, Target::block(BasicBlockId::new(0), &interner)),
/// (20, Target::block(BasicBlockId::new(1), &interner)),
/// (10, Target::block(BasicBlockId::new(0))),
/// (20, Target::block(BasicBlockId::new(1))),
/// ],
/// Some(Target::block(BasicBlockId::new(99), &interner)),
/// Some(Target::block(BasicBlockId::new(99))),
/// );
///
/// let pairs: Vec<_> = targets.iter().collect();
Expand Down Expand Up @@ -501,8 +494,8 @@ impl<'heap> SwitchTargets<'heap> {
/// let mut targets = SwitchTargets::new(
/// &heap,
/// [
/// (10, Target::block(BasicBlockId::new(0), &interner)),
/// (20, Target::block(BasicBlockId::new(1), &interner)),
/// (10, Target::block(BasicBlockId::new(0))),
/// (20, Target::block(BasicBlockId::new(1))),
/// ],
/// None,
/// );
Expand Down Expand Up @@ -545,8 +538,8 @@ impl<'heap> SwitchTargets<'heap> {
///
/// let mut targets = SwitchTargets::new(&heap, [], None);
///
/// targets.add_target(10, Target::block(BasicBlockId::new(0), &interner));
/// targets.add_target(5, Target::block(BasicBlockId::new(1), &interner));
/// targets.add_target(10, Target::block(BasicBlockId::new(0)));
/// targets.add_target(5, Target::block(BasicBlockId::new(1)));
///
/// // Values are kept sorted
/// assert_eq!(targets.values(), &[5, 10]);
Expand Down Expand Up @@ -587,16 +580,12 @@ impl<'heap> SwitchTargets<'heap> {
/// let heap = Heap::new();
/// let interner = Interner::new(&heap);
///
/// let mut first = SwitchTargets::new(
/// &heap,
/// [(10, Target::block(BasicBlockId::new(0), &interner))],
/// None,
/// );
/// let mut first = SwitchTargets::new(&heap, [(10, Target::block(BasicBlockId::new(0)))], None);
///
/// let mut second = SwitchTargets::new(
/// &heap,
/// [(20, Target::block(BasicBlockId::new(1), &interner))],
/// Some(Target::block(BasicBlockId::new(99), &interner)),
/// [(20, Target::block(BasicBlockId::new(1)))],
/// Some(Target::block(BasicBlockId::new(99))),
/// );
///
/// first.append(&mut second);
Expand Down Expand Up @@ -702,11 +691,11 @@ impl<'heap> SwitchTargets<'heap> {
/// let targets = SwitchTargets::new(
/// &heap,
/// [
/// (0, Target::block(BasicBlockId::new(0), &interner)),
/// (1, Target::block(BasicBlockId::new(1), &interner)),
/// (2, Target::block(BasicBlockId::new(2), &interner)),
/// (0, Target::block(BasicBlockId::new(0))),
/// (1, Target::block(BasicBlockId::new(1))),
/// (2, Target::block(BasicBlockId::new(2))),
/// ],
/// Some(Target::block(BasicBlockId::new(3), &interner)), // otherwise
/// Some(Target::block(BasicBlockId::new(3))), // otherwise
/// );
///
/// // Create the switch with an integer discriminant
Expand Down Expand Up @@ -734,12 +723,12 @@ impl<'heap> SwitchTargets<'heap> {
/// let heap = Heap::new();
/// let interner = Interner::new(&heap);
///
/// let then_target = Target::block(BasicBlockId::new(1), &interner);
/// let else_target = Target::block(BasicBlockId::new(2), &interner);
/// let then_target = Target::block(BasicBlockId::new(1));
/// let else_target = Target::block(BasicBlockId::new(2));
///
/// // Create a binary switch for if-else
/// let switch = SwitchInt {
/// discriminant: Operand::Place(Place::local(Local::new(0), &interner)),
/// discriminant: Operand::Place(Place::local(Local::new(0))),
/// targets: SwitchTargets::new_if(&heap, then_target, else_target),
/// };
///
Expand Down
14 changes: 6 additions & 8 deletions libs/@local/hashql/mir/src/body/terminator/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@

use hashql_core::intern::Interned;

use crate::{
body::{basic_block::BasicBlockId, operand::Operand},
intern::Interner,
};
use crate::body::{basic_block::BasicBlockId, operand::Operand};

/// A control flow target in the HashQL MIR.
///
Expand Down Expand Up @@ -39,11 +36,12 @@ pub struct Target<'heap> {
pub args: Interned<'heap, [Operand<'heap>]>,
}

impl<'heap> Target<'heap> {
pub fn block(block: impl Into<BasicBlockId>, interner: &Interner<'heap>) -> Self {
impl Target<'_> {
#[must_use]
pub const fn block(block: BasicBlockId) -> Self {
Self {
block: block.into(),
args: interner.operands.intern_slice(&[]),
block,
args: Interned::empty(),
}
}
}
2 changes: 1 addition & 1 deletion libs/@local/hashql/mir/src/builder/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ impl<'env, 'heap> BodyBuilder<'env, 'heap> {
};
let local = self.local_decls.push(decl);

Place::local(local, self.interner)
Place::local(local)
}

/// Reserves a new basic block and returns its ID.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ fn resolve_params_const<'heap, A: Allocator + Clone>(
} else {
// We have finished (we have terminated on a param, which is divergent, therefore the place
// is still valid, just doesn't have a constant value)
ResolutionResult::Resolved(Operand::Place(Place::local(place.local, state.interner)))
ResolutionResult::Resolved(Operand::Place(Place::local(place.local)))
}
}

Expand Down Expand Up @@ -382,15 +382,14 @@ pub(crate) fn resolve<'heap, A: Allocator + Clone>(
[] => {
// Base case: no more projections to resolve.
// Check for constant propagation through Load.
let operand = if let Some(constant) = state
let operand = state
.graph
.constant_bindings
.find_by_kind(place.local, EdgeKind::Load)
{
Operand::Constant(constant)
} else {
Operand::Place(Place::local(place.local, state.interner))
};
.map_or_else(
|| Operand::Place(Place::local(place.local)),
Operand::Constant,
);

return ResolutionResult::Resolved(operand);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ impl<'heap, A: Allocator> AdministrativeReductionVisitor<'_, '_, 'heap, A> {
.enumerate()
.map(|(param, argument)| Statement {
kind: StatementKind::Assign(Assign {
lhs: Place::local(Local::new(local_offset + param), self.interner),
lhs: Place::local(Local::new(local_offset + param)),
rhs: RValue::Load(argument),
}),
span,
Expand Down
11 changes: 3 additions & 8 deletions libs/@local/hashql/mir/src/pass/transform/cfg_simplify/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,7 @@ impl<A: BumpAllocator> CfgSimplify<A> {
/// 3. Replace `A`'s terminator with `B`'s terminator
///
/// SSA invariants may be temporarily broken; the [`SsaRepair`] runs afterward to fix them.
fn simplify_goto<'heap>(
context: &MirContext<'_, 'heap>,
body: &mut Body<'heap>,
id: BasicBlockId,
goto: Goto<'heap>,
) -> bool {
fn simplify_goto<'heap>(body: &mut Body<'heap>, id: BasicBlockId, goto: Goto<'heap>) -> bool {
// Self-loops cannot be optimized as there's no simplification possible.
if goto.target.block == id {
return false;
Expand Down Expand Up @@ -170,7 +165,7 @@ impl<A: BumpAllocator> CfgSimplify<A> {
block.statements.push(Statement {
span: block.terminator.span,
kind: StatementKind::Assign(Assign {
lhs: Place::local(param, context.interner),
lhs: Place::local(param),
rhs: RValue::Load(arg),
}),
});
Expand Down Expand Up @@ -424,7 +419,7 @@ impl<A: BumpAllocator> CfgSimplify<A> {
.transfer_into(&self.alloc);

let changed = match &body.basic_blocks[id].terminator.kind {
&TerminatorKind::Goto(goto) => Self::simplify_goto(context, body, id, goto),
&TerminatorKind::Goto(goto) => Self::simplify_goto(body, id, goto),
TerminatorKind::SwitchInt(_) => Self::simplify_switch_int(context, body, id),
TerminatorKind::Return(_)
| TerminatorKind::GraphRead(_)
Expand Down
Loading
Loading