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, salsa::Update, 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
65pub trait ApplyOptimization<'db> {
67 fn apply(
71 &self,
72 db: &'db dyn Database,
73 function: ConcreteFunctionWithBodyId<'db>,
74 lowered: &mut Lowered<'db>,
75 ) -> Maybe<()>;
76}
77
78impl<'db> ApplyOptimization<'db> for OptimizationPhase<'db> {
79 fn apply(
80 &self,
81 db: &'db dyn Database,
82 function: ConcreteFunctionWithBodyId<'db>,
83 lowered: &mut Lowered<'db>,
84 ) -> Maybe<()> {
85 debug!("Applying optimization: {self:?}");
86
87 match self {
88 OptimizationPhase::ApplyInlining { enable_const_folding } => {
89 apply_inlining(db, function, lowered, *enable_const_folding)?
90 }
91 OptimizationPhase::BranchInversion => branch_inversion(db, lowered),
92 OptimizationPhase::CancelOps => cancel_ops(lowered),
93 OptimizationPhase::ConstFolding => const_folding(db, function, lowered),
94 OptimizationPhase::Cse => cse(lowered),
95 OptimizationPhase::EarlyUnsafePanic => early_unsafe_panic(db, lowered),
96 OptimizationPhase::DedupBlocks => dedup_blocks(lowered),
97 OptimizationPhase::OptimizeMatches => optimize_matches(lowered),
98 OptimizationPhase::OptimizeRemappings => optimize_remappings(lowered),
99 OptimizationPhase::Reboxing => apply_reboxing(db, lowered)?,
100 OptimizationPhase::ReorderStatements => reorder_statements(db, lowered),
101 OptimizationPhase::ReorganizeBlocks => reorganize_blocks(lowered),
102 OptimizationPhase::ReturnOptimization => return_optimization(db, lowered),
103 OptimizationPhase::SplitStructs => split_structs(lowered),
104 OptimizationPhase::TrimUnreachable => trim_unreachable(db, lowered),
105 OptimizationPhase::LowerImplicits => lower_implicits(db, function, lowered),
106 OptimizationPhase::GasRedeposit => gas_redeposit(db, function, lowered),
107 OptimizationPhase::Validate => validate(lowered).unwrap_or_else(|err| {
108 panic!(
109 "Failed validation for function {}: {:?}",
110 function.full_path(db),
111 err.to_message()
112 )
113 }),
114 OptimizationPhase::SubStrategy { strategy, iterations } => {
115 for _ in 1..*iterations {
116 let before = lowered.clone();
117 strategy.apply(db, function, lowered)?;
118 if *lowered == before {
119 return Ok(());
120 }
121 }
122 strategy.apply(db, function, lowered)?
123 }
124 }
125 Ok(())
126 }
127}
128
129define_short_id!(OptimizationStrategyId, OptimizationStrategy<'db>);
130
131#[derive(Clone, Debug, Eq, Hash, PartialEq, salsa::Update, HeapSize)]
133pub struct OptimizationStrategy<'db>(pub Vec<OptimizationPhase<'db>>);
134
135impl<'db> ApplyOptimization<'db> for [OptimizationPhase<'db>] {
136 fn apply(
137 &self,
138 db: &'db dyn Database,
139 function: ConcreteFunctionWithBodyId<'db>,
140 lowered: &mut Lowered<'db>,
141 ) -> Maybe<()> {
142 for phase in self {
143 phase.apply(db, function, lowered)?;
144 }
145 Ok(())
146 }
147}
148
149impl<'db> ApplyOptimization<'db> for OptimizationStrategyId<'db> {
150 fn apply(
154 &self,
155 db: &'db dyn Database,
156 function: ConcreteFunctionWithBodyId<'db>,
157 lowered: &mut Lowered<'db>,
158 ) -> Maybe<()> {
159 self.long(db).0.apply(db, function, lowered)
160 }
161}
162
163#[salsa::tracked]
165pub fn baseline_optimization_strategy<'db>(db: &'db dyn Database) -> OptimizationStrategyId<'db> {
166 match db.optimizations() {
167 Optimizations::Enabled(_) => {
168 OptimizationStrategy(vec![
169 OptimizationPhase::ReorganizeBlocks,
171 OptimizationPhase::ApplyInlining { enable_const_folding: true },
172 OptimizationPhase::ReturnOptimization,
173 OptimizationPhase::ReorganizeBlocks,
174 OptimizationPhase::ReorderStatements,
175 OptimizationPhase::BranchInversion,
176 OptimizationPhase::CancelOps,
177 OptimizationPhase::ReorganizeBlocks,
179 OptimizationPhase::ConstFolding,
180 OptimizationPhase::OptimizeMatches,
181 OptimizationPhase::SplitStructs,
182 OptimizationPhase::ReorganizeBlocks,
183 OptimizationPhase::ReorderStatements,
184 OptimizationPhase::OptimizeMatches,
185 OptimizationPhase::ReorganizeBlocks,
186 OptimizationPhase::Reboxing,
187 OptimizationPhase::CancelOps,
188 OptimizationPhase::ReorganizeBlocks,
189 OptimizationPhase::Cse,
192 OptimizationPhase::DedupBlocks,
193 OptimizationPhase::ReturnOptimization,
195 OptimizationPhase::ReorderStatements,
196 OptimizationPhase::ReorganizeBlocks,
197 ])
198 }
199 Optimizations::Disabled => OptimizationStrategy(vec![OptimizationPhase::ApplyInlining {
200 enable_const_folding: false,
201 }]),
202 }
203 .intern(db)
204}
205
206#[salsa::tracked]
208pub fn final_optimization_strategy<'db>(db: &'db dyn Database) -> OptimizationStrategyId<'db> {
209 match db.optimizations() {
210 Optimizations::Enabled(_) => {
211 OptimizationStrategy(vec![
212 OptimizationPhase::GasRedeposit,
213 OptimizationPhase::EarlyUnsafePanic,
214 OptimizationPhase::TrimUnreachable,
217 OptimizationPhase::LowerImplicits,
218 OptimizationPhase::ReorganizeBlocks,
219 ])
220 }
221 Optimizations::Disabled => OptimizationStrategy(vec![
222 OptimizationPhase::LowerImplicits,
223 OptimizationPhase::ReorganizeBlocks,
224 ]),
225 }
226 .intern(db)
227}