Merge pull request #10942 from ethereum/returnSlotAllocation

Delayed return slot allocation.
This commit is contained in:
chriseth
2021-04-08 16:42:07 +02:00
committed by GitHub
24 changed files with 644 additions and 97 deletions
@@ -150,6 +150,7 @@ sub_0: assembly {
revert(0x00, 0x24)
/* "#utility.yul":196:425 */
tag_22:
/* "#utility.yul":236:239 */
0x00
/* "#utility.yul":267:268 */
dup3
@@ -155,6 +155,7 @@ sub_0: assembly {
revert(0x00, 0x24)
/* "#utility.yul":196:425 */
tag_19:
/* "#utility.yul":236:239 */
0x00
/* "#utility.yul":267:268 */
dup3
@@ -62,7 +62,7 @@ contract C {
// test_bytes() ->
// gas irOptimized: 511133
// gas legacy: 466763
// gas legacyOptimized: 374537
// gas legacyOptimized: 374591
// test_uint256() ->
// gas irOptimized: 706775
// gas legacy: 634592
@@ -63,7 +63,7 @@ contract C {
// test_bytes() ->
// gas irOptimized: 511133
// gas legacy: 466763
// gas legacyOptimized: 374537
// gas legacyOptimized: 374591
// test_uint256() ->
// gas irOptimized: 706775
// gas legacy: 634592
+122 -6
View File
@@ -117,16 +117,63 @@ BOOST_AUTO_TEST_CASE(many_variables_many_uses)
BOOST_CHECK_EQUAL(out, "f: 10 ");
}
BOOST_AUTO_TEST_CASE(many_return_variables)
BOOST_AUTO_TEST_CASE(many_return_variables_unused_arguments)
{
string out = check(R"({
function f(a, b) -> r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19 {
}
})");
BOOST_CHECK_EQUAL(out, "f: 3 ");
}
BOOST_AUTO_TEST_CASE(many_return_variables_used_arguments)
{
string out = check(R"({
function f(a, b) -> r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19 {
r1 := 0
sstore(a, b)
}
})");
BOOST_CHECK_EQUAL(out, "f: 5 ");
}
BOOST_AUTO_TEST_CASE(multiple_functions)
BOOST_AUTO_TEST_CASE(multiple_functions_used_arguments)
{
string out = check(R"({
function f(a, b) -> r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19 {
r1 := 0
sstore(a, b)
}
function g(r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19) -> x, y {
x := 0
sstore(r1, r2)
}
function h(x) {
let r1 := 0
let r2 := 0
let r3 := 0
let r4 := 0
let r5 := 0
let r6 := 0
let r7 := 0
let r8 := 0
let r9 := 0
let r10 := 0
let r11 := 0
let r12 := 0
let r13 := 0
let r14 := 0
let r15 := 0
let r16 := 0
let r17 := 0
let r18 := 0
x := add(add(add(add(add(add(add(add(add(add(add(add(x, r12), r11), r10), r9), r8), r7), r6), r5), r4), r3), r2), r1)
}
})");
BOOST_CHECK_EQUAL(out, "h: 9 g: 5 f: 5 ");
}
BOOST_AUTO_TEST_CASE(multiple_functions_unused_arguments)
{
string out = check(R"({
function f(a, b) -> r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19 {
@@ -155,10 +202,47 @@ BOOST_AUTO_TEST_CASE(multiple_functions)
x := add(add(add(add(add(add(add(add(add(add(add(add(x, r12), r11), r10), r9), r8), r7), r6), r5), r4), r3), r2), r1)
}
})");
BOOST_CHECK_EQUAL(out, "h: 9 f: 3 ");
}
BOOST_AUTO_TEST_CASE(nested_used_arguments)
{
string out = check(R"({
function h(x) {
let r1 := 0
let r2 := 0
let r3 := 0
let r4 := 0
let r5 := 0
let r6 := 0
let r7 := 0
let r8 := 0
let r9 := 0
let r10 := 0
let r11 := 0
let r12 := 0
let r13 := 0
let r14 := 0
let r15 := 0
let r16 := 0
let r17 := 0
let r18 := 0
function f(a, b) -> t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19 {
function g(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19) -> w, v {
w := v
sstore(s1, s2)
}
t1 := t2
sstore(a, b)
}
x := add(add(add(add(add(add(add(add(add(add(add(add(x, r12), r11), r10), r9), r8), r7), r6), r5), r4), r3), r2), r1)
}
})");
BOOST_CHECK_EQUAL(out, "h: 9 g: 5 f: 5 ");
}
BOOST_AUTO_TEST_CASE(nested)
BOOST_AUTO_TEST_CASE(nested_unused_arguments)
{
string out = check(R"({
function h(x) {
@@ -187,10 +271,42 @@ BOOST_AUTO_TEST_CASE(nested)
x := add(add(add(add(add(add(add(add(add(add(add(add(x, r12), r11), r10), r9), r8), r7), r6), r5), r4), r3), r2), r1)
}
})");
BOOST_CHECK_EQUAL(out, "h: 9 g: 5 f: 5 ");
BOOST_CHECK_EQUAL(out, "h: 9 f: 3 ");
}
BOOST_AUTO_TEST_CASE(also_in_outer_block)
BOOST_AUTO_TEST_CASE(also_in_outer_block_used_arguments)
{
string out = check(R"({
let x := 0
let r1 := 0
let r2 := 0
let r3 := 0
let r4 := 0
let r5 := 0
let r6 := 0
let r7 := 0
let r8 := 0
let r9 := 0
let r10 := 0
let r11 := 0
let r12 := 0
let r13 := 0
let r14 := 0
let r15 := 0
let r16 := 0
let r17 := 0
let r18 := 0
x := add(add(add(add(add(add(add(add(add(add(add(add(x, r12), r11), r10), r9), r8), r7), r6), r5), r4), r3), r2), r1)
function g(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19) -> w, v {
w := v
sstore(s1, s2)
}
})");
BOOST_CHECK_EQUAL(out, "g: 5 : 9 ");
}
BOOST_AUTO_TEST_CASE(also_in_outer_block_unused_arguments)
{
string out = check(R"({
let x := 0
@@ -216,7 +332,7 @@ BOOST_AUTO_TEST_CASE(also_in_outer_block)
function g(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19) -> w, v {
}
})");
BOOST_CHECK_EQUAL(out, "g: 5 : 9 ");
BOOST_CHECK_EQUAL(out, ": 9 ");
}
BOOST_AUTO_TEST_SUITE_END()
@@ -0,0 +1,28 @@
{
function f(a, b, c) -> x { pop(address()) sstore(a, c) pop(callvalue()) x := b }
}
// ====
// stackOptimization: true
// ----
// PUSH1 0x17
// JUMP
// JUMPDEST
// ADDRESS
// POP
// DUP3
// DUP2
// SSTORE
// POP
// CALLVALUE
// POP
// PUSH1 0x0
// DUP2
// SWAP1
// POP
// JUMPDEST
// SWAP3
// SWAP2
// POP
// POP
// JUMP
// JUMPDEST
@@ -12,18 +12,17 @@
// PUSH1 0xD
// JUMP
// JUMPDEST
// PUSH1 0x16
// PUSH1 0x15
// JUMP
// JUMPDEST
// POP
// POP
// PUSH1 0x0
// JUMPDEST
// SWAP3
// SWAP2
// POP
// POP
// SWAP1
// JUMP
// JUMPDEST
// PUSH1 0x20
// PUSH1 0x1F
// PUSH1 0x4
// PUSH1 0x3
// PUSH1 0xD
@@ -0,0 +1,116 @@
{
function f(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) -> x {
mstore(0x0100, a1)
mstore(0x0120, a2)
mstore(0x0140, a3)
mstore(0x0160, a4)
mstore(0x0180, a5)
mstore(0x01A0, a6)
mstore(0x01C0, a7)
mstore(0x01E0, a8)
mstore(0x0200, a9)
mstore(0x0220, a10)
mstore(0x0240, a11)
mstore(0x0260, a12)
mstore(0x0280, a13)
mstore(0x02A0, a14)
mstore(0x02C0, a15)
mstore(0x02E0, a16)
mstore(0x0300, a17)
mstore(0x0320, a18)
mstore(0x0340, a19)
x := a20
}
}
// ====
// stackOptimization: true
// ----
// PUSH1 0x80
// JUMP
// JUMPDEST
// DUP1
// PUSH2 0x100
// MSTORE
// POP
// DUP1
// PUSH2 0x120
// MSTORE
// POP
// DUP1
// PUSH2 0x140
// MSTORE
// POP
// DUP1
// PUSH2 0x160
// MSTORE
// POP
// DUP1
// PUSH2 0x180
// MSTORE
// POP
// DUP1
// PUSH2 0x1A0
// MSTORE
// POP
// DUP1
// PUSH2 0x1C0
// MSTORE
// POP
// DUP1
// PUSH2 0x1E0
// MSTORE
// POP
// DUP1
// PUSH2 0x200
// MSTORE
// POP
// DUP1
// PUSH2 0x220
// MSTORE
// POP
// DUP1
// PUSH2 0x240
// MSTORE
// POP
// DUP1
// PUSH2 0x260
// MSTORE
// POP
// DUP1
// PUSH2 0x280
// MSTORE
// POP
// DUP1
// PUSH2 0x2A0
// MSTORE
// POP
// DUP1
// PUSH2 0x2C0
// MSTORE
// POP
// DUP1
// PUSH2 0x2E0
// MSTORE
// POP
// DUP1
// PUSH2 0x300
// MSTORE
// POP
// DUP1
// PUSH2 0x320
// MSTORE
// POP
// DUP1
// PUSH2 0x340
// MSTORE
// POP
// PUSH1 0x0
// DUP2
// SWAP1
// POP
// JUMPDEST
// SWAP2
// SWAP1
// POP
// JUMP
// JUMPDEST
@@ -7,8 +7,8 @@
// PUSH1 0x8
// JUMP
// JUMPDEST
// POP
// POP
// JUMPDEST
// POP
// POP
// JUMP
// JUMPDEST
@@ -8,18 +8,17 @@
// ====
// stackOptimization: true
// ----
// PUSH1 0x11
// PUSH1 0x10
// JUMP
// JUMPDEST
// POP
// POP
// POP
// POP
// PUSH1 0x0
// PUSH1 0x0
// JUMPDEST
// SWAP5
// POP
// SWAP5
// SWAP3
// POP
// POP
// POP
// SWAP1
// SWAP2
// JUMP
// JUMPDEST
@@ -4,14 +4,18 @@
// ====
// stackOptimization: true
// ----
// PUSH1 0x1F
// PUSH1 0x1E
// JUMP
// JUMPDEST
// PUSH1 0x0
// PUSH1 0x0
// PUSH1 0x3
// SWAP4
// POP
// PUSH1 0x3
// SWAP1
// POP
// POP
// POP
// POP
// PUSH1 0x0
// PUSH1 0x0
// PUSH1 0x9
// PUSH1 0x2
// SWAP2
@@ -21,12 +25,7 @@
// MSTORE
// POP
// JUMPDEST
// SWAP5
// POP
// SWAP5
// SWAP3
// POP
// POP
// POP
// SWAP1
// SWAP2
// JUMP
// JUMPDEST
@@ -0,0 +1,18 @@
{
function f() -> x { pop(address()) { pop(callvalue()) } }
}
// ====
// stackOptimization: true
// ----
// PUSH1 0xD
// JUMP
// JUMPDEST
// ADDRESS
// POP
// PUSH1 0x0
// CALLVALUE
// POP
// JUMPDEST
// SWAP1
// JUMP
// JUMPDEST
@@ -0,0 +1,18 @@
{
function f() -> x { pop(address()) let y := callvalue() }
}
// ====
// stackOptimization: true
// ----
// PUSH1 0xD
// JUMP
// JUMPDEST
// ADDRESS
// POP
// PUSH1 0x0
// CALLVALUE
// POP
// JUMPDEST
// SWAP1
// JUMP
// JUMPDEST
@@ -0,0 +1,27 @@
{
function f() -> x { pop(address()) for { pop(callvalue()) } 0 {} { } }
}
// ====
// stackOptimization: true
// ----
// PUSH1 0x19
// JUMP
// JUMPDEST
// ADDRESS
// POP
// PUSH1 0x0
// CALLVALUE
// POP
// JUMPDEST
// PUSH1 0x0
// ISZERO
// PUSH1 0x15
// JUMPI
// JUMPDEST
// PUSH1 0xA
// JUMP
// JUMPDEST
// JUMPDEST
// SWAP1
// JUMP
// JUMPDEST
@@ -0,0 +1,23 @@
{
function f() -> x { pop(address()) if 1 { pop(callvalue()) } }
}
// ====
// stackOptimization: true
// ----
// PUSH1 0x14
// JUMP
// JUMPDEST
// ADDRESS
// POP
// PUSH1 0x0
// PUSH1 0x1
// ISZERO
// PUSH1 0x10
// JUMPI
// CALLVALUE
// POP
// JUMPDEST
// JUMPDEST
// SWAP1
// JUMP
// JUMPDEST
@@ -0,0 +1,20 @@
{
function f() -> x { pop(address()) leave pop(callvalue()) }
}
// ====
// stackOptimization: true
// ----
// PUSH1 0x10
// JUMP
// JUMPDEST
// ADDRESS
// POP
// PUSH1 0x0
// PUSH1 0xD
// JUMP
// CALLVALUE
// POP
// JUMPDEST
// SWAP1
// JUMP
// JUMPDEST
@@ -0,0 +1,21 @@
{
function f() -> x { pop(address()) sstore(0, x) pop(callvalue()) }
}
// ====
// stackOptimization: true
// ----
// PUSH1 0x11
// JUMP
// JUMPDEST
// ADDRESS
// POP
// PUSH1 0x0
// DUP1
// PUSH1 0x0
// SSTORE
// CALLVALUE
// POP
// JUMPDEST
// SWAP1
// JUMP
// JUMPDEST
@@ -0,0 +1,16 @@
{
function f() -> x { pop(callvalue()) }
}
// ====
// stackOptimization: true
// ----
// PUSH1 0xB
// JUMP
// JUMPDEST
// CALLVALUE
// POP
// PUSH1 0x0
// JUMPDEST
// SWAP1
// JUMP
// JUMPDEST
@@ -0,0 +1,20 @@
{
function f() -> x, y, z { pop(callvalue()) }
}
// ====
// stackOptimization: true
// ----
// PUSH1 0x11
// JUMP
// JUMPDEST
// CALLVALUE
// POP
// PUSH1 0x0
// PUSH1 0x0
// PUSH1 0x0
// JUMPDEST
// SWAP1
// SWAP2
// SWAP3
// JUMP
// JUMPDEST
@@ -10,15 +10,14 @@
// ====
// stackOptimization: true
// ----
// PUSH1 0x15
// PUSH1 0x14
// JUMP
// JUMPDEST
// POP
// POP
// PUSH1 0x0
// JUMPDEST
// SWAP3
// SWAP2
// POP
// POP
// SWAP1
// JUMP
// JUMPDEST
// PUSH1 0x0
@@ -28,13 +27,13 @@
// SWAP2
// JUMP
// JUMPDEST
// PUSH1 0x1F
// PUSH1 0x1E
// PUSH1 0x2
// PUSH1 0x1
// PUSH1 0x3
// JUMP
// JUMPDEST
// PUSH1 0x29
// PUSH1 0x28
// PUSH1 0x4
// PUSH1 0x3
// PUSH1 0x3
@@ -43,12 +42,12 @@
// SWAP1
// POP
// POP
// PUSH1 0x32
// PUSH1 0xC
// PUSH1 0x31
// PUSH1 0xB
// JUMP
// JUMPDEST
// PUSH1 0x38
// PUSH1 0xC
// PUSH1 0x37
// PUSH1 0xB
// JUMP
// JUMPDEST
// SWAP2
+5 -4
View File
@@ -31,6 +31,7 @@ object "Contract" {
// tag_7
// jumpi
// /* "source":82:87 */
// pop
// jump(tag_6)
// /* "source":75:77 */
// tag_7:
@@ -47,8 +48,8 @@ object "Contract" {
// jump // in
// tag_8:
// /* "source":73:104 */
// tag_6:
// pop
// tag_6:
// jump // out
// tag_1:
// /* "source":109:113 */
@@ -59,6 +60,6 @@ object "Contract" {
// tag_5
// jump // in
// tag_9:
// Bytecode: 6025565b600b6001600e565b5b565b80156017576022565b602160028201600e565b5b50565b602d6001600e565b
// Opcodes: PUSH1 0x25 JUMP JUMPDEST PUSH1 0xB PUSH1 0x1 PUSH1 0xE JUMP JUMPDEST JUMPDEST JUMP JUMPDEST DUP1 ISZERO PUSH1 0x17 JUMPI PUSH1 0x22 JUMP JUMPDEST PUSH1 0x21 PUSH1 0x2 DUP3 ADD PUSH1 0xE JUMP JUMPDEST JUMPDEST POP JUMP JUMPDEST PUSH1 0x2D PUSH1 0x1 PUSH1 0xE JUMP JUMPDEST
// SourceMappings: 33:21:0:-:0;;;48:4;50:1;48:4;:::i;:::-;46:8;:::o;59:45::-;78:1;75:2;;;82:5;;75:2;90:12;99:1;96;92:9;90:12;:::i;:::-;73:31;;:::o;:::-;109:4;111:1;109:4;:::i;:::-
// Bytecode: 6026565b600b6001600e565b5b565b8015601857506024565b602260028201600e565b505b565b602e6001600e565b
// Opcodes: PUSH1 0x26 JUMP JUMPDEST PUSH1 0xB PUSH1 0x1 PUSH1 0xE JUMP JUMPDEST JUMPDEST JUMP JUMPDEST DUP1 ISZERO PUSH1 0x18 JUMPI POP PUSH1 0x24 JUMP JUMPDEST PUSH1 0x22 PUSH1 0x2 DUP3 ADD PUSH1 0xE JUMP JUMPDEST POP JUMPDEST JUMP JUMPDEST PUSH1 0x2E PUSH1 0x1 PUSH1 0xE JUMP JUMPDEST
// SourceMappings: 33:21:0:-:0;;;48:4;50:1;48:4;:::i;:::-;46:8;:::o;59:45::-;78:1;75:2;;;82:5;;;75:2;90:12;99:1;96;92:9;90:12;:::i;:::-;73:31;;:::o;:::-;109:4;111:1;109:4;:::i;:::-