diff --git a/Changelog.md b/Changelog.md index 7dcf1d3e9..cf05a948d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -25,6 +25,7 @@ Bugfixes: * TypeChecker: Fix internal error and disallow index access on contracts and libraries. * Yul: Properly detect name clashes with functions before their declaration. * Yul: Take builtin functions into account in the compilability checker. + * Yul Optimizer: Properly take reassignments to variables in sub-expressions into account when replacing in the ExpressionSimplifier. Build System: diff --git a/libyul/optimiser/ExpressionSimplifier.cpp b/libyul/optimiser/ExpressionSimplifier.cpp index b26e42458..213cac977 100644 --- a/libyul/optimiser/ExpressionSimplifier.cpp +++ b/libyul/optimiser/ExpressionSimplifier.cpp @@ -36,7 +36,7 @@ using namespace dev::solidity; void ExpressionSimplifier::visit(Expression& _expression) { ASTModifier::visit(_expression); - while (auto match = SimplificationRules::findFirstMatch(_expression, m_dialect, m_ssaValues)) + while (auto match = SimplificationRules::findFirstMatch(_expression, m_dialect, m_value)) { // Do not apply the rule if it removes non-constant parts of the expression. // TODO: The check could actually be less strict than "movable". @@ -53,7 +53,5 @@ void ExpressionSimplifier::visit(Expression& _expression) void ExpressionSimplifier::run(Dialect const& _dialect, Block& _ast) { - SSAValueTracker ssaValues; - ssaValues(_ast); - ExpressionSimplifier{_dialect, ssaValues.values()}(_ast); + ExpressionSimplifier{_dialect}(_ast); } diff --git a/libyul/optimiser/ExpressionSimplifier.h b/libyul/optimiser/ExpressionSimplifier.h index b1122e911..bf62fb307 100644 --- a/libyul/optimiser/ExpressionSimplifier.h +++ b/libyul/optimiser/ExpressionSimplifier.h @@ -22,7 +22,7 @@ #include -#include +#include namespace yul { @@ -33,9 +33,12 @@ struct Dialect; * The component will work best if the code is in SSA form, but * this is not required for correctness. * + * It tracks the current values of variables using the DataFlowAnalyzer + * and takes them into account for replacements. + * * Prerequisite: Disambiguator. */ -class ExpressionSimplifier: public ASTModifier +class ExpressionSimplifier: public DataFlowAnalyzer { public: using ASTModifier::operator(); @@ -43,12 +46,7 @@ public: static void run(Dialect const& _dialect, Block& _ast); private: - explicit ExpressionSimplifier(Dialect const& _dialect, std::map _ssaValues): - m_dialect(_dialect), m_ssaValues(std::move(_ssaValues)) - {} - - Dialect const& m_dialect; - std::map m_ssaValues; + explicit ExpressionSimplifier(Dialect const& _dialect): DataFlowAnalyzer(_dialect) {} }; } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/reassign.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/reassign.yul new file mode 100644 index 000000000..10d5dc67a --- /dev/null +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/reassign.yul @@ -0,0 +1,12 @@ +{ + let x := mload(0) + x := 0 + mstore(0, add(7, x)) +} +// ---- +// expressionSimplifier +// { +// let x := mload(0) +// x := 0 +// mstore(0, 7) +// } diff --git a/test/libyul/yulOptimizerTests/fullSuite/reuse_vars_bug_in_simplifier.yul b/test/libyul/yulOptimizerTests/fullSuite/reuse_vars_bug_in_simplifier.yul new file mode 100644 index 000000000..8136a4e9e --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSuite/reuse_vars_bug_in_simplifier.yul @@ -0,0 +1,16 @@ +{ + // This tests that a bug is fixed that was related to just taking + // values of SSA variables in account and not clearing them when + // a dependency was reassigned. + pop(foo()) + function foo() -> x_9 + { + x_9 := sub(1,sub(x_9,1)) + mstore(sub(1,div(sub(x_9,1),sub(1,sub(x_9,1)))), 1) + } +} +// ---- +// fullSuite +// { +// mstore(1, 1) +// }