mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #6486 from nanspro/develop
No special treatment of pre blocks in loops
This commit is contained in:
commit
34995d4e97
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
@ -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())
|
||||||
}
|
}
|
||||||
|
@ -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))
|
||||||
// {
|
// {
|
||||||
|
@ -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)
|
||||||
// {
|
// {
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
// {
|
// {
|
||||||
|
@ -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()
|
||||||
// {
|
// {
|
||||||
|
@ -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
|
||||||
// {
|
// {
|
||||||
|
@ -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())
|
|
||||||
// }
|
|
||||||
// }
|
|
@ -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)
|
|
||||||
// }
|
|
||||||
// }
|
|
@ -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)
|
||||||
// {
|
// {
|
||||||
|
@ -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)
|
||||||
// {
|
// {
|
||||||
|
@ -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)
|
||||||
// {
|
// {
|
||||||
|
@ -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)
|
||||||
// {
|
// {
|
||||||
|
@ -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))
|
||||||
// {
|
// {
|
||||||
|
@ -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)
|
||||||
// {
|
// {
|
||||||
|
Loading…
Reference in New Issue
Block a user