cairo_lang_lowering/optimizations/
strategy.rs

1use cairo_lang_diagnostics::Maybe;
2use cairo_lang_utils::{Intern, LookupIntern, define_short_id};
3
4use super::gas_redeposit::gas_redeposit;
5use super::validate::validate;
6use crate::FlatLowered;
7use crate::db::LoweringGroup;
8use crate::ids::ConcreteFunctionWithBodyId;
9use crate::implicits::lower_implicits;
10use crate::inline::apply_inlining;
11use crate::optimizations::branch_inversion::branch_inversion;
12use crate::optimizations::cancel_ops::cancel_ops;
13use crate::optimizations::const_folding::const_folding;
14use crate::optimizations::match_optimizer::optimize_matches;
15use crate::optimizations::remappings::optimize_remappings;
16use crate::optimizations::reorder_statements::reorder_statements;
17use crate::optimizations::return_optimization::return_optimization;
18use crate::optimizations::split_structs::split_structs;
19use crate::reorganize_blocks::reorganize_blocks;
20
21/// Enum of the optimization phases that can be used in a strategy.
22#[derive(Clone, Debug, Eq, Hash, PartialEq)]
23pub enum OptimizationPhase {
24    ApplyInlining,
25    BranchInversion,
26    CancelOps,
27    ConstFolding,
28    OptimizeMatches,
29    OptimizeRemappings,
30    ReorderStatements,
31    ReorganizeBlocks,
32    ReturnOptimization,
33    SplitStructs,
34    GasRedeposit,
35    /// The following is not really an optimization but we want to apply optimizations before and
36    /// after it, so it is convenient to treat it as an optimization.
37    LowerImplicits,
38    /// A validation phase that checks the lowering is valid. Used for debugging purposes.
39    Validate,
40}
41
42impl OptimizationPhase {
43    /// Applies the optimization phase to the lowering.
44    ///
45    /// Assumes `lowered` is a lowering of `function`.
46    pub fn apply(
47        self,
48        db: &dyn LoweringGroup,
49        function: ConcreteFunctionWithBodyId,
50        lowered: &mut FlatLowered,
51    ) -> Maybe<()> {
52        match self {
53            OptimizationPhase::ApplyInlining => apply_inlining(db, function, lowered)?,
54            OptimizationPhase::BranchInversion => branch_inversion(db, lowered),
55            OptimizationPhase::CancelOps => cancel_ops(lowered),
56            OptimizationPhase::ConstFolding => const_folding(db, lowered),
57            OptimizationPhase::OptimizeMatches => optimize_matches(lowered),
58            OptimizationPhase::OptimizeRemappings => optimize_remappings(lowered),
59            OptimizationPhase::ReorderStatements => reorder_statements(db, lowered),
60            OptimizationPhase::ReorganizeBlocks => reorganize_blocks(lowered),
61            OptimizationPhase::ReturnOptimization => return_optimization(db, lowered),
62            OptimizationPhase::SplitStructs => split_structs(lowered),
63            OptimizationPhase::LowerImplicits => lower_implicits(db, function, lowered),
64            OptimizationPhase::GasRedeposit => gas_redeposit(db, function, lowered),
65            OptimizationPhase::Validate => validate(lowered)
66                .unwrap_or_else(|err| panic!("Failed validation: {:?}", err.to_message())),
67        }
68        Ok(())
69    }
70}
71
72define_short_id!(
73    OptimizationStrategyId,
74    OptimizationStrategy,
75    LoweringGroup,
76    lookup_intern_strategy,
77    intern_strategy
78);
79
80/// A strategy is a sequence of optimization phases.
81#[derive(Clone, Debug, Eq, Hash, PartialEq)]
82pub struct OptimizationStrategy(pub Vec<OptimizationPhase>);
83
84impl OptimizationStrategyId {
85    /// Applies the optimization strategy phase to the lowering.
86    ///
87    /// Assumes `lowered` is a lowering of `function`.
88    pub fn apply_strategy(
89        self,
90        db: &dyn LoweringGroup,
91        function: ConcreteFunctionWithBodyId,
92        lowered: &mut FlatLowered,
93    ) -> Maybe<()> {
94        for phase in self.lookup_intern(db).0 {
95            phase.apply(db, function, lowered)?;
96        }
97
98        Ok(())
99    }
100}
101
102/// Query implementation of [crate::db::LoweringGroup::baseline_optimization_strategy].
103pub fn baseline_optimization_strategy(db: &dyn LoweringGroup) -> OptimizationStrategyId {
104    OptimizationStrategy(vec![
105        OptimizationPhase::ApplyInlining,
106        OptimizationPhase::ReturnOptimization,
107        OptimizationPhase::ReorganizeBlocks,
108        // The call to `reorder_statements` before and after `branch_inversion` is intentional.
109        // See description of `branch_inversion` for more details.
110        OptimizationPhase::ReorderStatements,
111        OptimizationPhase::BranchInversion,
112        OptimizationPhase::ReorderStatements,
113        OptimizationPhase::CancelOps,
114        OptimizationPhase::ConstFolding,
115        OptimizationPhase::OptimizeMatches,
116        OptimizationPhase::SplitStructs,
117        OptimizationPhase::ReorganizeBlocks,
118        OptimizationPhase::ReorderStatements,
119        OptimizationPhase::OptimizeMatches,
120        OptimizationPhase::ReorganizeBlocks,
121        OptimizationPhase::CancelOps,
122        OptimizationPhase::ReorderStatements,
123        OptimizationPhase::ReorganizeBlocks,
124    ])
125    .intern(db)
126}
127
128/// Query implementation of [crate::db::LoweringGroup::final_optimization_strategy].
129pub fn final_optimization_strategy(db: &dyn LoweringGroup) -> OptimizationStrategyId {
130    OptimizationStrategy(vec![
131        OptimizationPhase::GasRedeposit,
132        OptimizationPhase::LowerImplicits,
133        OptimizationPhase::ReorganizeBlocks,
134        OptimizationPhase::CancelOps,
135        OptimizationPhase::ReorderStatements,
136        OptimizationPhase::ReorganizeBlocks,
137    ])
138    .intern(db)
139}