cairo_lang_lowering/optimizations/
strategy.rs1use cairo_lang_diagnostics::Maybe;
2use cairo_lang_utils::{Intern, define_short_id};
3use salsa::Database;
4
5use super::cse::cse;
6use super::dedup_blocks::dedup_blocks;
7use super::early_unsafe_panic::early_unsafe_panic;
8use super::gas_redeposit::gas_redeposit;
9use super::trim_unreachable::trim_unreachable;
10use super::validate::validate;
11use crate::Lowered;
12use crate::ids::ConcreteFunctionWithBodyId;
13use crate::implicits::lower_implicits;
14use crate::inline::apply_inlining;
15use crate::optimizations::branch_inversion::branch_inversion;
16use crate::optimizations::cancel_ops::cancel_ops;
17use crate::optimizations::const_folding::const_folding;
18use crate::optimizations::match_optimizer::optimize_matches;
19use crate::optimizations::remappings::optimize_remappings;
20use crate::optimizations::reorder_statements::reorder_statements;
21use crate::optimizations::return_optimization::return_optimization;
22use crate::optimizations::split_structs::split_structs;
23use crate::reorganize_blocks::reorganize_blocks;
24
25#[derive(Clone, Debug, Eq, Hash, PartialEq)]
27pub enum OptimizationPhase<'db> {
28 ApplyInlining {
29 enable_const_folding: bool,
30 },
31 BranchInversion,
32 CancelOps,
33 ConstFolding,
34 Cse,
35 DedupBlocks,
36 EarlyUnsafePanic,
37 OptimizeMatches,
38 OptimizeRemappings,
39 ReorderStatements,
40 ReorganizeBlocks,
41 ReturnOptimization,
42 SplitStructs,
43 TrimUnreachable,
44 GasRedeposit,
45 LowerImplicits,
48 Validate,
50 SubStrategy {
53 strategy: OptimizationStrategyId<'db>,
55 iterations: usize,
57 },
58}
59
60impl<'db> OptimizationPhase<'db> {
61 pub fn apply(
65 self,
66 db: &'db dyn Database,
67 function: ConcreteFunctionWithBodyId<'db>,
68 lowered: &mut Lowered<'db>,
69 ) -> Maybe<()> {
70 match self {
71 OptimizationPhase::ApplyInlining { enable_const_folding } => {
72 apply_inlining(db, function, lowered, enable_const_folding)?
73 }
74 OptimizationPhase::BranchInversion => branch_inversion(db, lowered),
75 OptimizationPhase::CancelOps => cancel_ops(lowered),
76 OptimizationPhase::ConstFolding => const_folding(db, function, lowered),
77 OptimizationPhase::Cse => cse(lowered),
78 OptimizationPhase::EarlyUnsafePanic => early_unsafe_panic(db, lowered),
79 OptimizationPhase::DedupBlocks => dedup_blocks(lowered),
80 OptimizationPhase::OptimizeMatches => optimize_matches(lowered),
81 OptimizationPhase::OptimizeRemappings => optimize_remappings(lowered),
82 OptimizationPhase::ReorderStatements => reorder_statements(db, lowered),
83 OptimizationPhase::ReorganizeBlocks => reorganize_blocks(lowered),
84 OptimizationPhase::ReturnOptimization => return_optimization(db, lowered),
85 OptimizationPhase::SplitStructs => split_structs(lowered),
86 OptimizationPhase::TrimUnreachable => trim_unreachable(db, lowered),
87 OptimizationPhase::LowerImplicits => lower_implicits(db, function, lowered),
88 OptimizationPhase::GasRedeposit => gas_redeposit(db, function, lowered),
89 OptimizationPhase::Validate => validate(lowered).unwrap_or_else(|err| {
90 panic!(
91 "Failed validation for function {}: {:?}",
92 function.full_path(db),
93 err.to_message()
94 )
95 }),
96 OptimizationPhase::SubStrategy { strategy, iterations } => {
97 for _ in 1..iterations {
98 let before = lowered.clone();
99 strategy.apply_strategy(db, function, lowered)?;
100 if *lowered == before {
101 return Ok(());
102 }
103 }
104 strategy.apply_strategy(db, function, lowered)?
105 }
106 }
107 Ok(())
108 }
109}
110
111define_short_id!(OptimizationStrategyId, OptimizationStrategy<'db>);
112
113#[derive(Clone, Debug, Eq, Hash, PartialEq)]
115pub struct OptimizationStrategy<'db>(pub Vec<OptimizationPhase<'db>>);
116
117impl<'db> OptimizationStrategyId<'db> {
118 pub fn apply_strategy(
122 self,
123 db: &'db dyn Database,
124 function: ConcreteFunctionWithBodyId<'db>,
125 lowered: &mut Lowered<'db>,
126 ) -> Maybe<()> {
127 for phase in self.long(db).0.clone() {
128 phase.apply(db, function, lowered)?;
129 }
130
131 Ok(())
132 }
133}
134
135#[salsa::tracked]
137pub fn baseline_optimization_strategy<'db>(db: &'db dyn Database) -> OptimizationStrategyId<'db> {
138 OptimizationStrategy(vec![
139 OptimizationPhase::ReorganizeBlocks,
141 OptimizationPhase::ApplyInlining { enable_const_folding: true },
142 OptimizationPhase::ReturnOptimization,
143 OptimizationPhase::ReorganizeBlocks,
144 OptimizationPhase::ReorderStatements,
145 OptimizationPhase::BranchInversion,
146 OptimizationPhase::CancelOps,
147 OptimizationPhase::ReorganizeBlocks,
149 OptimizationPhase::ConstFolding,
150 OptimizationPhase::OptimizeMatches,
151 OptimizationPhase::SplitStructs,
152 OptimizationPhase::ReorganizeBlocks,
153 OptimizationPhase::ReorderStatements,
154 OptimizationPhase::OptimizeMatches,
155 OptimizationPhase::ReorganizeBlocks,
156 OptimizationPhase::CancelOps,
157 OptimizationPhase::ReorganizeBlocks,
158 OptimizationPhase::Cse,
160 OptimizationPhase::DedupBlocks,
161 OptimizationPhase::ReturnOptimization,
163 OptimizationPhase::ReorderStatements,
164 OptimizationPhase::ReorganizeBlocks,
165 ])
166 .intern(db)
167}
168
169#[salsa::tracked]
171pub fn final_optimization_strategy<'db>(db: &'db dyn Database) -> OptimizationStrategyId<'db> {
172 OptimizationStrategy(vec![
173 OptimizationPhase::GasRedeposit,
174 OptimizationPhase::EarlyUnsafePanic,
175 OptimizationPhase::TrimUnreachable,
178 OptimizationPhase::LowerImplicits,
179 OptimizationPhase::ReorganizeBlocks,
180 ])
181 .intern(db)
182}