Merge pull request #12262 from ethereum/functionGrouper

Keep canonical form of Yul during optimization.
This commit is contained in:
chriseth 2021-11-10 11:09:15 +01:00 committed by GitHub
commit f42e3c0bae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
169 changed files with 936 additions and 652 deletions

View File

@ -972,10 +972,13 @@ BlockFlattener
^^^^^^^^^^^^^^
This stage eliminates nested blocks by inserting the statement in the
inner block at the appropriate place in the outer block:
inner block at the appropriate place in the outer block. It depends on the
FunctionGrouper and does not flatten the outermost block to keep the form
produced by the FunctionGrouper.
.. code-block:: yul
{
{
let x := 2
{
@ -983,16 +986,19 @@ inner block at the appropriate place in the outer block:
mstore(x, y)
}
}
}
is transformed to
.. code-block:: yul
{
{
let x := 2
let y := 3
mstore(x, y)
}
}
As long as the code is disambiguated, this does not cause a problem because
the scopes of variables can only grow.

View File

@ -43,3 +43,15 @@ void BlockFlattener::operator()(Block& _block)
}
);
}
void BlockFlattener::run(OptimiserStepContext&, Block& _ast)
{
BlockFlattener flattener;
for (auto& statement: _ast.statements)
if (auto* block = get_if<Block>(&statement))
flattener(*block);
else if (auto* function = get_if<FunctionDefinition>(&statement))
flattener(function->body);
else
yulAssert(false, "BlockFlattener requires the FunctionGrouper.");
}

View File

@ -27,7 +27,7 @@ class BlockFlattener: public ASTModifier
{
public:
static constexpr char const* name{"BlockFlattener"};
static void run(OptimiserStepContext&, Block& _ast) { BlockFlattener{}(_ast); }
static void run(OptimiserStepContext&, Block& _ast);
using ASTModifier::operator();
void operator()(Block& _block) override;

View File

@ -18,6 +18,7 @@
#include <libyul/optimiser/CircularReferencesPruner.h>
#include <libyul/optimiser/CallGraphGenerator.h>
#include <libyul/optimiser/FunctionGrouper.h>
#include <libyul/optimiser/OptimizerUtilities.h>
#include <libyul/AST.h>
@ -29,6 +30,7 @@ using namespace solidity::yul;
void CircularReferencesPruner::run(OptimiserStepContext& _context, Block& _ast)
{
CircularReferencesPruner{_context.reservedIdentifiers}(_ast);
FunctionGrouper::run(_context, _ast);
}
void CircularReferencesPruner::operator()(Block& _block)

View File

@ -22,6 +22,7 @@
#include <libyul/optimiser/ExpressionJoiner.h>
#include <libyul/optimiser/FunctionGrouper.h>
#include <libyul/optimiser/NameCollector.h>
#include <libyul/optimiser/OptimizerUtilities.h>
#include <libyul/Exceptions.h>
@ -37,9 +38,10 @@ using namespace std;
using namespace solidity;
using namespace solidity::yul;
void ExpressionJoiner::run(OptimiserStepContext&, Block& _ast)
void ExpressionJoiner::run(OptimiserStepContext& _context, Block& _ast)
{
ExpressionJoiner{_ast}(_ast);
FunctionGrouper::run(_context, _ast);
}

View File

@ -34,7 +34,7 @@ struct OptimiserStepContext;
* all function definitions.
*
* After this step, a block is of the form
* { { I...} F... }
* { { I... } F... }
* Where I are (non-function-definition) instructions and F are function definitions.
*/
class FunctionGrouper

View File

@ -37,6 +37,8 @@ namespace solidity::yul
{
/// Removes statements that are just empty blocks (non-recursive).
/// If this is run on the outermost block, the FunctionGrouper should be run afterwards to keep
/// the canonical form.
void removeEmptyBlocks(Block& _block);
/// Returns true if a given literal can not be used as an identifier.

View File

@ -118,7 +118,7 @@ void OptimiserSuite::run(
// Some steps depend on properties ensured by FunctionHoister, BlockFlattener, FunctionGrouper and
// ForLoopInitRewriter. Run them first to be able to run arbitrary sequences safely.
suite.runSequence("hfgo", ast);
suite.runSequence("hgfo", ast);
NameSimplifier::run(suite.m_context, ast);
// Now the user-supplied part

View File

@ -21,6 +21,7 @@
#include <libyul/optimiser/UnusedPruner.h>
#include <libyul/optimiser/CallGraphGenerator.h>
#include <libyul/optimiser/FunctionGrouper.h>
#include <libyul/optimiser/NameCollector.h>
#include <libyul/optimiser/Semantics.h>
#include <libyul/optimiser/OptimizerUtilities.h>
@ -33,6 +34,12 @@ using namespace std;
using namespace solidity;
using namespace solidity::yul;
void UnusedPruner::run(OptimiserStepContext& _context, Block& _ast)
{
UnusedPruner::runUntilStabilisedOnFullAST(_context.dialect, _ast, _context.reservedIdentifiers);
FunctionGrouper::run(_context, _ast);
}
UnusedPruner::UnusedPruner(
Dialect const& _dialect,
Block& _ast,

View File

@ -50,9 +50,7 @@ class UnusedPruner: public ASTModifier
{
public:
static constexpr char const* name{"UnusedPruner"};
static void run(OptimiserStepContext& _context, Block& _ast) {
UnusedPruner::runUntilStabilisedOnFullAST(_context.dialect, _ast, _context.reservedIdentifiers);
}
static void run(OptimiserStepContext& _context, Block& _ast);
using ASTModifier::operator();

View File

@ -1,4 +1,5 @@
{
{
let _1 := mload(0)
let f_a := mload(1)
let f_r
@ -7,11 +8,13 @@
f_r := add(f_a, calldatasize())
}
let z := mload(2)
}
}
// ----
// step: blockFlattener
//
// {
// {
// let _1 := mload(0)
// let f_a := mload(1)
// let f_r
@ -19,3 +22,4 @@
// f_r := add(f_a, calldatasize())
// let z := mload(2)
// }
// }

View File

@ -1,12 +1,16 @@
{
{
for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } {
a := add(a, 1)
}
}
}
// ----
// step: blockFlattener
//
// {
// {
// for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) }
// { a := add(a, 1) }
// }
// }

View File

@ -1,4 +1,5 @@
{
{
if add(mload(7), sload(mload(3)))
{
let y := add(mload(3), 3)
@ -7,11 +8,13 @@
}
}
let t := add(3, 9)
}
}
// ----
// step: blockFlattener
//
// {
// {
// if add(mload(7), sload(mload(3)))
// {
// let y := add(mload(3), 3)
@ -19,3 +22,4 @@
// }
// let t := add(3, 9)
// }
// }

View File

@ -1,4 +1,5 @@
{
{
let a := 3
let b := 4
{
@ -13,11 +14,13 @@
}
a := add(a, c)
}
}
}
// ----
// step: blockFlattener
//
// {
// {
// let a := 3
// let b := 4
// a := add(b, 3)
@ -27,3 +30,4 @@
// b := add(a, b)
// a := add(a, c)
// }
// }

View File

@ -1,14 +1,17 @@
{
{
let a := 1
switch calldataload(0)
case 0 { { { mstore(0, 1) } } a := 8 }
default { a := 3 { a := 4 } }
a := 5
}
}
// ----
// step: blockFlattener
//
// {
// {
// let a := 1
// switch calldataload(0)
// case 0 {
@ -21,3 +24,4 @@
// }
// a := 5
// }
// }

View File

@ -9,8 +9,10 @@
// step: circularReferencesPruner
//
// {
// {
// let a
// a := h()
// }
// function f() -> x
// { x := g() }
// function g() -> y

View File

@ -11,4 +11,4 @@
// ----
// step: circularReferencesPruner
//
// { }
// { { } }

View File

@ -11,4 +11,4 @@
// ----
// step: circularReferencesPruner
//
// { }
// { { } }

View File

@ -5,4 +5,4 @@
// ----
// step: circularReferencesPruner
//
// { }
// { { } }

View File

@ -14,6 +14,8 @@
// step: expressionJoiner
//
// {
// {
// if add(mload(7), sload(mload(3))) { let y := add(mload(3), 3) }
// let t := add(3, 9)
// }
// }

View File

@ -8,7 +8,9 @@
// step: expressionJoiner
//
// {
// {
// let a := mload(3)
// let b := mload(6)
// sstore(mul(add(b, a), mload(2)), 3)
// }
// }

View File

@ -8,5 +8,7 @@
// step: expressionJoiner
//
// {
// {
// sstore(mul(add(mload(6), mload(2)), 2), 3)
// }
// }

View File

@ -7,6 +7,8 @@
// step: expressionJoiner
//
// {
// {
// let a := mload(2)
// let b := add(a, a)
// }
// }

View File

@ -11,6 +11,8 @@
// step: expressionJoiner
//
// {
// {
// let a := mload(2)
// sstore(mul(a, add(2, mload(6))), 3)
// }
// }

View File

@ -8,6 +8,8 @@
// step: expressionJoiner
//
// {
// {
// let a := mload(2)
// sstore(mul(add(a, mload(6)), 2), 3)
// }
// }

View File

@ -15,6 +15,8 @@
// step: expressionJoiner
//
// {
// {
// let x := calldataload(mload(2))
// sstore(x, 3)
// }
// }

View File

@ -5,6 +5,8 @@
// step: expressionJoiner
//
// {
// {
// for { let b := mload(1) } b { }
// { }
// }
// }

View File

@ -6,7 +6,9 @@
// step: expressionJoiner
//
// {
// {
// let a := mload(0)
// for { } a { }
// { }
// }
// }

View File

@ -9,6 +9,7 @@
// step: expressionJoiner
//
// {
// { }
// function f(a) -> x
// {
// a := mload(2)

View File

@ -8,7 +8,9 @@
// step: expressionJoiner
//
// {
// {
// let a := mload(2)
// let b := mload(a)
// a := 4
// }
// }

View File

@ -7,5 +7,7 @@
// step: expressionJoiner
//
// {
// {
// sstore(calldataload(mload(2)), 3)
// }
// }

View File

@ -9,6 +9,8 @@
// step: expressionJoiner
//
// {
// {
// let b := sload(mload(3))
// sstore(add(b, mload(7)), 0)
// }
// }

View File

@ -2,4 +2,4 @@
// ----
// step: expressionJoiner
//
// { }
// { { } }

View File

@ -18,8 +18,10 @@
// step: expressionJoiner
//
// {
// {
// switch add(mload(7), sload(mload(3)))
// case 3 { let y := add(mload(3), 3) }
// default { sstore(1, 0) }
// let t := add(3, 9)
// }
// }

View File

@ -9,5 +9,7 @@
// step: expressionJoiner
//
// {
// {
// sstore(mul(add(mload(7), mload(6)), mload(2)), 3)
// }
// }

View File

@ -8,8 +8,10 @@
// step: expressionSimplifier
//
// {
// {
// let c, d := f()
// sstore(add(add(d, c), 7), 20)
// }
// function f() -> x, z
// { }
// }

View File

@ -6,4 +6,4 @@
// ----
// step: expressionSimplifier
//
// { sstore(0, 0) }
// { { sstore(0, 0) } }

View File

@ -13,7 +13,9 @@
// step: expressionSimplifier
//
// {
// {
// let x := calldataload(0)
// let a := and(0xff, and(shr(248, x), 255))
// sstore(a, shr(12, and(shl(8, x), 15790080)))
// }
// }

View File

@ -24,6 +24,7 @@
// step: expressionSimplifier
//
// {
// {
// let x := calldataload(0)
// let _2 := 0xf
// let _5 := and(shr(248, x), 0)
@ -46,3 +47,4 @@
// sstore(_2, f)
// sstore(16, g)
// }
// }

View File

@ -21,6 +21,7 @@
// step: expressionSimplifier
//
// {
// {
// let x := calldataload(0)
// let a := and(shl(8, x), 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000)
// let b := and(shr(8, x), 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0)
@ -35,3 +36,4 @@
// sstore(19, d)
// sstore(20, e)
// }
// }

View File

@ -5,4 +5,4 @@
// ----
// step: expressionSimplifier
//
// { mstore(20, mload(0)) }
// { { mstore(20, mload(0)) } }

View File

@ -5,4 +5,4 @@
// ----
// step: expressionSimplifier
//
// { sstore(7, 13) }
// { { sstore(7, 13) } }

View File

@ -12,9 +12,11 @@
// step: expressionSimplifier
//
// {
// {
// let _1 := 0xffffffffffffffffffffffffffffffffffffffff
// let _2 := 0
// let _3 := 0x20
// let a := and(create2(_2, _2, _3, _2), _1)
// sstore(a, and(_1, create2(_2, _2, _3, _2)))
// }
// }

View File

@ -11,6 +11,7 @@
// step: expressionSimplifier
//
// {
// {
// let _1 := 0x20
// let _2 := 0
// let c := create(_2, _2, _1)
@ -18,3 +19,4 @@
// let a := and(c, _4)
// sstore(a, and(_4, create(_2, _2, _1)))
// }
// }

View File

@ -13,6 +13,7 @@
// step: expressionSimplifier
//
// {
// {
// let _1 := 0
// let t := calldataload(_1)
// sstore(_1, iszero(t))
@ -22,3 +23,4 @@
// sstore(3, exp(8, t))
// sstore(4, sub(iszero(and(t, 1)), and(t, 1)))
// }
// }

View File

@ -9,8 +9,10 @@
// step: expressionSimplifier
//
// {
// {
// let x := calldataload(0)
// let z := calldataload(1)
// let t := and(x, z)
// sstore(t, or(x, z))
// }
// }

View File

@ -5,4 +5,4 @@
// ----
// step: expressionSimplifier
//
// { sstore(0, 0) }
// { { sstore(0, 0) } }

View File

@ -6,6 +6,8 @@
// step: expressionSimplifier
//
// {
// {
// let _1 := 0
// sstore(_1, sub(calldataload(1), calldataload(_1)))
// }
// }

View File

@ -6,4 +6,4 @@
// ----
// step: expressionSimplifier
//
// { sstore(0, 0) }
// { { sstore(0, 0) } }

View File

@ -7,7 +7,7 @@
// step: expressionSimplifier
//
// {
// sstore(0, f())
// { sstore(0, f()) }
// function f() -> a
// { }
// }

View File

@ -6,7 +6,9 @@
// step: expressionSimplifier
//
// {
// {
// let a := 10
// for { } iszero(iszero(a)) { a := add(a, 1) }
// { }
// }
// }

View File

@ -6,4 +6,4 @@
// ----
// step: expressionSimplifier
//
// { sstore(0, mload(0)) }
// { { sstore(0, mload(0)) } }

View File

@ -10,7 +10,9 @@
// step: expressionSimplifier
//
// {
// {
// let _1 := 0
// let a := calldataload(_1)
// if eq(a, calldataload(0x20)) { sstore(_1, 1) }
// }
// }

View File

@ -13,6 +13,7 @@
// step: expressionSimplifier
//
// {
// {
// let _1 := 0
// let a := calldataload(_1)
// let b := 0
@ -24,3 +25,4 @@
// sstore(9, c)
// sstore(10, d)
// }
// }

View File

@ -5,6 +5,8 @@
// step: expressionSimplifier
//
// {
// {
// let _4 := 0
// mstore(_4, and(calldataload(_4), 255))
// }
// }

View File

@ -5,6 +5,8 @@
// step: expressionSimplifier
//
// {
// {
// let _4 := 0
// mstore(_4, and(calldataload(_4), 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff))
// }
// }

View File

@ -7,9 +7,11 @@
// step: expressionSimplifier
//
// {
// {
// let _2 := f(1)
// let _3 := 0
// sstore(_3, sub(f(_3), _2))
// }
// function f(a) -> b
// { }
// }

View File

@ -8,7 +8,7 @@
// step: expressionSimplifier
//
// {
// sstore(0, sub(f1(), f2()))
// { sstore(0, sub(f1(), f2())) }
// function f1() -> a
// { }
// function f2() -> b

View File

@ -8,7 +8,7 @@
// step: expressionSimplifier
//
// {
// sstore(sub(f(), f()), 8)
// { sstore(sub(f(), f()), 8) }
// function f() -> a
// { mstore(0, 1) }
// }

View File

@ -9,9 +9,11 @@
// step: expressionSimplifier
//
// {
// {
// let _1 := msize()
// let _2 := 0
// sstore(_2, _1)
// pop(keccak256(_2, _2))
// sstore(20, 0)
// }
// }

View File

@ -7,7 +7,9 @@
// step: expressionSimplifier
//
// {
// {
// let _1 := 0
// pop(call(_1, _1, _1, _1, _1, _1, _1))
// sstore(_1, 0)
// }
// }

View File

@ -8,8 +8,10 @@
// step: expressionSimplifier
//
// {
// {
// pop(f())
// mstore(0, 0)
// }
// function f() -> x
// { mstore(0, 1337) }
// }

View File

@ -7,4 +7,4 @@
// ----
// step: expressionSimplifier
//
// { sstore(0, 0) }
// { { sstore(0, 0) } }

View File

@ -7,8 +7,10 @@
// step: expressionSimplifier
//
// {
// {
// let _1 := 0
// let x := mload(_1)
// x := _1
// mstore(_1, 7)
// }
// }

View File

@ -12,6 +12,7 @@
// step: expressionSimplifier
//
// {
// {
// let _2 := calldataload(0)
// let _5 := 0xff
// let a := shr(248, _2)
@ -21,3 +22,4 @@
// sstore(a, b)
// sstore(c, d)
// }
// }

View File

@ -12,6 +12,7 @@
// step: expressionSimplifier
//
// {
// {
// let a := 0
// let b := 0
// let _8 := calldataload(2)
@ -21,3 +22,4 @@
// sstore(a, b)
// sstore(c, d)
// }
// }

View File

@ -10,7 +10,7 @@
// step: expressionSimplifier
//
// {
// let t, v := f()
// { let t, v := f() }
// function f() -> c, d
// { sstore(0, 7) }
// }

View File

@ -6,6 +6,8 @@
// step: expressionSimplifier
//
// {
// {
// let _1 := 0
// sstore(_1, mload(_1))
// }
// }

View File

@ -6,4 +6,6 @@
// ----
// step: expressionSimplifier
//
// {
// { sstore(0, balance(address())) }
// }

View File

@ -9,6 +9,8 @@
// step: expressionSimplifier
//
// {
// {
// let a := address()
// sstore(a, selfbalance())
// }
// }

View File

@ -6,4 +6,4 @@
// ----
// step: expressionSimplifier
//
// { sstore(0, selfbalance()) }
// { { sstore(0, selfbalance()) } }

View File

@ -9,6 +9,8 @@
// step: expressionSimplifier
//
// {
// {
// for { } div(create(0, 1, 0), shl(msize(), 1)) { }
// { }
// }
// }

View File

@ -2,4 +2,4 @@
// ----
// step: expressionSimplifier
//
// { }
// { { } }

View File

@ -8,6 +8,8 @@
// step: expressionSimplifier
//
// {
// {
// let c, d
// sstore(d, 7)
// }
// }

View File

@ -8,4 +8,4 @@
// ----
// step: expressionSimplifier
//
// { sstore(8, 7) }
// { { sstore(8, 7) } }

View File

@ -13,6 +13,7 @@
// step: fullInliner
//
// {
// { }
// function f(a) -> b
// { b := sload(mload(a)) }
// function g() -> x_1

View File

@ -6,6 +6,8 @@
// step: fullSimplify
//
// {
// {
// let _2 := 0
// mstore(mload(_2), _2)
// }
// }

View File

@ -5,4 +5,4 @@
// ----
// step: fullSimplify
//
// { mstore(0, 13) }
// { { mstore(0, 13) } }

View File

@ -5,4 +5,4 @@
// ----
// step: fullSimplify
//
// { mstore(0, 0) }
// { { mstore(0, 0) } }

View File

@ -6,6 +6,8 @@
// step: fullSimplify
//
// {
// {
// let _1 := 0
// mstore(_1, sub(calldataload(1), calldataload(_1)))
// }
// }

View File

@ -5,4 +5,4 @@
// ----
// step: fullSimplify
//
// { mstore(0, 0) }
// { { mstore(0, 0) } }

View File

@ -7,7 +7,7 @@
// step: fullSimplify
//
// {
// mstore(f(), 0)
// { mstore(f(), 0) }
// function f() -> a
// { }
// }

View File

@ -7,7 +7,9 @@
// step: fullSimplify
//
// {
// {
// let a := 10
// for { } iszero(iszero(a)) { a := add(a, 1) }
// { }
// }
// }

View File

@ -11,8 +11,10 @@
// step: fullSimplify
//
// {
// {
// let a := calldataload(0)
// let _4 := 0
// let b := a
// mstore(b, eq(calldataload(_4), a))
// }
// }

View File

@ -5,6 +5,8 @@
// step: fullSimplify
//
// {
// {
// let _4 := 0
// mstore(_4, and(calldataload(_4), 255))
// }
// }

View File

@ -5,6 +5,8 @@
// step: fullSimplify
//
// {
// {
// let _4 := 0
// mstore(_4, and(calldataload(_4), 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff))
// }
// }

View File

@ -6,9 +6,11 @@
// step: fullSimplify
//
// {
// {
// let _2 := f(1)
// let _3 := 0
// mstore(_3, sub(f(_3), _2))
// }
// function f(a) -> b
// { }
// }

View File

@ -8,7 +8,7 @@
// step: fullSimplify
//
// {
// mstore(0, sub(f1(), f2()))
// { mstore(0, sub(f1(), f2())) }
// function f1() -> a
// { }
// function f2() -> b

View File

@ -8,7 +8,7 @@
// step: fullSimplify
//
// {
// mstore(0, sub(f(), f()))
// { mstore(0, sub(f(), f())) }
// function f() -> a
// { mstore(1, 2) }
// }

View File

@ -7,7 +7,9 @@
// step: fullSimplify
//
// {
// {
// let _1 := 0
// pop(create(_1, _1, _1))
// mstore(_1, 0)
// }
// }

View File

@ -23,6 +23,7 @@
// step: fullSimplify
//
// {
// {
// mstore(1, 0)
// mstore(2, 0)
// mstore(3, 0)
@ -42,3 +43,4 @@
// mstore(17, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
// mstore(18, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
// }
// }

View File

@ -6,6 +6,8 @@
// step: fullSimplify
//
// {
// {
// let _1 := 0
// mstore(_1, mload(_1))
// }
// }

View File

@ -8,6 +8,8 @@
// step: fullSimplify
//
// {
// {
// mstore(0, 7)
// mstore(1, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
// }
// }

View File

@ -2,4 +2,4 @@
// ----
// step: fullSimplify
//
// { }
// { { } }

View File

@ -8,6 +8,8 @@
// step: loadResolver
//
// {
// {
// let a := mload(calldataload(0))
// sstore(a, a)
// }
// }

View File

@ -9,8 +9,10 @@
// step: loadResolver
//
// {
// {
// let x := calldataload(0)
// let a := mload(x)
// x := 7
// sstore(a, mload(x))
// }
// }

View File

@ -9,8 +9,10 @@
// step: loadResolver
//
// {
// {
// let x := calldataload(0)
// let a := mload(x)
// a := 7
// sstore(a, mload(x))
// }
// }

View File

@ -9,8 +9,10 @@
// step: loadResolver
//
// {
// {
// let _1 := 10
// let _2 := 0
// mstore(_2, _1)
// sstore(_2, 89717814153306320011181716697424560163256864414616650038987186496166826726056)
// }
// }

View File

@ -6,8 +6,10 @@
// step: loadResolver
//
// {
// {
// for { }
// addmod(keccak256(0x0, create(0x0, 0x0, 0x0)), 0x0, 0x0)
// { }
// { }
// }
// }

View File

@ -10,9 +10,11 @@
// step: loadResolver
//
// {
// {
// let _1 := 30
// let _2 := 0
// mstore(_2, _1)
// if calldataload(_2) { mstore(_2, 20) }
// sstore(_2, keccak256(_2, 32))
// }
// }

Some files were not shown because too many files have changed in this diff Show More