use crate::ir_inner::model::program::Program;
#[must_use]
#[inline]
pub fn optimize(program: Program) -> Program {
use crate::optimizer::passes::algebraic::canonicalize_engine;
use crate::optimizer::passes::cleanup::region_inline_engine;
let prepared =
region_inline_engine::run(canonicalize_engine::run(program)).reconcile_runnable_top_level();
let scheduled = {
use crate::optimizer::passes::const_fold::ConstFold;
use crate::optimizer::passes::loop_strip_mine::LoopStripMine;
use crate::optimizer::passes::loop_unroll::LoopUnroll;
use crate::optimizer::passes::normalize_atomics::NormalizeAtomicsPass;
use crate::optimizer::passes::strength_reduce::StrengthReduce;
use crate::optimizer::{PassScheduler, ProgramPassKind};
PassScheduler::with_passes(vec![
ProgramPassKind::new(ConstFold),
ProgramPassKind::new(LoopStripMine),
ProgramPassKind::new(LoopUnroll),
ProgramPassKind::new(StrengthReduce),
ProgramPassKind::new(NormalizeAtomicsPass),
])
.run(prepared.clone())
.unwrap_or(prepared)
};
let cleaned = canonicalize_engine::run(region_inline_engine::run(
crate::optimizer::passes::fusion_cse::dce::engine::dce(
crate::optimizer::passes::fusion_cse::cse::engine::cse(scheduled),
),
));
let phase4 = {
use crate::optimizer::passes::algebraic::canonicalize::Canonicalize;
use crate::optimizer::passes::cleanup::if_constant_branch_eliminate::IfConstantBranchEliminatePass;
use crate::optimizer::passes::const_fold::ConstFold;
use crate::optimizer::passes::fusion_cse::dce::DcePass;
use crate::optimizer::passes::region_inline::RegionInlinePass;
use crate::optimizer::{PassScheduler, ProgramPassKind};
match PassScheduler::with_passes(vec![
ProgramPassKind::new(ConstFold),
ProgramPassKind::new(IfConstantBranchEliminatePass),
ProgramPassKind::new(Canonicalize),
ProgramPassKind::new(DcePass),
ProgramPassKind::new(RegionInlinePass),
])
.run(cleaned.clone())
{
Ok(p) => p,
Err(e) => {
println!("Phase 4 hit iteration limit! Error: {:?}", e);
cleaned
}
}
};
phase4.reconcile_runnable_top_level()
}
#[cfg(test)]
mod tests {
use super::optimize;
use crate::ir::{BufferDecl, DataType, Expr, Node, Program};
#[test]
fn optimize_preserves_top_level_region_wrap_after_inline() {
let program = Program::wrapped(
vec![BufferDecl::output("out", 0, DataType::U32).with_count(1)],
[1, 1, 1],
vec![Node::store("out", Expr::u32(0), Expr::u32(7))],
);
assert!(program.is_top_level_region_wrapped());
let optimized = optimize(program);
assert!(
optimized.is_top_level_region_wrapped(),
"Fix: optimize() must preserve top-level region-wrap invariant after region_inline"
);
}
}