cairo_lang_lowering/optimizations/
strategy.rs1use cairo_lang_diagnostics::Maybe;
2use cairo_lang_proc_macros::HeapSize;
3use cairo_lang_utils::{Intern, define_short_id};
4use salsa::Database;
5
6use super::cse::cse;
7use super::dedup_blocks::dedup_blocks;
8use super::early_unsafe_panic::early_unsafe_panic;
9use super::gas_redeposit::gas_redeposit;
10use super::reboxing::apply_reboxing;
11use super::trim_unreachable::trim_unreachable;
12use super::validate::validate;
13use crate::Lowered;
14use crate::db::LoweringGroup;
15use crate::ids::ConcreteFunctionWithBodyId;
16use crate::implicits::lower_implicits;
17use crate::inline::apply_inlining;
18use crate::optimizations::branch_inversion::branch_inversion;
19use crate::optimizations::cancel_ops::cancel_ops;
20use crate::optimizations::config::Optimizations;
21use crate::optimizations::const_folding::const_folding;
22use crate::optimizations::match_optimizer::optimize_matches;
23use crate::optimizations::remappings::optimize_remappings;
24use crate::optimizations::reorder_statements::reorder_statements;
25use crate::optimizations::return_optimization::return_optimization;
26use crate::optimizations::split_structs::split_structs;
27use crate::reorganize_blocks::reorganize_blocks;
28
29#[derive(Clone, Debug, Eq, Hash, PartialEq, HeapSize)]
31pub enum OptimizationPhase<'db> {
32 ApplyInlining {
33 enable_const_folding: bool,
34 },
35 BranchInversion,
36 CancelOps,
37 ConstFolding,
38 Cse,
39 DedupBlocks,
40 EarlyUnsafePanic,
41 OptimizeMatches,
42 OptimizeRemappings,
43 Reboxing,
44 ReorderStatements,
45 ReorganizeBlocks,
46 ReturnOptimization,
47 SplitStructs,
48 TrimUnreachable,
49 GasRedeposit,
50 LowerImplicits,
53 Validate,
55 SubStrategy {
58 strategy: OptimizationStrategyId<'db>,
60 iterations: usize,
62 },
63}
64
65impl<'db> OptimizationPhase<'db> {
66 pub fn apply(
70 self,
71 db: &'db dyn Database,
72 function: ConcreteFunctionWithBodyId<'db>,
73 lowered: &mut Lowered<'db>,
74 ) -> Maybe<()> {
75 debug!("Applying optimization: {self:?}");
76
77 match self {
78 OptimizationPhase::ApplyInlining { enable_const_folding } => {
79 apply_inlining(db, function, lowered, enable_const_folding)?
80 }
81 OptimizationPhase::BranchInversion => branch_inversion(db, lowered),
82 OptimizationPhase::CancelOps => cancel_ops(lowered),
83 OptimizationPhase::ConstFolding => const_folding(db, function, lowered),
84 OptimizationPhase::Cse => cse(lowered),
85 OptimizationPhase::EarlyUnsafePanic => early_unsafe_panic(db, lowered),
86 OptimizationPhase::DedupBlocks => dedup_blocks(lowered),
87 OptimizationPhase::OptimizeMatches => optimize_matches(lowered),
88 OptimizationPhase::OptimizeRemappings => optimize_remappings(lowered),
89 OptimizationPhase::Reboxing => apply_reboxing(db, lowered),
90 OptimizationPhase::ReorderStatements => reorder_statements(db, lowered),
91 OptimizationPhase::ReorganizeBlocks => reorganize_blocks(lowered),
92 OptimizationPhase::ReturnOptimization => return_optimization(db, lowered),
93 OptimizationPhase::SplitStructs => split_structs(lowered),
94 OptimizationPhase::TrimUnreachable => trim_unreachable(db, lowered),
95 OptimizationPhase::LowerImplicits => lower_implicits(db, function, lowered),
96 OptimizationPhase::GasRedeposit => gas_redeposit(db, function, lowered),
97 OptimizationPhase::Validate => validate(lowered).unwrap_or_else(|err| {
98 panic!(
99 "Failed validation for function {}: {:?}",
100 function.full_path(db),
101 err.to_message()
102 )
103 }),
104 OptimizationPhase::SubStrategy { strategy, iterations } => {
105 for _ in 1..iterations {
106 let before = lowered.clone();
107 strategy.apply_strategy(db, function, lowered)?;
108 if *lowered == before {
109 return Ok(());
110 }
111 }
112 strategy.apply_strategy(db, function, lowered)?
113 }
114 }
115 Ok(())
116 }
117}
118
119define_short_id!(OptimizationStrategyId, OptimizationStrategy<'db>);
120
121#[derive(Clone, Debug, Eq, Hash, PartialEq, HeapSize)]
123pub struct OptimizationStrategy<'db>(pub Vec<OptimizationPhase<'db>>);
124
125impl<'db> OptimizationStrategyId<'db> {
126 pub fn apply_strategy(
130 self,
131 db: &'db dyn Database,
132 function: ConcreteFunctionWithBodyId<'db>,
133 lowered: &mut Lowered<'db>,
134 ) -> Maybe<()> {
135 for phase in self.long(db).0.clone() {
136 phase.apply(db, function, lowered)?;
137 }
138
139 Ok(())
140 }
141}
142
143#[salsa::tracked]
145pub fn baseline_optimization_strategy<'db>(db: &'db dyn Database) -> OptimizationStrategyId<'db> {
146 match db.optimizations() {
147 Optimizations::Enabled(_) => {
148 OptimizationStrategy(vec![
149 OptimizationPhase::ReorganizeBlocks,
151 OptimizationPhase::ApplyInlining { enable_const_folding: true },
152 OptimizationPhase::ReturnOptimization,
153 OptimizationPhase::ReorganizeBlocks,
154 OptimizationPhase::ReorderStatements,
155 OptimizationPhase::BranchInversion,
156 OptimizationPhase::CancelOps,
157 OptimizationPhase::ReorganizeBlocks,
159 OptimizationPhase::ConstFolding,
160 OptimizationPhase::OptimizeMatches,
161 OptimizationPhase::SplitStructs,
162 OptimizationPhase::ReorganizeBlocks,
163 OptimizationPhase::ReorderStatements,
164 OptimizationPhase::OptimizeMatches,
165 OptimizationPhase::ReorganizeBlocks,
166 OptimizationPhase::Reboxing,
167 OptimizationPhase::CancelOps,
168 OptimizationPhase::ReorganizeBlocks,
169 OptimizationPhase::Cse,
172 OptimizationPhase::DedupBlocks,
173 OptimizationPhase::ReturnOptimization,
175 OptimizationPhase::ReorderStatements,
176 OptimizationPhase::ReorganizeBlocks,
177 ])
178 }
179 Optimizations::Disabled => OptimizationStrategy(vec![OptimizationPhase::ApplyInlining {
180 enable_const_folding: false,
181 }]),
182 }
183 .intern(db)
184}
185
186#[salsa::tracked]
188pub fn final_optimization_strategy<'db>(db: &'db dyn Database) -> OptimizationStrategyId<'db> {
189 match db.optimizations() {
190 Optimizations::Enabled(_) => {
191 OptimizationStrategy(vec![
192 OptimizationPhase::GasRedeposit,
193 OptimizationPhase::EarlyUnsafePanic,
194 OptimizationPhase::TrimUnreachable,
197 OptimizationPhase::LowerImplicits,
198 OptimizationPhase::ReorganizeBlocks,
199 ])
200 }
201 Optimizations::Disabled => OptimizationStrategy(vec![
202 OptimizationPhase::LowerImplicits,
203 OptimizationPhase::ReorganizeBlocks,
204 ]),
205 }
206 .intern(db)
207}