Merge pull request #9672 from ethereum/fixRecompilation

Fix inlining order to correspond to source order.
This commit is contained in:
chriseth 2020-08-26 16:39:03 +02:00 committed by GitHub
commit bc4e07d309
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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 array implicit conversion.
* SMTChecker: Fix internal error on fixed bytes index access. * SMTChecker: Fix internal error on fixed bytes index access.
* References Resolver: Fix internal bug when using constructor for library. * 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) ### 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: // TODO it might be good to determine a visiting order:
// first handle functions that are called from many places. // 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); if (!holds_alternative<FunctionDefinition>(statement))
updateCodeSize(*fun.second); 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))) (import \"ethereum\" \"finish\" (func $eth.finish (param i32 i32)))
(memory $memory (export \"memory\") 1) (memory $memory (export \"memory\") 1)
(export \"main\" (func $main)) (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 (func $main
(local $_1 i64) (local $_1 i64)
@ -15,6 +18,7 @@
(local $z1 i64) (local $z1 i64)
(local $z2 i64) (local $z2 i64)
(local $z3 i64) (local $z3 i64)
(local $z4 i64)
(local $_3 i64) (local $_3 i64)
(block $label_ (block $label_
(local.set $_1 (i64.const 0)) (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 16)) (local.get $_2))
(i64.store (i32.add (local.get $r) (i32.const 24)) (call $endian_swap (i64.const 128))) (i64.store (i32.add (local.get $r) (i32.const 24)) (call $endian_swap (i64.const 128)))
(call $eth.getCallValue (i32.const 0)) (call $eth.getCallValue (i32.const 0))
(local.set $z1 (call $endian_swap (i64.load (i32.const 0)))) (block
(local.set $z2 (call $endian_swap (i64.load (i32.add (i32.const 0) (i32.const 8))))) (local.set $z1 (call $mload_internal (i32.const 0)))
(local.set $z3 (call $endian_swap (i64.load (i32.add (i32.const 0) (i32.const 16))))) (local.set $z2 (global.get $global_))
(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 (local.set $z3 (global.get $global__1))
(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)))) (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\")) (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 $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 $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.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) (param $x4 i64)
(result i32) (result i32)
(local $v 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 (if (i64.ne (i64.const 0) (i64.or (i64.or (local.get $x1) (local.get $x2)) (local.get $x3))) (then
(unreachable))) (unreachable)))
(if (i64.ne (i64.const 0) (i64.shr_u (local.get $x4) (i64.const 32))) (then (if (i64.ne (i64.const 0) (i64.shr_u (local.get $x4) (i64.const 32))) (then
@ -65,7 +73,7 @@
(result i32) (result i32)
(local $r i32) (local $r i32)
(local $p 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 $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))) (local.set $r (i32.add (local.get $p) (i32.const 64)))
(if (i32.lt_u (local.get $r) (local.get $p)) (then (if (i32.lt_u (local.get $r) (local.get $p)) (then
@ -75,29 +83,11 @@
(local.get $r) (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 (func $endian_swap_16
(param $x i64) (param $x i64)
(result i64) (result i64)
(local $y 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)))) (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) (result i64)
(local $y i64) (local $y i64)
(local $hi 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 $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))))) (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) (result i64)
(local $y i64) (local $y i64)
(local $hi 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 $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))))) (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) (local.get $y)
) )
(func $return (func $mload_internal
(param $x1 i64) (param $pos i32)
(param $x2 i64) (result i64)
(param $x3 i64) (local $z1 i64)
(param $x4 i64) (local $z2 i64)
(param $y1 i64) (local $z3 i64)
(param $y2 i64) (local $z4 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)
(block $label__8 (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 // optimize-yul: true
// ---- // ----
// creation: // creation:
// codeDepositCost: 603000 // codeDepositCost: 616600
// executionCost: 638 // executionCost: 651
// totalCost: 603638 // totalCost: 617251
// external: // external:
// a(): 1029 // a(): 1029
// b(uint256): 2084 // b(uint256): 2084

View File

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