diff --git a/libyul/optimiser/CommonSubexpressionEliminator.h b/libyul/optimiser/CommonSubexpressionEliminator.h index 9f416d9fd..6499e6db3 100644 --- a/libyul/optimiser/CommonSubexpressionEliminator.h +++ b/libyul/optimiser/CommonSubexpressionEliminator.h @@ -32,7 +32,7 @@ struct Dialect; * Optimisation stage that replaces expressions known to be the current value of a variable * in scope by a reference to that variable. * - * Prerequisite: Disambiguator + * Prerequisite: Disambiguator, ForLoopInitRewriter. */ class CommonSubexpressionEliminator: public DataFlowAnalyzer { diff --git a/libyul/optimiser/DataFlowAnalyzer.cpp b/libyul/optimiser/DataFlowAnalyzer.cpp index 5a812151d..86011ffd1 100644 --- a/libyul/optimiser/DataFlowAnalyzer.cpp +++ b/libyul/optimiser/DataFlowAnalyzer.cpp @@ -112,10 +112,9 @@ void DataFlowAnalyzer::operator()(FunctionDefinition& _fun) void DataFlowAnalyzer::operator()(ForLoop& _for) { - // Special scope handling of the pre block. - pushScope(false); - for (auto& statement: _for.pre.statements) - visit(statement); + // If the pre block was not empty, + // we would have to deal with more complicated scoping rules. + assertThrow(_for.pre.statements.empty(), OptimizerException, ""); AssignmentsSinceContinue assignmentsSinceCont; assignmentsSinceCont(_for.body); @@ -130,8 +129,6 @@ void DataFlowAnalyzer::operator()(ForLoop& _for) clearValues(assignmentsSinceCont.names()); (*this)(_for.post); clearValues(assignments.names()); - - popScope(); } void DataFlowAnalyzer::operator()(Block& _block) diff --git a/libyul/optimiser/DataFlowAnalyzer.h b/libyul/optimiser/DataFlowAnalyzer.h index 5fb5db958..100a38665 100644 --- a/libyul/optimiser/DataFlowAnalyzer.h +++ b/libyul/optimiser/DataFlowAnalyzer.h @@ -39,7 +39,7 @@ struct Dialect; * * A special zero constant expression is used for the default value of variables. * - * Prerequisite: Disambiguator + * Prerequisite: Disambiguator, ForLoopInitRewriter. */ class DataFlowAnalyzer: public ASTModifier { diff --git a/libyul/optimiser/ExpressionSimplifier.h b/libyul/optimiser/ExpressionSimplifier.h index bf62fb307..1f371a8fc 100644 --- a/libyul/optimiser/ExpressionSimplifier.h +++ b/libyul/optimiser/ExpressionSimplifier.h @@ -36,7 +36,7 @@ struct Dialect; * It tracks the current values of variables using the DataFlowAnalyzer * and takes them into account for replacements. * - * Prerequisite: Disambiguator. + * Prerequisite: Disambiguator, ForLoopInitRewriter. */ class ExpressionSimplifier: public DataFlowAnalyzer { diff --git a/libyul/optimiser/RedundantAssignEliminator.cpp b/libyul/optimiser/RedundantAssignEliminator.cpp index b9740ad89..350999645 100644 --- a/libyul/optimiser/RedundantAssignEliminator.cpp +++ b/libyul/optimiser/RedundantAssignEliminator.cpp @@ -118,12 +118,9 @@ void RedundantAssignEliminator::operator()(ForLoop const& _forLoop) ForLoopInfo outerForLoopInfo; swap(outerForLoopInfo, m_forLoopInfo); - set outerDeclaredVariables; - swap(m_declaredVariables, outerDeclaredVariables); - - // We need to visit the statements directly because of the - // scoping rules. - walkVector(_forLoop.pre.statements); + // If the pre block was not empty, + // we would have to deal with more complicated scoping rules. + assertThrow(_forLoop.pre.statements.empty(), OptimizerException, ""); // We just run the loop twice to account for the // back edge. @@ -156,10 +153,6 @@ void RedundantAssignEliminator::operator()(ForLoop const& _forLoop) merge(m_assignments, move(m_forLoopInfo.pendingBreakStmts)); m_forLoopInfo.pendingBreakStmts.clear(); - for (auto const& var: m_declaredVariables) - finalize(var, State::Unused); - swap(m_declaredVariables, outerDeclaredVariables); - // Restore potential outer for-loop states. swap(m_forLoopInfo, outerForLoopInfo); } diff --git a/libyul/optimiser/RedundantAssignEliminator.h b/libyul/optimiser/RedundantAssignEliminator.h index 3165d0335..544563c11 100644 --- a/libyul/optimiser/RedundantAssignEliminator.h +++ b/libyul/optimiser/RedundantAssignEliminator.h @@ -95,7 +95,7 @@ struct Dialect; * This step is usually run right after the SSA transform to complete * the generation of the pseudo-SSA. * - * Prerequisite: Disambiguator. + * Prerequisite: Disambiguator, ForLoopInitRewriter. */ class RedundantAssignEliminator: public ASTWalker { diff --git a/libyul/optimiser/Rematerialiser.h b/libyul/optimiser/Rematerialiser.h index b568b5dbd..6871cdaa9 100644 --- a/libyul/optimiser/Rematerialiser.h +++ b/libyul/optimiser/Rematerialiser.h @@ -33,7 +33,7 @@ namespace yul * - the variable is referenced at most 5 times and the value is rather cheap * ("cost" of at most 1 like a constant up to 0xff) * - * Prerequisite: Disambiguator + * Prerequisite: Disambiguator, ForLoopInitRewriter. */ class Rematerialiser: public DataFlowAnalyzer { diff --git a/libyul/optimiser/StructuralSimplifier.h b/libyul/optimiser/StructuralSimplifier.h index 222324700..a4c90a7d3 100644 --- a/libyul/optimiser/StructuralSimplifier.h +++ b/libyul/optimiser/StructuralSimplifier.h @@ -36,7 +36,7 @@ namespace yul * - replace switch with const expr with matching case body * - replace for with false condition by its initialization part * - * Prerequisites: Disambiguator + * Prerequisite: Disambiguator, ForLoopInitRewriter. * * Important: Can only be used on EVM code. */ diff --git a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_for.yul b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_for.yul index ef366e529..721f78add 100644 --- a/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_for.yul +++ b/test/libyul/yulOptimizerTests/commonSubexpressionEliminator/branches_for.yul @@ -1,5 +1,6 @@ { - let a := 1 let b := codesize() + let a := 1 + let b := codesize() for { } lt(1, codesize()) { mstore(1, codesize()) a := add(a, codesize()) } { mstore(1, codesize()) } diff --git a/test/libyul/yulOptimizerTests/expressionSimplifier/inside_for.yul b/test/libyul/yulOptimizerTests/expressionSimplifier/inside_for.yul index dfb420858..336778599 100644 --- a/test/libyul/yulOptimizerTests/expressionSimplifier/inside_for.yul +++ b/test/libyul/yulOptimizerTests/expressionSimplifier/inside_for.yul @@ -1,12 +1,13 @@ { - for { let a := 10 } iszero(eq(a, 0)) { a := add(a, 1) } {} + let a := 10 + for { } iszero(eq(a, 0)) { a := add(a, 1) } {} } // ==== // step: expressionSimplifier // ---- // { +// let a := 10 // for { -// let a := 10 // } // iszero(iszero(a)) // { diff --git a/test/libyul/yulOptimizerTests/expressionSplitter/control_flow.yul b/test/libyul/yulOptimizerTests/expressionSplitter/control_flow.yul index 79791eabf..d7a21da12 100644 --- a/test/libyul/yulOptimizerTests/expressionSplitter/control_flow.yul +++ b/test/libyul/yulOptimizerTests/expressionSplitter/control_flow.yul @@ -38,4 +38,4 @@ // sstore(b, _12) // } // } -// } +// } \ No newline at end of file diff --git a/test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul b/test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul index 07c7c40d7..7f146f5e5 100644 --- a/test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul +++ b/test/libyul/yulOptimizerTests/fullInliner/not_inside_for.yul @@ -1,5 +1,6 @@ { - for { let x := f(0) } f(x) { x := f(x) } + let x := f(0) + for { } f(x) { x := f(x) } { let t := f(x) } @@ -13,12 +14,12 @@ // ---- // { // { +// let a_3 := 0 +// let r_4 := 0 +// sstore(a_3, 0) +// r_4 := a_3 +// let x := r_4 // for { -// let a_3 := 0 -// let r_4 := 0 -// sstore(a_3, 0) -// r_4 := a_3 -// let x := r_4 // } // f(x) // { diff --git a/test/libyul/yulOptimizerTests/fullSimplify/inside_for.yul b/test/libyul/yulOptimizerTests/fullSimplify/inside_for.yul index a2365cf0d..972c9f267 100644 --- a/test/libyul/yulOptimizerTests/fullSimplify/inside_for.yul +++ b/test/libyul/yulOptimizerTests/fullSimplify/inside_for.yul @@ -1,6 +1,7 @@ { let x := calldataload(3) - for { let a := 10 } iszero(eq(a, sub(x, calldataload(3)))) { a := add(a, 1) } {} + let a := 10 + for { } iszero(eq(a, sub(x, calldataload(3)))) { a := add(a, 1) } {} } // ==== // step: fullSimplify diff --git a/test/libyul/yulOptimizerTests/redundantAssignEliminator/for.yul b/test/libyul/yulOptimizerTests/redundantAssignEliminator/for.yul index d1df2d9a9..ecddd254c 100644 --- a/test/libyul/yulOptimizerTests/redundantAssignEliminator/for.yul +++ b/test/libyul/yulOptimizerTests/redundantAssignEliminator/for.yul @@ -1,9 +1,7 @@ { + let a := 2 + a := 3 for { - let a := 2 - // Should not be removed, even though you might think - // it goes out of scope - a := 3 } a { a := add(a, 1) } { a := 7 @@ -13,9 +11,9 @@ // step: redundantAssignEliminator // ---- // { +// let a := 2 +// a := 3 // for { -// let a := 2 -// a := 3 // } // a // { diff --git a/test/libyul/yulOptimizerTests/rematerialiser/branches_for1.yul b/test/libyul/yulOptimizerTests/rematerialiser/branches_for1.yul index 4117086d7..bd24b0903 100644 --- a/test/libyul/yulOptimizerTests/rematerialiser/branches_for1.yul +++ b/test/libyul/yulOptimizerTests/rematerialiser/branches_for1.yul @@ -1,6 +1,7 @@ { let a := caller() - for { pop(a) } a { pop(a) } { + pop(a) + for { } a { pop(a) } { pop(a) } } @@ -9,8 +10,8 @@ // ---- // { // let a := caller() +// pop(caller()) // for { -// pop(caller()) // } // caller() // { diff --git a/test/libyul/yulOptimizerTests/rematerialiser/branches_for2.yul b/test/libyul/yulOptimizerTests/rematerialiser/branches_for2.yul index 79a318b04..a7325ecef 100644 --- a/test/libyul/yulOptimizerTests/rematerialiser/branches_for2.yul +++ b/test/libyul/yulOptimizerTests/rematerialiser/branches_for2.yul @@ -1,6 +1,7 @@ { let a := caller() - for { pop(a) } a { pop(a) } { + pop(a) + for { } a { pop(a) } { a := address() let c := a } @@ -11,8 +12,8 @@ // ---- // { // let a := caller() +// pop(caller()) // for { -// pop(caller()) // } // a // { diff --git a/test/libyul/yulOptimizerTests/rematerialiser/branches_for_declared_in_init1.yul b/test/libyul/yulOptimizerTests/rematerialiser/branches_for_declared_in_init1.yul deleted file mode 100644 index a24341518..000000000 --- a/test/libyul/yulOptimizerTests/rematerialiser/branches_for_declared_in_init1.yul +++ /dev/null @@ -1,24 +0,0 @@ -{ - let b := 0 - for { let a := caller() pop(a) } a { pop(a) } { - b := 1 pop(a) - } -} -// ==== -// step: rematerialiser -// ---- -// { -// let b := 0 -// for { -// let a := caller() -// pop(caller()) -// } -// caller() -// { -// pop(caller()) -// } -// { -// b := 1 -// pop(caller()) -// } -// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/branches_for_declared_in_init2.yul b/test/libyul/yulOptimizerTests/rematerialiser/branches_for_declared_in_init2.yul deleted file mode 100644 index 27fe1b238..000000000 --- a/test/libyul/yulOptimizerTests/rematerialiser/branches_for_declared_in_init2.yul +++ /dev/null @@ -1,25 +0,0 @@ -{ - let b := 0 - for { let a := caller() pop(a) } lt(a, 0) { pop(a) a := add(a, 3) } { - b := 1 pop(a) - } -} -// ==== -// step: rematerialiser -// ---- -// { -// let b := 0 -// for { -// let a := caller() -// pop(caller()) -// } -// lt(a, 0) -// { -// pop(a) -// a := add(a, 3) -// } -// { -// b := 1 -// pop(a) -// } -// } diff --git a/test/libyul/yulOptimizerTests/rematerialiser/for_break.yul b/test/libyul/yulOptimizerTests/rematerialiser/for_break.yul index a86a35f9b..b9ec6f2a2 100644 --- a/test/libyul/yulOptimizerTests/rematerialiser/for_break.yul +++ b/test/libyul/yulOptimizerTests/rematerialiser/for_break.yul @@ -1,7 +1,8 @@ { let a let b - for {let i := 0} lt(i, 10) {i := add(a, b)} { + let i := 0 + for {} lt(i, 10) {i := add(a, b)} { a := origin() b := origin() b := caller() @@ -18,8 +19,8 @@ // { // let a // let b +// let i := 0 // for { -// let i := 0 // } // lt(i, 10) // { diff --git a/test/libyul/yulOptimizerTests/rematerialiser/for_continue.yul b/test/libyul/yulOptimizerTests/rematerialiser/for_continue.yul index 4fd69a32b..baf4c09e0 100644 --- a/test/libyul/yulOptimizerTests/rematerialiser/for_continue.yul +++ b/test/libyul/yulOptimizerTests/rematerialiser/for_continue.yul @@ -1,7 +1,8 @@ { let a let b - for { let i := 0 } + let i := 0 + for { } lt(i, 10) { i := add(a, b) } // `b` is always known to be caller() but `a` may be origin() or caller(). { @@ -20,8 +21,8 @@ // { // let a // let b +// let i := 0 // for { -// let i := 0 // } // lt(i, 10) // { diff --git a/test/libyul/yulOptimizerTests/rematerialiser/for_continue_2.yul b/test/libyul/yulOptimizerTests/rematerialiser/for_continue_2.yul index 7ad885476..6e946660c 100644 --- a/test/libyul/yulOptimizerTests/rematerialiser/for_continue_2.yul +++ b/test/libyul/yulOptimizerTests/rematerialiser/for_continue_2.yul @@ -2,7 +2,8 @@ let a let b let c - for { let i := 0 } + let i := 0 + for { } lt(i, 10) { i := add(add(a, b), c) } // `b` is always known to be caller() but `a` and `c` may be origin() or caller(). { @@ -26,8 +27,8 @@ // let a // let b // let c +// let i := 0 // for { -// let i := 0 // } // lt(i, 10) // { diff --git a/test/libyul/yulOptimizerTests/rematerialiser/for_continue_with_assignment_in_post.yul b/test/libyul/yulOptimizerTests/rematerialiser/for_continue_with_assignment_in_post.yul index 38424eb0a..325dd2284 100644 --- a/test/libyul/yulOptimizerTests/rematerialiser/for_continue_with_assignment_in_post.yul +++ b/test/libyul/yulOptimizerTests/rematerialiser/for_continue_with_assignment_in_post.yul @@ -2,10 +2,10 @@ let a let b let c + let i := 0 + b := origin() + c := origin() for { - let i := 0 - b := origin() - c := origin() } lt(i, 10) { @@ -30,10 +30,10 @@ // let a // let b // let c +// let i := 0 +// b := origin() +// c := origin() // for { -// let i := 0 -// b := origin() -// c := origin() // } // lt(i, 10) // { diff --git a/test/libyul/yulOptimizerTests/ssaAndBack/for_loop.yul b/test/libyul/yulOptimizerTests/ssaAndBack/for_loop.yul index 3fdf2a4c3..99d3d56e5 100644 --- a/test/libyul/yulOptimizerTests/ssaAndBack/for_loop.yul +++ b/test/libyul/yulOptimizerTests/ssaAndBack/for_loop.yul @@ -1,7 +1,7 @@ { + let a := mload(0) + let b := mload(1) for { - let a := mload(0) - let b := mload(1) } lt(mload(a),mload(b)) { @@ -19,9 +19,9 @@ // step: ssaAndBack // ---- // { +// let a := mload(0) +// let b := mload(1) // for { -// let a := mload(0) -// let b := mload(1) // } // lt(mload(a), mload(b)) // { diff --git a/test/libyul/yulOptimizerTests/ssaPlusCleanup/control_structures.yul b/test/libyul/yulOptimizerTests/ssaPlusCleanup/control_structures.yul index c1df9b032..e4f06a781 100644 --- a/test/libyul/yulOptimizerTests/ssaPlusCleanup/control_structures.yul +++ b/test/libyul/yulOptimizerTests/ssaPlusCleanup/control_structures.yul @@ -4,7 +4,8 @@ mstore(to, length) from := add(from, 0x20) to := add(to, 0x20) - for { let x := 1 } lt(x, length) { x := add(x, 0x20) } { + let x := 1 + for { } lt(x, length) { x := add(x, 0x20) } { mstore(add(to, x), mload(add(from, x))) } } @@ -20,9 +21,9 @@ // mstore(to, length_1) // let from_2 := add(from, 0x20) // let to_3 := add(to, 0x20) +// let x_4 := 1 +// let x := x_4 // for { -// let x_4 := 1 -// let x := x_4 // } // lt(x, length_1) // {