Skip to content

Add IR printing functionality to the PassManager #494

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
May 15, 2025
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
16 changes: 14 additions & 2 deletions dialects/hir/src/transforms/spill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use alloc::rc::Rc;
use midenc_hir::{
adt::SmallDenseMap,
dialects::builtin::{Function, FunctionRef, LocalVariable},
pass::{Pass, PassExecutionState},
pass::{Pass, PassExecutionState, PostPassStatus},
BlockRef, BuilderExt, EntityMut, Op, OpBuilder, OperationName, OperationRef, Report, Rewriter,
SourceSpan, Spanned, Symbol, ValueRef,
};
Expand Down Expand Up @@ -38,6 +38,7 @@ impl Pass for TransformSpills {
if function.is_declaration() {
log::debug!(target: "insert-spills", "function has no body, no spills needed!");
state.preserved_analyses_mut().preserve_all();
state.set_post_pass_status(PostPassStatus::Unchanged);
return Ok(());
}
let mut analysis =
Expand All @@ -46,6 +47,7 @@ impl Pass for TransformSpills {
if !analysis.has_spills() {
log::debug!(target: "insert-spills", "no spills needed!");
state.preserved_analyses_mut().preserve_all();
state.set_post_pass_status(PostPassStatus::Unchanged);
return Ok(());
}

Expand All @@ -62,7 +64,17 @@ impl Pass for TransformSpills {

let op = function.as_operation_ref();
drop(function);
transforms::transform_spills(op, analysis, &mut interface, state.analysis_manager().clone())

let transform_result = transforms::transform_spills(
op,
analysis,
&mut interface,
state.analysis_manager().clone(),
)?;

state.set_post_pass_status(transform_result);

Ok(())
}
}

Expand Down
5 changes: 4 additions & 1 deletion dialects/scf/src/transforms/cfg_to_scf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use midenc_hir::{
diagnostics::Severity,
dialects::builtin,
dominance::DominanceInfo,
pass::{Pass, PassExecutionState},
pass::{Pass, PassExecutionState, PostPassStatus},
Builder, EntityMut, Forward, Op, Operation, OperationName, OperationRef, RawWalk, Report,
SmallVec, Spanned, Type, ValueRange, ValueRef, WalkResult,
};
Expand Down Expand Up @@ -130,6 +130,7 @@ impl Pass for LiftControlFlowToSCF {
});

if result.was_interrupted() {
state.set_post_pass_status(PostPassStatus::Unchanged);
return result.into_result();
}

Expand All @@ -141,6 +142,8 @@ impl Pass for LiftControlFlowToSCF {
state.preserved_analyses_mut().preserve_all();
}

state.set_post_pass_status(changed.into());

Ok(())
}
}
Expand Down
23 changes: 15 additions & 8 deletions hir-transform/src/canonicalization.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use alloc::{boxed::Box, format, rc::Rc};

use midenc_hir::{
pass::{OperationPass, Pass, PassExecutionState},
pass::{OperationPass, Pass, PassExecutionState, PostPassStatus},
patterns::{self, FrozenRewritePatternSet, GreedyRewriteConfig, RewritePatternSet},
Context, EntityMut, Operation, OperationName, Report, Spanned,
};
Expand Down Expand Up @@ -96,6 +96,7 @@ impl Pass for Canonicalizer {
) -> Result<(), Report> {
let Some(rewrites) = self.rewrites.as_ref() else {
log::debug!("skipping canonicalization as there are no rewrite patterns to apply");
state.set_post_pass_status(PostPassStatus::Unchanged);
return Ok(());
};
let op = {
Expand Down Expand Up @@ -129,15 +130,21 @@ impl Pass for Canonicalizer {
}

let op = op.borrow();
match converged {
let changed = match converged {
Ok(changed) => {
log::debug!("canonicalization converged for '{}', changed={changed}", op.name())
log::debug!("canonicalization converged for '{}', changed={changed}", op.name());
changed
}
Err(changed) => log::warn!(
"canonicalization failed to converge for '{}', changed={changed}",
op.name()
),
}
Err(changed) => {
log::warn!(
"canonicalization failed to converge for '{}', changed={changed}",
op.name()
);
changed
}
};
let ir_changed = changed.into();
state.set_post_pass_status(ir_changed);

Ok(())
}
Expand Down
13 changes: 9 additions & 4 deletions hir-transform/src/sccp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ impl SparseConditionalConstantPropagation {
fn rewrite(
&mut self,
op: &mut Operation,
_state: &mut PassExecutionState,
state: &mut PassExecutionState,
solver: &DataFlowSolver,
) -> Result<(), Report> {
let mut worklist = SmallVec::<[BlockRef; 8]>::default();
Expand All @@ -76,6 +76,7 @@ impl SparseConditionalConstantPropagation {

add_to_worklist(op.regions(), &mut worklist);

let mut replaced_any = false;
while let Some(mut block) = worklist.pop() {
let mut block = block.borrow_mut();
let body = block.body_mut();
Expand All @@ -91,8 +92,10 @@ impl SparseConditionalConstantPropagation {
let mut replaced_all = num_results != 0;
for index in 0..num_results {
let result = { op.borrow().get_result(index).borrow().as_value_ref() };
replaced_all &=
replace_with_constant(solver, &mut builder, &mut folder, result);
let replaced = replace_with_constant(solver, &mut builder, &mut folder, result);

replaced_any |= replaced;
replaced_all &= replaced;
}

// If all of the results of the operation were replaced, try to erase the operation
Expand All @@ -112,7 +115,7 @@ impl SparseConditionalConstantPropagation {
builder.set_insertion_point_to_start(block.as_block_ref());

for arg in block.arguments() {
replace_with_constant(
replaced_any |= replace_with_constant(
solver,
&mut builder,
&mut folder,
Expand All @@ -121,6 +124,8 @@ impl SparseConditionalConstantPropagation {
}
}

state.set_post_pass_status(replaced_any.into());

Ok(())
}
}
Expand Down
19 changes: 14 additions & 5 deletions hir-transform/src/sink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use midenc_hir::{
adt::SmallDenseMap,
dominance::DominanceInfo,
matchers::{self, Matcher},
pass::{Pass, PassExecutionState},
pass::{Pass, PassExecutionState, PostPassStatus},
traits::{ConstantLike, Terminator},
Backward, Builder, EntityMut, Forward, FxHashSet, OpBuilder, Operation, OperationName,
OperationRef, ProgramPoint, RawWalk, Region, RegionBranchOpInterface,
Expand Down Expand Up @@ -105,6 +105,7 @@ impl Pass for ControlFlowSink {

let dominfo = state.analysis_manager().get_analysis::<DominanceInfo>()?;

let mut sunk = PostPassStatus::Unchanged;
operation.raw_prewalk_all::<Forward, _>(|op: OperationRef| {
let regions_to_sink = {
let op = op.borrow();
Expand All @@ -118,7 +119,7 @@ impl Pass for ControlFlowSink {
};

// Sink side-effect free operations.
control_flow_sink(
sunk = control_flow_sink(
&regions_to_sink,
&dominfo,
|op: &Operation, _region: &Region| op.is_memory_effect_free(),
Expand All @@ -132,6 +133,8 @@ impl Pass for ControlFlowSink {
);
});

state.set_post_pass_status(sunk);

Ok(())
}
}
Expand Down Expand Up @@ -171,7 +174,7 @@ impl Pass for SinkOperandDefs {
fn run_on_operation(
&mut self,
op: EntityMut<'_, Self::Target>,
_state: &mut PassExecutionState,
state: &mut PassExecutionState,
) -> Result<(), Report> {
let operation = op.as_operation_ref();
drop(op);
Expand All @@ -184,6 +187,7 @@ impl Pass for SinkOperandDefs {
// then process the worklist, moving everything into position.
let mut worklist = alloc::collections::VecDeque::default();

let mut changed = PostPassStatus::Unchanged;
// Visit ops in "true" post-order (i.e. block bodies are visited bottom-up).
operation.raw_postwalk_all::<Backward, _>(|operation: OperationRef| {
// Determine if any of this operation's operands represent one of the following:
Expand Down Expand Up @@ -308,6 +312,7 @@ impl Pass for SinkOperandDefs {
log::trace!(target: "sink-operand-defs", " rewriting operand {operand_value} as {replacement}");
operand.borrow_mut().set(replacement);

changed = PostPassStatus::Changed;
// If no other uses of this value remain, then remove the original
// operation, as it is now dead.
if !operand_value.borrow().is_used() {
Expand Down Expand Up @@ -354,6 +359,7 @@ impl Pass for SinkOperandDefs {
log::trace!(target: "sink-operand-defs", " rewriting operand {operand_value} as {replacement}");
sink_state.replacements.insert(operand_value, replacement);
operand.borrow_mut().set(replacement);
changed = PostPassStatus::Changed;
} else {
log::trace!(target: "sink-operand-defs", " defining op is a constant with no other uses, moving into place");
// The original op can be moved
Expand Down Expand Up @@ -397,6 +403,7 @@ impl Pass for SinkOperandDefs {
}
}

state.set_post_pass_status(changed);
Ok(())
}
}
Expand Down Expand Up @@ -548,12 +555,14 @@ pub fn control_flow_sink<P, F>(
dominfo: &DominanceInfo,
should_move_into_region: P,
move_into_region: F,
) where
) -> PostPassStatus
where
P: Fn(&Operation, &Region) -> bool,
F: Fn(OperationRef, RegionRef),
{
let sinker = Sinker::new(dominfo, should_move_into_region, move_into_region);
sinker.sink_regions(regions);
let sunk_regions = sinker.sink_regions(regions);
(sunk_regions > 0).into()
}

/// Populates `regions` with regions of the provided region branch op that are executed at most once
Expand Down
6 changes: 3 additions & 3 deletions hir-transform/src/spill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use midenc_hir::{
adt::{SmallDenseMap, SmallSet},
cfg::Graph,
dominance::{DomTreeNode, DominanceFrontier, DominanceInfo},
pass::AnalysisManager,
pass::{AnalysisManager, PostPassStatus},
traits::SingleRegion,
BlockRef, Builder, Context, FxHashMap, OpBuilder, OpOperand, Operation, OperationRef,
ProgramPoint, Region, RegionBranchOpInterface, RegionBranchPoint, RegionRef, Report, Rewriter,
Expand Down Expand Up @@ -113,7 +113,7 @@ pub fn transform_spills(
analysis: &mut SpillAnalysis,
interface: &mut dyn TransformSpillsInterface,
analysis_manager: AnalysisManager,
) -> Result<(), Report> {
) -> Result<PostPassStatus, Report> {
assert!(
op.borrow().implements::<dyn SingleRegion>(),
"the spills transformation is not supported when the root op is multi-region"
Expand Down Expand Up @@ -252,7 +252,7 @@ pub fn transform_spills(
)?;
}

Ok(())
Ok(PostPassStatus::Changed)
}

fn rewrite_single_block_spills(
Expand Down
1 change: 1 addition & 0 deletions hir/src/ir/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::{
AttributeValue, EntityWithId, SuccessorOperands, Value,
};

#[derive(Debug)]
pub struct OpPrintingFlags {
pub print_entry_block_headers: bool,
pub print_intrinsic_attributes: bool,
Expand Down
Loading