Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement common subexpression elimination #550

Merged
merged 2 commits into from
Nov 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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),
)
LucasSte marked this conversation as resolved.
Show resolved Hide resolved
.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