mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Yul tests for MemoryStoreRemover
This commit is contained in:
parent
ed5fae9183
commit
f6a82f8efa
@ -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))
|
||||
// }
|
||||
@ -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)) }
|
||||
// }
|
||||
@ -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)
|
||||
// }
|
||||
// }
|
||||
@ -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))
|
||||
// }
|
||||
// }
|
||||
@ -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)) }
|
||||
// }
|
||||
@ -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))
|
||||
// }
|
||||
@ -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))
|
||||
// }
|
||||
@ -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))
|
||||
// }
|
||||
@ -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) }
|
||||
// }
|
||||
@ -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)
|
||||
// }
|
||||
19
test/libyul/yulOptimizerTests/memoryStoreRemover/eip1985.yul
Normal file
19
test/libyul/yulOptimizerTests/memoryStoreRemover/eip1985.yul
Normal file
@ -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)
|
||||
// }
|
||||
15
test/libyul/yulOptimizerTests/memoryStoreRemover/msize.yul
Normal file
15
test/libyul/yulOptimizerTests/memoryStoreRemover/msize.yul
Normal file
@ -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)
|
||||
// }
|
||||
@ -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))
|
||||
// }
|
||||
@ -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))
|
||||
// }
|
||||
13
test/libyul/yulOptimizerTests/memoryStoreRemover/simple1.yul
Normal file
13
test/libyul/yulOptimizerTests/memoryStoreRemover/simple1.yul
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
let x := 10
|
||||
let y := 20
|
||||
mstore(x, y)
|
||||
}
|
||||
// ----
|
||||
// step: memoryStoreRemover
|
||||
//
|
||||
// {
|
||||
// let x := 10
|
||||
// let y := 20
|
||||
// pop(y)
|
||||
// }
|
||||
@ -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)
|
||||
// }
|
||||
17
test/libyul/yulOptimizerTests/memoryStoreRemover/simple2.yul
Normal file
17
test/libyul/yulOptimizerTests/memoryStoreRemover/simple2.yul
Normal file
@ -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))
|
||||
// }
|
||||
17
test/libyul/yulOptimizerTests/memoryStoreRemover/simple3.yul
Normal file
17
test/libyul/yulOptimizerTests/memoryStoreRemover/simple3.yul
Normal file
@ -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))
|
||||
// }
|
||||
19
test/libyul/yulOptimizerTests/memoryStoreRemover/simple4.yul
Normal file
19
test/libyul/yulOptimizerTests/memoryStoreRemover/simple4.yul
Normal file
@ -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)) }
|
||||
// }
|
||||
19
test/libyul/yulOptimizerTests/memoryStoreRemover/simple5.yul
Normal file
19
test/libyul/yulOptimizerTests/memoryStoreRemover/simple5.yul
Normal file
@ -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)
|
||||
// }
|
||||
21
test/libyul/yulOptimizerTests/memoryStoreRemover/simple6.yul
Normal file
21
test/libyul/yulOptimizerTests/memoryStoreRemover/simple6.yul
Normal file
@ -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))
|
||||
// }
|
||||
19
test/libyul/yulOptimizerTests/memoryStoreRemover/simple7.yul
Normal file
19
test/libyul/yulOptimizerTests/memoryStoreRemover/simple7.yul
Normal file
@ -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)
|
||||
// }
|
||||
21
test/libyul/yulOptimizerTests/memoryStoreRemover/simple8.yul
Normal file
21
test/libyul/yulOptimizerTests/memoryStoreRemover/simple8.yul
Normal file
@ -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)
|
||||
// }
|
||||
// }
|
||||
24
test/libyul/yulOptimizerTests/memoryStoreRemover/simple9.yul
Normal file
24
test/libyul/yulOptimizerTests/memoryStoreRemover/simple9.yul
Normal file
@ -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)
|
||||
// }
|
||||
// }
|
||||
@ -0,0 +1,5 @@
|
||||
{ }
|
||||
// ----
|
||||
// step: memoryStoreRemover
|
||||
//
|
||||
// { }
|
||||
Loading…
Reference in New Issue
Block a user