Skip to content

Commit

Permalink
Implement common subexpression elimination
Browse files Browse the repository at this point in the history
Signed-off-by: Lucas Steuernagel <[email protected]>
  • Loading branch information
LucasSte authored and seanyoung committed Nov 12, 2021
1 parent 64cedb8 commit 8f19e1b
Show file tree
Hide file tree
Showing 17 changed files with 2,458 additions and 827 deletions.
56 changes: 56 additions & 0 deletions docs/optimizer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,59 @@ a allocation. For example:
This optimization pass can be disabled by running `solang --no-vector-to-slice`. You can see the difference between
having this optimization pass on by comparing the output of `solang --no-vector-to-slice --emit cfg foo.sol` with
`solang --emit cfg foo.sol`.

Unused Variable Elimination
___________________________

During the semantic analysis, Solang detects unused variables and raises warnings for them.
During codegen, we remove all assignments that have been made to this unused variable. There is an example below:

.. code-block:: javascript
contract test {
function test1(int a) public pure returns (int) {
int x = 5;
x++;
if (a > 0) {
x = 5;
}
a = (x=3) + a*4;
return a;
}
}
The variable 'x' will be removed from the function, as it has never been used. The removal won't affect any
expressions inside the function.


Common Subexpression Elimination
________________________________
Solang performs common subexpression elimination by doing two passes over the CFG (Control
Flow Graph). During the first one, it builds a graph to track existing expressions and detect repeated ones.
During the second pass, it replaces the repeated expressions by a temporary variable, which assumes the value
of the expression. To disable this feature, use `solang --no-cse`.

Check out the example below. It contains multiple common subexpressions:

.. code-block:: javascript
contract {
function csePass(int a, int b) {
int x = a*b-5;
if (x > 0) {
x = a*b-19;
} else {
x = a*b*a;
}
return x+a*b;
}
}
The expression `a*b` is repeated throughout the function and will be saved to a temporary variable.
This temporary will be placed wherever there is an expression `a*b`. You can see the pass in action when you compile
this contract and check the CFG, using `solang --emit cfg`.
9 changes: 8 additions & 1 deletion src/bin/solang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,17 @@ fn main() {
.long("no-vector-to-slice")
.display_order(4),
)
.arg(
Arg::with_name("COMMONSUBEXPRESSIONELIMINATION")
.help("Disable common subexpression elimination")
.long("no-cse")
.display_order(5),
)
.arg(
Arg::with_name("MATHOVERFLOW")
.help("Enable math overflow checking")
.long("math-overflow")
.display_order(5),
.display_order(6),
)
.arg(
Arg::with_name("LANGUAGESERVER")
Expand Down Expand Up @@ -307,6 +313,7 @@ fn main() {
strength_reduce: !matches.is_present("STRENGTHREDUCE"),
constant_folding: !matches.is_present("CONSTANTFOLDING"),
vector_to_slice: !matches.is_present("VECTORTOSLICE"),
common_subexpression_elimination: !matches.is_present("COMMONEXPRESSIONELIMINATION"),
math_overflow_check,
opt_level,
};
Expand Down
Loading

0 comments on commit 8f19e1b

Please sign in to comment.