From f6a82f8efadc1650ae4cb5648c8d3fb4dfca53ea Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Mon, 29 Mar 2021 11:18:53 +0200 Subject: [PATCH] Yul tests for MemoryStoreRemover --- .../memoryStoreRemover/calldatasize.yul | 21 ++++++++++++ .../memoryStoreRemover/complex1.yul | 21 ++++++++++++ .../memoryStoreRemover/complex2.yul | 32 +++++++++++++++++++ .../memoryStoreRemover/complex3.yul | 25 +++++++++++++++ .../memoryStoreRemover/complex4.yul | 23 +++++++++++++ .../memoryStoreRemover/complex5.yul | 22 +++++++++++++ .../memoryStoreRemover/complex6.yul | 22 +++++++++++++ .../memoryStoreRemover/complex7.yul | 22 +++++++++++++ .../memoryStoreRemover/complex8.yul | 19 +++++++++++ .../memoryStoreRemover/complex9.yul | 16 ++++++++++ .../memoryStoreRemover/eip1985.yul | 19 +++++++++++ .../memoryStoreRemover/msize.yul | 15 +++++++++ .../memoryStoreRemover/overflow.yul | 20 ++++++++++++ .../memoryStoreRemover/overflow_mstore.yul | 19 +++++++++++ .../memoryStoreRemover/simple1.yul | 13 ++++++++ .../memoryStoreRemover/simple10.yul | 29 +++++++++++++++++ .../memoryStoreRemover/simple2.yul | 17 ++++++++++ .../memoryStoreRemover/simple3.yul | 17 ++++++++++ .../memoryStoreRemover/simple4.yul | 19 +++++++++++ .../memoryStoreRemover/simple5.yul | 19 +++++++++++ .../memoryStoreRemover/simple6.yul | 21 ++++++++++++ .../memoryStoreRemover/simple7.yul | 19 +++++++++++ .../memoryStoreRemover/simple8.yul | 21 ++++++++++++ .../memoryStoreRemover/simple9.yul | 24 ++++++++++++++ .../memoryStoreRemover/smoke.yul | 5 +++ 25 files changed, 500 insertions(+) create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/calldatasize.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/complex1.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/complex2.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/complex3.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/complex4.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/complex5.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/complex6.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/complex7.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/complex8.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/complex9.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/eip1985.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/msize.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/overflow.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/overflow_mstore.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/simple1.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/simple10.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/simple2.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/simple3.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/simple4.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/simple5.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/simple6.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/simple7.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/simple8.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/simple9.yul create mode 100644 test/libyul/yulOptimizerTests/memoryStoreRemover/smoke.yul diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/calldatasize.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/calldatasize.yul new file mode 100644 index 000000000..f6a5a1a6b --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/calldatasize.yul @@ -0,0 +1,21 @@ +// Test to see if the solver can prove that there is no overflow +// during memory calculations. +{ + let x := 0 + let y := 100 + // can be removed + mstore(x, y) + // reads from [500, 500 + calldatasize()) + // since `500 + calldatasize()` does not overflow, it does not read from [0, 32) + // Assuming EIP 1985, the value of calldatasize is at most 2**32. + pop(staticcall(10000, 0, 500, calldatasize(), 0, 0)) +} +// ---- +// step: memoryStoreRemover +// +// { +// let x := 0 +// let y := 100 +// pop(y) +// pop(staticcall(10000, 0, 500, calldatasize(), 0, 0)) +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/complex1.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/complex1.yul new file mode 100644 index 000000000..fbaa462e1 --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/complex1.yul @@ -0,0 +1,21 @@ +{ + let x := 10 + let y := 100 + if calldataload(0) { + // should be removed + mstore(x, y) + } + + if calldataload(0) { + pop(mload(y)) + } +} +// ---- +// step: memoryStoreRemover +// +// { +// let x := 10 +// let y := 100 +// if calldataload(0) { pop(y) } +// if calldataload(0) { pop(mload(y)) } +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/complex2.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/complex2.yul new file mode 100644 index 000000000..f4c53aa18 --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/complex2.yul @@ -0,0 +1,32 @@ +{ + f() + let z := 100 + pop(mload(z)) + + if calldataload(0) { + // does not read from location [20, 52) + pop(keccak256(z, z)) + } + + function f() { + let x := 10 + let y := 20 + // can be removed + mstore(x, y) + } +} +// ---- +// step: memoryStoreRemover +// +// { +// f() +// let z := 100 +// pop(mload(z)) +// if calldataload(0) { pop(keccak256(z, z)) } +// function f() +// { +// let x := 10 +// let y := 20 +// pop(y) +// } +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/complex3.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/complex3.yul new file mode 100644 index 000000000..92fbd4b56 --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/complex3.yul @@ -0,0 +1,25 @@ +{ + let x := 32 + let y := 100 + // can be removed + mstore(x, y) + if calldataload(0) { + let cds := calldatasize() + // Reads from [0, 32), so does not invalidate location x! + pop(call(1000, 0, 100, 0, 32, 64, 0)) + } + +} +// ---- +// step: memoryStoreRemover +// +// { +// let x := 32 +// let y := 100 +// pop(y) +// if calldataload(0) +// { +// let cds := calldatasize() +// pop(call(1000, 0, 100, 0, 32, 64, 0)) +// } +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/complex4.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/complex4.yul new file mode 100644 index 000000000..ee1183435 --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/complex4.yul @@ -0,0 +1,23 @@ +{ + let x := 32 + let y := 100 + // cannot be removed + mstore(x, y) + let i := 1 + for {} lt(i, 10) {i := add(i, 1) } { + // does not read from i, however, we cannot infer this. So, the above mstore + // cannot be removed. + pop(mload(i)) + } +} +// ---- +// step: memoryStoreRemover +// +// { +// let x := 32 +// let y := 100 +// mstore(x, y) +// let i := 1 +// for { } lt(i, 10) { i := add(i, 1) } +// { pop(mload(i)) } +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/complex5.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/complex5.yul new file mode 100644 index 000000000..31ffb8ff5 --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/complex5.yul @@ -0,0 +1,22 @@ +{ + let x := 0 + let y := 50 + // cannot be removed, since z is not in SSA form + mstore(x, y) + + let z := 200 + // z is not in SSA form, so the solver would use a free variable. + z := 100 + pop(mload(z)) +} +// ---- +// step: memoryStoreRemover +// +// { +// let x := 0 +// let y := 50 +// mstore(x, y) +// let z := 200 +// z := 100 +// pop(mload(z)) +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/complex6.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/complex6.yul new file mode 100644 index 000000000..dfa259214 --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/complex6.yul @@ -0,0 +1,22 @@ +{ + let x := 0 + let y := 10 + let i := 0 + for {} iszero(i) {i := add(i, 1)} + { + // can be removed! + mstore(x, i) + } + pop(mload(200)) +} +// ---- +// step: memoryStoreRemover +// +// { +// let x := 0 +// let y := 10 +// let i := 0 +// for { } iszero(i) { i := add(i, 1) } +// { pop(i) } +// pop(mload(200)) +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/complex7.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/complex7.yul new file mode 100644 index 000000000..2c4e41715 --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/complex7.yul @@ -0,0 +1,22 @@ +{ + let x := 0 + let y := 10 + let i := 0 + for {} iszero(i) {i := add(i, 1)} + { + // cannot be removed! + mstore(i, y) + } + pop(mload(200)) +} +// ---- +// step: memoryStoreRemover +// +// { +// let x := 0 +// let y := 10 +// let i := 0 +// for { } iszero(i) { i := add(i, 1) } +// { mstore(i, y) } +// pop(mload(200)) +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/complex8.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/complex8.yul new file mode 100644 index 000000000..1c92f6656 --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/complex8.yul @@ -0,0 +1,19 @@ +{ + let x := 0 + let y := 10 + f(x, y) + function f(a, b) { + // cannot be removed, since a and b are considered as free variables + mstore(a, b) + } +} +// ---- +// step: memoryStoreRemover +// +// { +// let x := 0 +// let y := 10 +// f(x, y) +// function f(a, b) +// { mstore(a, b) } +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/complex9.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/complex9.yul new file mode 100644 index 000000000..a03b75700 --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/complex9.yul @@ -0,0 +1,16 @@ +{ + let x := 0 + let y := 32 + // can be removed + mstore(x, y) + return(0, 0) +} +// ---- +// step: memoryStoreRemover +// +// { +// let x := 0 +// let y := 32 +// pop(y) +// return(0, 0) +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/eip1985.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/eip1985.yul new file mode 100644 index 000000000..3d6463db0 --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/eip1985.yul @@ -0,0 +1,19 @@ +{ + // 2**128 + let x := 340282366920938463463374607431768211456 + // The optimization step will remove the following `mstore`. + // EIP 1985 limits `msize()` to `2**32` and the `mstore` + // beyond the region would result in out of gas. + // By removing `mstore`, we are converting a snippet + // that will be always OOG into one that would execute. + mstore(x, 100) + sstore(0, 10) +} +// ---- +// step: memoryStoreRemover +// +// { +// let x := 340282366920938463463374607431768211456 +// pop(100) +// sstore(0, 10) +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/msize.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/msize.yul new file mode 100644 index 000000000..4553e8788 --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/msize.yul @@ -0,0 +1,15 @@ +// Test to see if the rule is applied in presence of msize +{ + pop(msize()) + let x := 100 + // cannot be removed because of the msize + mstore(x, 100) +} +// ---- +// step: memoryStoreRemover +// +// { +// pop(msize()) +// let x := 100 +// mstore(x, 100) +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/overflow.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/overflow.yul new file mode 100644 index 000000000..f775046e7 --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/overflow.yul @@ -0,0 +1,20 @@ +{ + let x := 0 + let y := 100 + // Actually cannot be removed. + mstore(x, y) + + // Even though this cannot happen in practice, + // we'll unfortunately have to deal with this situation. + // reads from bytes 2*256 - 1, 0, ..., 30 + pop(mload(115792089237316195423570985008687907853269984665640564039457584007913129639935)) +} +// ---- +// step: memoryStoreRemover +// +// { +// let x := 0 +// let y := 100 +// mstore(x, y) +// pop(mload(115792089237316195423570985008687907853269984665640564039457584007913129639935)) +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/overflow_mstore.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/overflow_mstore.yul new file mode 100644 index 000000000..42b67a377 --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/overflow_mstore.yul @@ -0,0 +1,19 @@ +{ + let x := 115792089237316195423570985008687907853269984665640564039457584007913129639935 + let y := 1000 + // Cannot be removed, since it writes to bytes + // 2**256 - 1, 0, 1, ..., 30 + mstore(x, y) + + // reads from [0, 32) + pop(mload(0)) +} +// ---- +// step: memoryStoreRemover +// +// { +// let x := 115792089237316195423570985008687907853269984665640564039457584007913129639935 +// let y := 1000 +// mstore(x, y) +// pop(mload(0)) +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/simple1.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/simple1.yul new file mode 100644 index 000000000..e981a982d --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/simple1.yul @@ -0,0 +1,13 @@ +{ + let x := 10 + let y := 20 + mstore(x, y) +} +// ---- +// step: memoryStoreRemover +// +// { +// let x := 10 +// let y := 20 +// pop(y) +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/simple10.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/simple10.yul new file mode 100644 index 000000000..76bd86ad4 --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/simple10.yul @@ -0,0 +1,29 @@ +{ + let x := 0 + // y is not a SSA Variable + let y := 20 + if calldataload(10) { + y := 100 + } + // The location is not read from. + // Even though the value is not an identifier, let alone an SSA variable. + mstore(x, calldataload(y)) + mstore(x, y) + + // does not read from memory + pop(extcodesize(0)) + // does not read from [0, 32) + log0(100, 200) +} +// ---- +// step: memoryStoreRemover +// +// { +// let x := 0 +// let y := 20 +// if calldataload(10) { y := 100 } +// pop(calldataload(y)) +// pop(y) +// pop(extcodesize(0)) +// log0(100, 200) +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/simple2.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/simple2.yul new file mode 100644 index 000000000..bd3badc64 --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/simple2.yul @@ -0,0 +1,17 @@ +{ + let x := 10 + let y := 60 + // can be removed + mstore(x, y) + // Does not read from [10, 42) + pop(mload(y)) +} +// ---- +// step: memoryStoreRemover +// +// { +// let x := 10 +// let y := 60 +// pop(y) +// pop(mload(y)) +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/simple3.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/simple3.yul new file mode 100644 index 000000000..4a88e91bd --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/simple3.yul @@ -0,0 +1,17 @@ +{ + let x := 10 + let y := 20 + // This should not be removed + mstore(x, y) + // reads from x + pop(mload(x)) +} +// ---- +// step: memoryStoreRemover +// +// { +// let x := 10 +// let y := 20 +// mstore(x, y) +// pop(mload(x)) +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/simple4.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/simple4.yul new file mode 100644 index 000000000..552853c4e --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/simple4.yul @@ -0,0 +1,19 @@ +{ + let x := 10 + let y := 10 + // should not be removed because of the if statement + mstore(x, y) + if calldataload(0) { + // reads inside control flow + pop(mload(x)) + } +} +// ---- +// step: memoryStoreRemover +// +// { +// let x := 10 +// let y := 10 +// mstore(x, y) +// if calldataload(0) { pop(mload(x)) } +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/simple5.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/simple5.yul new file mode 100644 index 000000000..c533eb8fe --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/simple5.yul @@ -0,0 +1,19 @@ +{ + // x is not in SSA form + let x := 10 + if calldataload(0) { + x := 25 + } + let y := 20 + // Should not be removed because x is not in SSA form + mstore(x, y) +} +// ---- +// step: memoryStoreRemover +// +// { +// let x := 10 +// if calldataload(0) { x := 25 } +// let y := 20 +// mstore(x, y) +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/simple6.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/simple6.yul new file mode 100644 index 000000000..19ad7ebf8 --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/simple6.yul @@ -0,0 +1,21 @@ +{ + let x := 10 + let y := 20 + let z := 30 + + // even though `x` is assigned twice, both `mstores` can be removed. + mstore(x, y) + mstore(x, z) + pop(mload(100)) +} +// ---- +// step: memoryStoreRemover +// +// { +// let x := 10 +// let y := 20 +// let z := 30 +// pop(y) +// pop(z) +// pop(mload(100)) +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/simple7.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/simple7.yul new file mode 100644 index 000000000..873e9ee5c --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/simple7.yul @@ -0,0 +1,19 @@ +{ + + let x := 10 + let y := 20 + pop(mload(x)) + + // can't be removed even though nothing is read afterwards, because we'll check reads from the + // entire block. + mstore(x, y) +} +// ---- +// step: memoryStoreRemover +// +// { +// let x := 10 +// let y := 20 +// pop(mload(x)) +// mstore(x, y) +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/simple8.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/simple8.yul new file mode 100644 index 000000000..709ae548e --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/simple8.yul @@ -0,0 +1,21 @@ +{ + f() + function f() { + let x := 10 + let y := 20 + // will never be read, so can be removed + mstore(x, y) + } +} +// ---- +// step: memoryStoreRemover +// +// { +// f() +// function f() +// { +// let x := 10 +// let y := 20 +// pop(y) +// } +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/simple9.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/simple9.yul new file mode 100644 index 000000000..682062ff4 --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/simple9.yul @@ -0,0 +1,24 @@ +{ + f() + pop(mload(16)) + function f() { + let x := 10 + let y := 20 + + // cannot be removed + mstore(x, y) + } +} +// ---- +// step: memoryStoreRemover +// +// { +// f() +// pop(mload(16)) +// function f() +// { +// let x := 10 +// let y := 20 +// mstore(x, y) +// } +// } diff --git a/test/libyul/yulOptimizerTests/memoryStoreRemover/smoke.yul b/test/libyul/yulOptimizerTests/memoryStoreRemover/smoke.yul new file mode 100644 index 000000000..2209e744d --- /dev/null +++ b/test/libyul/yulOptimizerTests/memoryStoreRemover/smoke.yul @@ -0,0 +1,5 @@ +{ } +// ---- +// step: memoryStoreRemover +// +// { }