Merge pull request #6486 from nanspro/develop

No special treatment of pre blocks in loops
This commit is contained in:
chriseth 2019-04-17 10:45:43 +02:00 committed by GitHub
commit 34995d4e97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 60 additions and 111 deletions

View File

@ -32,7 +32,7 @@ struct Dialect;
* Optimisation stage that replaces expressions known to be the current value of a variable * Optimisation stage that replaces expressions known to be the current value of a variable
* in scope by a reference to that variable. * in scope by a reference to that variable.
* *
* Prerequisite: Disambiguator * Prerequisite: Disambiguator, ForLoopInitRewriter.
*/ */
class CommonSubexpressionEliminator: public DataFlowAnalyzer class CommonSubexpressionEliminator: public DataFlowAnalyzer
{ {

View File

@ -112,10 +112,9 @@ void DataFlowAnalyzer::operator()(FunctionDefinition& _fun)
void DataFlowAnalyzer::operator()(ForLoop& _for) void DataFlowAnalyzer::operator()(ForLoop& _for)
{ {
// Special scope handling of the pre block. // If the pre block was not empty,
pushScope(false); // we would have to deal with more complicated scoping rules.
for (auto& statement: _for.pre.statements) assertThrow(_for.pre.statements.empty(), OptimizerException, "");
visit(statement);
AssignmentsSinceContinue assignmentsSinceCont; AssignmentsSinceContinue assignmentsSinceCont;
assignmentsSinceCont(_for.body); assignmentsSinceCont(_for.body);
@ -130,8 +129,6 @@ void DataFlowAnalyzer::operator()(ForLoop& _for)
clearValues(assignmentsSinceCont.names()); clearValues(assignmentsSinceCont.names());
(*this)(_for.post); (*this)(_for.post);
clearValues(assignments.names()); clearValues(assignments.names());
popScope();
} }
void DataFlowAnalyzer::operator()(Block& _block) void DataFlowAnalyzer::operator()(Block& _block)

View File

@ -39,7 +39,7 @@ struct Dialect;
* *
* A special zero constant expression is used for the default value of variables. * A special zero constant expression is used for the default value of variables.
* *
* Prerequisite: Disambiguator * Prerequisite: Disambiguator, ForLoopInitRewriter.
*/ */
class DataFlowAnalyzer: public ASTModifier class DataFlowAnalyzer: public ASTModifier
{ {

View File

@ -36,7 +36,7 @@ struct Dialect;
* It tracks the current values of variables using the DataFlowAnalyzer * It tracks the current values of variables using the DataFlowAnalyzer
* and takes them into account for replacements. * and takes them into account for replacements.
* *
* Prerequisite: Disambiguator. * Prerequisite: Disambiguator, ForLoopInitRewriter.
*/ */
class ExpressionSimplifier: public DataFlowAnalyzer class ExpressionSimplifier: public DataFlowAnalyzer
{ {

View File

@ -118,12 +118,9 @@ void RedundantAssignEliminator::operator()(ForLoop const& _forLoop)
ForLoopInfo outerForLoopInfo; ForLoopInfo outerForLoopInfo;
swap(outerForLoopInfo, m_forLoopInfo); swap(outerForLoopInfo, m_forLoopInfo);
set<YulString> outerDeclaredVariables; // If the pre block was not empty,
swap(m_declaredVariables, outerDeclaredVariables); // we would have to deal with more complicated scoping rules.
assertThrow(_forLoop.pre.statements.empty(), OptimizerException, "");
// We need to visit the statements directly because of the
// scoping rules.
walkVector(_forLoop.pre.statements);
// We just run the loop twice to account for the // We just run the loop twice to account for the
// back edge. // back edge.
@ -156,10 +153,6 @@ void RedundantAssignEliminator::operator()(ForLoop const& _forLoop)
merge(m_assignments, move(m_forLoopInfo.pendingBreakStmts)); merge(m_assignments, move(m_forLoopInfo.pendingBreakStmts));
m_forLoopInfo.pendingBreakStmts.clear(); m_forLoopInfo.pendingBreakStmts.clear();
for (auto const& var: m_declaredVariables)
finalize(var, State::Unused);
swap(m_declaredVariables, outerDeclaredVariables);
// Restore potential outer for-loop states. // Restore potential outer for-loop states.
swap(m_forLoopInfo, outerForLoopInfo); swap(m_forLoopInfo, outerForLoopInfo);
} }

View File

@ -95,7 +95,7 @@ struct Dialect;
* This step is usually run right after the SSA transform to complete * This step is usually run right after the SSA transform to complete
* the generation of the pseudo-SSA. * the generation of the pseudo-SSA.
* *
* Prerequisite: Disambiguator. * Prerequisite: Disambiguator, ForLoopInitRewriter.
*/ */
class RedundantAssignEliminator: public ASTWalker class RedundantAssignEliminator: public ASTWalker
{ {

View File

@ -33,7 +33,7 @@ namespace yul
* - the variable is referenced at most 5 times and the value is rather cheap * - 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) * ("cost" of at most 1 like a constant up to 0xff)
* *
* Prerequisite: Disambiguator * Prerequisite: Disambiguator, ForLoopInitRewriter.
*/ */
class Rematerialiser: public DataFlowAnalyzer class Rematerialiser: public DataFlowAnalyzer
{ {

View File

@ -36,7 +36,7 @@ namespace yul
* - replace switch with const expr with matching case body * - replace switch with const expr with matching case body
* - replace for with false condition by its initialization part * - replace for with false condition by its initialization part
* *
* Prerequisites: Disambiguator * Prerequisite: Disambiguator, ForLoopInitRewriter.
* *
* Important: Can only be used on EVM code. * Important: Can only be used on EVM code.
*/ */

View File

@ -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()) } { for { } lt(1, codesize()) { mstore(1, codesize()) a := add(a, codesize()) } {
mstore(1, codesize()) mstore(1, codesize())
} }

View File

@ -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 // step: expressionSimplifier
// ---- // ----
// { // {
// for {
// let a := 10 // let a := 10
// for {
// } // }
// iszero(iszero(a)) // iszero(iszero(a))
// { // {

View File

@ -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) let t := f(x)
} }
@ -13,12 +14,12 @@
// ---- // ----
// { // {
// { // {
// for {
// let a_3 := 0 // let a_3 := 0
// let r_4 := 0 // let r_4 := 0
// sstore(a_3, 0) // sstore(a_3, 0)
// r_4 := a_3 // r_4 := a_3
// let x := r_4 // let x := r_4
// for {
// } // }
// f(x) // f(x)
// { // {

View File

@ -1,6 +1,7 @@
{ {
let x := calldataload(3) 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 // step: fullSimplify

View File

@ -1,9 +1,7 @@
{ {
for {
let a := 2 let a := 2
// Should not be removed, even though you might think
// it goes out of scope
a := 3 a := 3
for {
} a { a := add(a, 1) } } a { a := add(a, 1) }
{ {
a := 7 a := 7
@ -13,9 +11,9 @@
// step: redundantAssignEliminator // step: redundantAssignEliminator
// ---- // ----
// { // {
// for {
// let a := 2 // let a := 2
// a := 3 // a := 3
// for {
// } // }
// a // a
// { // {

View File

@ -1,6 +1,7 @@
{ {
let a := caller() let a := caller()
for { pop(a) } a { pop(a) } { pop(a)
for { } a { pop(a) } {
pop(a) pop(a)
} }
} }
@ -9,8 +10,8 @@
// ---- // ----
// { // {
// let a := caller() // let a := caller()
// for {
// pop(caller()) // pop(caller())
// for {
// } // }
// caller() // caller()
// { // {

View File

@ -1,6 +1,7 @@
{ {
let a := caller() let a := caller()
for { pop(a) } a { pop(a) } { pop(a)
for { } a { pop(a) } {
a := address() a := address()
let c := a let c := a
} }
@ -11,8 +12,8 @@
// ---- // ----
// { // {
// let a := caller() // let a := caller()
// for {
// pop(caller()) // pop(caller())
// for {
// } // }
// a // a
// { // {

View File

@ -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())
// }
// }

View File

@ -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)
// }
// }

View File

@ -1,7 +1,8 @@
{ {
let a let a
let b 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() a := origin()
b := origin() b := origin()
b := caller() b := caller()
@ -18,8 +19,8 @@
// { // {
// let a // let a
// let b // let b
// for {
// let i := 0 // let i := 0
// for {
// } // }
// lt(i, 10) // lt(i, 10)
// { // {

View File

@ -1,7 +1,8 @@
{ {
let a let a
let b let b
for { let i := 0 } let i := 0
for { }
lt(i, 10) lt(i, 10)
{ i := add(a, b) } // `b` is always known to be caller() but `a` may be origin() or caller(). { 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 a
// let b // let b
// for {
// let i := 0 // let i := 0
// for {
// } // }
// lt(i, 10) // lt(i, 10)
// { // {

View File

@ -2,7 +2,8 @@
let a let a
let b let b
let c let c
for { let i := 0 } let i := 0
for { }
lt(i, 10) 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(). { 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 a
// let b // let b
// let c // let c
// for {
// let i := 0 // let i := 0
// for {
// } // }
// lt(i, 10) // lt(i, 10)
// { // {

View File

@ -2,10 +2,10 @@
let a let a
let b let b
let c let c
for {
let i := 0 let i := 0
b := origin() b := origin()
c := origin() c := origin()
for {
} }
lt(i, 10) lt(i, 10)
{ {
@ -30,10 +30,10 @@
// let a // let a
// let b // let b
// let c // let c
// for {
// let i := 0 // let i := 0
// b := origin() // b := origin()
// c := origin() // c := origin()
// for {
// } // }
// lt(i, 10) // lt(i, 10)
// { // {

View File

@ -1,7 +1,7 @@
{ {
for {
let a := mload(0) let a := mload(0)
let b := mload(1) let b := mload(1)
for {
} }
lt(mload(a),mload(b)) lt(mload(a),mload(b))
{ {
@ -19,9 +19,9 @@
// step: ssaAndBack // step: ssaAndBack
// ---- // ----
// { // {
// for {
// let a := mload(0) // let a := mload(0)
// let b := mload(1) // let b := mload(1)
// for {
// } // }
// lt(mload(a), mload(b)) // lt(mload(a), mload(b))
// { // {

View File

@ -4,7 +4,8 @@
mstore(to, length) mstore(to, length)
from := add(from, 0x20) from := add(from, 0x20)
to := add(to, 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))) mstore(add(to, x), mload(add(from, x)))
} }
} }
@ -20,9 +21,9 @@
// mstore(to, length_1) // mstore(to, length_1)
// let from_2 := add(from, 0x20) // let from_2 := add(from, 0x20)
// let to_3 := add(to, 0x20) // let to_3 := add(to, 0x20)
// for {
// let x_4 := 1 // let x_4 := 1
// let x := x_4 // let x := x_4
// for {
// } // }
// lt(x, length_1) // lt(x, length_1)
// { // {