leo_passes/common_subexpression_elimination/mod.rs
1// Copyright (C) 2019-2025 Provable Inc.
2// This file is part of the Leo library.
3
4// The Leo library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// The Leo library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
16
17//! The common subexpression elimination pass traverses the AST and removes
18//! duplicate definitions.
19//!
20//! That is, this code:
21//! ```leo
22//! function main(val: field) -> field {
23//! let x = val + 1field;
24//! let y = val + 1field;
25//! let z = x + y;
26//! return z;
27//! }
28//! ```
29//!
30//! Will be transformed to something like this:
31//! ```leo
32//! function main(val: field) -> field {
33//! let x = val + 1field;
34//! let z = x + x;
35//! return z;
36//! }
37//! ```
38//!
39//! The pass expects flattening and destructuring to have already been run, and
40//! for the code to be in SSA form. Given that there is little flow control
41//! at this point in the compiler, there's no need for any kind of data flow analysis.
42
43use crate::Pass;
44
45use leo_ast::ProgramReconstructor as _;
46use leo_errors::Result;
47
48mod ast;
49
50mod program;
51
52mod visitor;
53use visitor::*;
54
55pub struct CommonSubexpressionEliminating;
56
57impl Pass for CommonSubexpressionEliminating {
58 type Input = ();
59 type Output = ();
60
61 const NAME: &str = "CommonSubexpressionEliminating";
62
63 fn do_pass(_input: Self::Input, state: &mut crate::CompilerState) -> Result<Self::Output> {
64 let mut ast = std::mem::take(&mut state.ast);
65 let mut visitor = CommonSubexpressionEliminatingVisitor { state, scopes: Default::default() };
66 ast.ast = visitor.reconstruct_program(ast.ast);
67 visitor.state.handler.last_err()?;
68 visitor.state.ast = ast;
69 Ok(())
70 }
71}