Fix inlining order to correspond to source order.

This commit is contained in:
chriseth 2020-08-25 16:56:59 +02:00
parent 29b6c17246
commit e72afcba47
5 changed files with 59 additions and 71 deletions

View File

@ -18,6 +18,7 @@ Bugfixes:
* SMTChecker: Fix internal error on array implicit conversion.
* SMTChecker: Fix internal error on fixed bytes index access.
* References Resolver: Fix internal bug when using constructor for library.
* Yul Optimizer: Make function inlining order more resilient to whether or not unrelated source files are present.
### 0.7.0 (2020-07-28)

View File

@ -80,10 +80,20 @@ void FullInliner::run()
// TODO it might be good to determine a visiting order:
// first handle functions that are called from many places.
for (auto const& fun: m_functions)
// Note that the order of inlining can result in very different code.
// Since AST IDs and thus function names depend on whether or not a contract
// is compiled together with other source files, a change in AST IDs
// should have as little an impact as possible. This is the case
// if we handle inlining in source (and thus, for the IR generator,
// function name) order.
for (auto& statement: m_ast.statements)
{
handleBlock(fun.second->name, fun.second->body);
updateCodeSize(*fun.second);
if (!holds_alternative<FunctionDefinition>(statement))
continue;
FunctionDefinition& fun = std::get<FunctionDefinition>(statement);
handleBlock(fun.name, fun.body);
updateCodeSize(fun);
}
}

View File

@ -6,6 +6,9 @@
(import \"ethereum\" \"finish\" (func $eth.finish (param i32 i32)))
(memory $memory (export \"memory\") 1)
(export \"main\" (func $main))
(global $global_ (mut i64) (i64.const 0))
(global $global__1 (mut i64) (i64.const 0))
(global $global__2 (mut i64) (i64.const 0))
(func $main
(local $_1 i64)
@ -15,6 +18,7 @@
(local $z1 i64)
(local $z2 i64)
(local $z3 i64)
(local $z4 i64)
(local $_3 i64)
(block $label_
(local.set $_1 (i64.const 0))
@ -28,14 +32,18 @@
(i64.store (i32.add (local.get $r) (i32.const 16)) (local.get $_2))
(i64.store (i32.add (local.get $r) (i32.const 24)) (call $endian_swap (i64.const 128)))
(call $eth.getCallValue (i32.const 0))
(local.set $z1 (call $endian_swap (i64.load (i32.const 0))))
(local.set $z2 (call $endian_swap (i64.load (i32.add (i32.const 0) (i32.const 8)))))
(local.set $z3 (call $endian_swap (i64.load (i32.add (i32.const 0) (i32.const 16)))))
(if (i32.eqz (i64.eqz (i64.or (i64.or (local.get $z1) (local.get $z2)) (i64.or (local.get $z3) (call $endian_swap (i64.load (i32.add (i32.const 0) (i32.const 24)))))))) (then
(call $revert (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1))))
(block
(local.set $z1 (call $mload_internal (i32.const 0)))
(local.set $z2 (global.get $global_))
(local.set $z3 (global.get $global__1))
(local.set $z4 (global.get $global__2))
)
(if (i32.eqz (i64.eqz (i64.or (i64.or (local.get $z1) (local.get $z2)) (i64.or (local.get $z3) (local.get $z4))))) (then
(call $eth.revert (call $to_internal_i32ptr (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1)) (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1)))))
(local.set $_3 (datasize \"C_2_deployed\"))
(call $codecopy (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1) (dataoffset \"C_2_deployed\") (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_3))
(call $return (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_3))
(call $eth.codeCopy (call $to_internal_i32ptr (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1)) (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (dataoffset \"C_2_deployed\")) (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_3)))
(call $eth.finish (call $to_internal_i32ptr (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_1)) (call $u256_to_i32 (local.get $_1) (local.get $_1) (local.get $_1) (local.get $_3)))
)
)
@ -46,7 +54,7 @@
(param $x4 i64)
(result i32)
(local $v i32)
(block $label__1
(block $label__3
(if (i64.ne (i64.const 0) (i64.or (i64.or (local.get $x1) (local.get $x2)) (local.get $x3))) (then
(unreachable)))
(if (i64.ne (i64.const 0) (i64.shr_u (local.get $x4) (i64.const 32))) (then
@ -65,7 +73,7 @@
(result i32)
(local $r i32)
(local $p i32)
(block $label__2
(block $label__4
(local.set $p (call $u256_to_i32 (local.get $x1) (local.get $x2) (local.get $x3) (local.get $x4)))
(local.set $r (i32.add (local.get $p) (i32.const 64)))
(if (i32.lt_u (local.get $r) (local.get $p)) (then
@ -75,29 +83,11 @@
(local.get $r)
)
(func $codecopy
(param $x1 i64)
(param $x2 i64)
(param $x3 i64)
(param $x4 i64)
(param $y1 i64)
(param $y2 i64)
(param $y3 i64)
(param $y4 i64)
(param $z1 i64)
(param $z2 i64)
(param $z3 i64)
(param $z4 i64)
(block $label__3
(call $eth.codeCopy (call $to_internal_i32ptr (local.get $x1) (local.get $x2) (local.get $x3) (local.get $x4)) (call $u256_to_i32 (local.get $y1) (local.get $y2) (local.get $y3) (local.get $y4)) (call $u256_to_i32 (local.get $z1) (local.get $z2) (local.get $z3) (local.get $z4)))
)
)
(func $endian_swap_16
(param $x i64)
(result i64)
(local $y i64)
(block $label__4
(block $label__5
(local.set $y (i64.or (i64.and (i64.shl (local.get $x) (i64.const 8)) (i64.const 65280)) (i64.and (i64.shr_u (local.get $x) (i64.const 8)) (i64.const 255))))
)
@ -109,7 +99,7 @@
(result i64)
(local $y i64)
(local $hi i64)
(block $label__5
(block $label__6
(local.set $hi (i64.shl (call $endian_swap_16 (local.get $x)) (i64.const 16)))
(local.set $y (i64.or (local.get $hi) (call $endian_swap_16 (i64.shr_u (local.get $x) (i64.const 16)))))
@ -122,7 +112,7 @@
(result i64)
(local $y i64)
(local $hi i64)
(block $label__6
(block $label__7
(local.set $hi (i64.shl (call $endian_swap_32 (local.get $x)) (i64.const 32)))
(local.set $y (i64.or (local.get $hi) (call $endian_swap_32 (i64.shr_u (local.get $x) (i64.const 32)))))
@ -130,32 +120,24 @@
(local.get $y)
)
(func $return
(param $x1 i64)
(param $x2 i64)
(param $x3 i64)
(param $x4 i64)
(param $y1 i64)
(param $y2 i64)
(param $y3 i64)
(param $y4 i64)
(block $label__7
(call $eth.finish (call $to_internal_i32ptr (local.get $x1) (local.get $x2) (local.get $x3) (local.get $x4)) (call $u256_to_i32 (local.get $y1) (local.get $y2) (local.get $y3) (local.get $y4)))
)
)
(func $revert
(param $x1 i64)
(param $x2 i64)
(param $x3 i64)
(param $x4 i64)
(param $y1 i64)
(param $y2 i64)
(param $y3 i64)
(param $y4 i64)
(func $mload_internal
(param $pos i32)
(result i64)
(local $z1 i64)
(local $z2 i64)
(local $z3 i64)
(local $z4 i64)
(block $label__8
(call $eth.revert (call $to_internal_i32ptr (local.get $x1) (local.get $x2) (local.get $x3) (local.get $x4)) (call $u256_to_i32 (local.get $y1) (local.get $y2) (local.get $y3) (local.get $y4)))
(local.set $z1 (call $endian_swap (i64.load (local.get $pos))))
(local.set $z2 (call $endian_swap (i64.load (i32.add (local.get $pos) (i32.const 8)))))
(local.set $z3 (call $endian_swap (i64.load (i32.add (local.get $pos) (i32.const 16)))))
(local.set $z4 (call $endian_swap (i64.load (i32.add (local.get $pos) (i32.const 24)))))
)
(global.set $global_ (local.get $z2))
(global.set $global__1 (local.get $z3))
(global.set $global__2 (local.get $z4))
(local.get $z1)
)
)

View File

@ -17,9 +17,9 @@ contract C {
// optimize-yul: true
// ----
// creation:
// codeDepositCost: 603000
// executionCost: 638
// totalCost: 603638
// codeDepositCost: 616600
// executionCost: 651
// totalCost: 617251
// external:
// a(): 1029
// b(uint256): 2084

View File

@ -36,20 +36,15 @@
// function f(x)
// {
// mstore(0, x)
// let t_20 := 0
// t_20 := 2
// mstore(7, t_20)
// g(10)
// let t_14 := 0
// t_14 := 2
// mstore(7, t_14)
// let x_1_15 := 10
// f(1)
// mstore(1, x)
// }
// function g(x_1)
// {
// let x_14 := 1
// mstore(0, x_14)
// mstore(7, h())
// g(10)
// mstore(1, x_14)
// }
// { f(1) }
// function h() -> t
// { t := 2 }
// }