mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Unused store eliminator.
This commit is contained in:
@@ -54,6 +54,7 @@
|
||||
#include <libyul/optimiser/SSATransform.h>
|
||||
#include <libyul/optimiser/Semantics.h>
|
||||
#include <libyul/optimiser/UnusedAssignEliminator.h>
|
||||
#include <libyul/optimiser/UnusedStoreEliminator.h>
|
||||
#include <libyul/optimiser/StructuralSimplifier.h>
|
||||
#include <libyul/optimiser/StackCompressor.h>
|
||||
#include <libyul/optimiser/Suite.h>
|
||||
@@ -237,6 +238,15 @@ YulOptimizerTestCommon::YulOptimizerTestCommon(
|
||||
ForLoopInitRewriter::run(*m_context, *m_ast);
|
||||
UnusedAssignEliminator::run(*m_context, *m_ast);
|
||||
}},
|
||||
{"unusedStoreEliminator", [&]() {
|
||||
disambiguate();
|
||||
ForLoopInitRewriter::run(*m_context, *m_ast);
|
||||
ExpressionSplitter::run(*m_context, *m_ast);
|
||||
SSATransform::run(*m_context, *m_ast);
|
||||
UnusedStoreEliminator::run(*m_context, *m_ast);
|
||||
SSAReverser::run(*m_context, *m_ast);
|
||||
ExpressionJoiner::run(*m_context, *m_ast);
|
||||
}},
|
||||
{"equalStoreEliminator", [&]() {
|
||||
disambiguate();
|
||||
FunctionHoister::run(*m_context, *m_ast);
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
let _1 := 0
|
||||
let value := calldataload(4)
|
||||
if iszero(eq(value, and(value, sub(shl(160, 1), 1)))) { revert(_1, _1) }
|
||||
let length := extcodesize(value)
|
||||
let _2 := 0xffffffffffffffff
|
||||
if gt(length, _2) { revert(0, 0) }
|
||||
let _3 := not(31)
|
||||
let memPtr := mload(64)
|
||||
let newFreePtr := add(memPtr, and(add(and(add(length, 31), _3), 63), _3))
|
||||
if or(gt(newFreePtr, _2), lt(newFreePtr, memPtr)) { revert(0, 0) }
|
||||
mstore(64, newFreePtr)
|
||||
mstore(memPtr, length)
|
||||
|
||||
// We aim to optimize this out.
|
||||
extcodecopy(value, add(memPtr, 32), _1, length)
|
||||
sstore(_1, mload(memPtr))
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >byzantium
|
||||
// ----
|
||||
// step: fullSuite
|
||||
//
|
||||
// {
|
||||
// {
|
||||
// let value := calldataload(4)
|
||||
// if iszero(eq(value, and(value, sub(shl(160, 1), 1)))) { revert(0, 0) }
|
||||
// let length := extcodesize(value)
|
||||
// let _1 := 0xffffffffffffffff
|
||||
// if gt(length, _1) { revert(0, 0) }
|
||||
// let memPtr := mload(64)
|
||||
// let _2 := not(31)
|
||||
// let newFreePtr := add(memPtr, and(add(and(add(length, 31), _2), 63), _2))
|
||||
// if or(gt(newFreePtr, _1), lt(newFreePtr, memPtr)) { revert(0, 0) }
|
||||
// sstore(0, length)
|
||||
// }
|
||||
// }
|
||||
@@ -23,13 +23,7 @@
|
||||
//
|
||||
// {
|
||||
// {
|
||||
// let p := mload(0x40)
|
||||
// mstore(0x40, add(p, 0x20))
|
||||
// mstore(0x40, add(p, 96))
|
||||
// let p_1 := add(p, 128)
|
||||
// mstore(p_1, 2)
|
||||
// mstore(0x40, 0x20)
|
||||
// sstore(0, p_1)
|
||||
// sstore(0, add(mload(0x40), 128))
|
||||
// sstore(1, 0x20)
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -15,6 +15,5 @@
|
||||
// case 0 { }
|
||||
// case 1 { }
|
||||
// default { invalid() }
|
||||
// mstore(1, 1)
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -52,7 +52,6 @@
|
||||
// pop(keccak256(gcd(_3, _2), or(gt(not(gcd(_3, _2)), _1), _1)))
|
||||
// mstore(lt(or(gt(_1, or(or(gt(or(or(or(gt(or(gt(_6, _9), _1), _8), _7), _5), _1), _1), _4), _1)), _1), _1), _1)
|
||||
// sstore(not(gcd(_3, _2)), _1)
|
||||
// sstore(0, 0)
|
||||
// sstore(2, _1)
|
||||
// extcodecopy(_1, msize(), _1, _1)
|
||||
// sstore(3, _1)
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
// mstore(4, 0x32)
|
||||
// revert(_1, 0x24)
|
||||
// }
|
||||
// mstore(_1, _1)
|
||||
// sstore(0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56d, 0x05)
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
//
|
||||
// {
|
||||
// {
|
||||
// sstore(4, 5)
|
||||
// sstore(4, 3)
|
||||
// sstore(8, 3)
|
||||
// }
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
// {
|
||||
// {
|
||||
// let out1, out2 := foo(sload(32))
|
||||
// sstore(0, out1)
|
||||
// sstore(0, out2)
|
||||
// let out1_1, out2_1 := foo(sload(8))
|
||||
// }
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
// {
|
||||
// {
|
||||
// f()
|
||||
// sstore(0, 1)
|
||||
// f()
|
||||
// f()
|
||||
// }
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
// {
|
||||
// let x, y, z := f()
|
||||
// sstore(0, x)
|
||||
// sstore(1, y)
|
||||
// sstore(1, z)
|
||||
// }
|
||||
// function f() -> x, y, z
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
// {
|
||||
// {
|
||||
// let out1, out2 := foo(sload(32))
|
||||
// sstore(0, out1)
|
||||
// sstore(0, out2)
|
||||
// sstore(0, 0)
|
||||
// let out1_1, out2_1 := foo(sload(8))
|
||||
// }
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
// {
|
||||
// {
|
||||
// f()
|
||||
// sstore(0, 1)
|
||||
// f()
|
||||
// f()
|
||||
// }
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
{
|
||||
let start := calldataload(0x10)
|
||||
if calldataload(0) {
|
||||
// not covered
|
||||
mstore(add(start, 2), 7)
|
||||
calldatacopy(start, 0, 0x20)
|
||||
}
|
||||
if calldataload(1) {
|
||||
// covered
|
||||
mstore(add(start, 2), 9)
|
||||
calldatacopy(add(start, 1), 0, 0x21)
|
||||
}
|
||||
if calldataload(2) {
|
||||
// covered
|
||||
mstore8(add(start, 2), 7)
|
||||
calldatacopy(start, 0, 3)
|
||||
}
|
||||
if calldataload(3) {
|
||||
// not covered
|
||||
mstore8(add(start, 3), 7)
|
||||
calldatacopy(start, 0, 3)
|
||||
}
|
||||
sstore(0, keccak256(start, 0x40))
|
||||
}
|
||||
// ----
|
||||
// step: unusedStoreEliminator
|
||||
//
|
||||
// {
|
||||
// {
|
||||
// let start := calldataload(0x10)
|
||||
// if calldataload(0)
|
||||
// {
|
||||
// let _4 := 7
|
||||
// mstore(add(start, 2), _4)
|
||||
// calldatacopy(start, 0, 0x20)
|
||||
// }
|
||||
// if calldataload(1)
|
||||
// {
|
||||
// let _11 := 9
|
||||
// let _13 := add(start, 2)
|
||||
// let _14 := 0x21
|
||||
// let _15 := 0
|
||||
// calldatacopy(add(start, 1), _15, _14)
|
||||
// }
|
||||
// if calldataload(2)
|
||||
// {
|
||||
// let _20 := 7
|
||||
// let _22 := add(start, 2)
|
||||
// calldatacopy(start, 0, 3)
|
||||
// }
|
||||
// if calldataload(3)
|
||||
// {
|
||||
// let _27 := 7
|
||||
// mstore8(add(start, 3), _27)
|
||||
// calldatacopy(start, 0, 3)
|
||||
// }
|
||||
// sstore(0, keccak256(start, 0x40))
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
sstore(5, 10)
|
||||
pop(create(0, 0, 0))
|
||||
sstore(5, 20)
|
||||
}
|
||||
// ----
|
||||
// step: unusedStoreEliminator
|
||||
//
|
||||
// {
|
||||
// {
|
||||
// sstore(5, 10)
|
||||
// pop(create(0, 0, 0))
|
||||
// sstore(5, 20)
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
function f() {
|
||||
let x := calldataload(2)
|
||||
sstore(x, 2)
|
||||
// This cannot be removed because we do not know what happens after the function.
|
||||
sstore(x, 3)
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// step: unusedStoreEliminator
|
||||
//
|
||||
// {
|
||||
// { }
|
||||
// function f()
|
||||
// {
|
||||
// let x := calldataload(2)
|
||||
// let _2 := 2
|
||||
// sstore(x, 3)
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,55 @@
|
||||
{
|
||||
function justStop() { return(0, 0) }
|
||||
function justRevert() { revert(0, 0) }
|
||||
|
||||
let x := 0
|
||||
let y := 1
|
||||
let a := 0x80
|
||||
let b := 7
|
||||
let c := 9
|
||||
switch calldataload(0)
|
||||
case 0
|
||||
{
|
||||
sstore(x, y)
|
||||
mstore(a, b)
|
||||
justStop()
|
||||
sstore(x, y)
|
||||
mstore(a, b)
|
||||
}
|
||||
case 1
|
||||
{
|
||||
sstore(x, y)
|
||||
mstore(a, b)
|
||||
justRevert()
|
||||
sstore(x, y)
|
||||
mstore(a, b)
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// step: unusedStoreEliminator
|
||||
//
|
||||
// {
|
||||
// {
|
||||
// let x := 0
|
||||
// let y := 1
|
||||
// let a := 0x80
|
||||
// let b := 7
|
||||
// let c := 9
|
||||
// switch calldataload(0)
|
||||
// case 0 {
|
||||
// sstore(x, y)
|
||||
// mstore(a, b)
|
||||
// justStop()
|
||||
// sstore(x, y)
|
||||
// }
|
||||
// case 1 {
|
||||
// mstore(a, b)
|
||||
// justRevert()
|
||||
// sstore(x, y)
|
||||
// }
|
||||
// }
|
||||
// function justStop()
|
||||
// { return(0, 0) }
|
||||
// function justRevert()
|
||||
// { revert(0, 0) }
|
||||
// }
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
let x := 0
|
||||
let y := 1
|
||||
sstore(x, y)
|
||||
f()
|
||||
sstore(x, y)
|
||||
function f() {
|
||||
// prevent inlining
|
||||
f()
|
||||
return(0, 0)
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// step: unusedStoreEliminator
|
||||
//
|
||||
// {
|
||||
// {
|
||||
// let x := 0
|
||||
// let y := 1
|
||||
// f()
|
||||
// sstore(x, y)
|
||||
// }
|
||||
// function f()
|
||||
// {
|
||||
// f()
|
||||
// return(0, 0)
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
let c := calldataload(0)
|
||||
// This store will be overwritten in all branches and thus can be removed.
|
||||
sstore(c, 1)
|
||||
if c {
|
||||
sstore(c, 2)
|
||||
}
|
||||
sstore(c, 3)
|
||||
}
|
||||
// ----
|
||||
// step: unusedStoreEliminator
|
||||
//
|
||||
// {
|
||||
// {
|
||||
// let c := calldataload(0)
|
||||
// let _2 := 1
|
||||
// if c { let _3 := 2 }
|
||||
// sstore(c, 3)
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
function f() {
|
||||
mstore(0, 5)
|
||||
if calldataload(0) { leave }
|
||||
mstore(0x20, 5)
|
||||
revert(0, 0)
|
||||
}
|
||||
f()
|
||||
}
|
||||
// ----
|
||||
// step: unusedStoreEliminator
|
||||
//
|
||||
// {
|
||||
// { f() }
|
||||
// function f()
|
||||
// {
|
||||
// mstore(0, 5)
|
||||
// if calldataload(0) { leave }
|
||||
// let _5 := 5
|
||||
// let _6 := 0x20
|
||||
// revert(0, 0)
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
mstore(0x40, memoryguard(100))
|
||||
let free_mem_ptr := mload(0x40)
|
||||
// redundant
|
||||
mstore(free_mem_ptr, 100)
|
||||
// redundant
|
||||
mstore8(add(free_mem_ptr, 31), 200)
|
||||
mstore(free_mem_ptr, 300)
|
||||
return(free_mem_ptr, add(free_mem_ptr, 100))
|
||||
}
|
||||
// ----
|
||||
// step: unusedStoreEliminator
|
||||
//
|
||||
// {
|
||||
// {
|
||||
// mstore(0x40, memoryguard(100))
|
||||
// let free_mem_ptr := mload(0x40)
|
||||
// let _4 := 100
|
||||
// let _5 := 200
|
||||
// let _7 := add(free_mem_ptr, 31)
|
||||
// mstore(free_mem_ptr, 300)
|
||||
// return(free_mem_ptr, add(free_mem_ptr, 100))
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
mstore(0, 5)
|
||||
let x := mload(0)
|
||||
mstore(0, 8)
|
||||
let y := mload(0)
|
||||
sstore(0, y)
|
||||
}
|
||||
// ----
|
||||
// step: unusedStoreEliminator
|
||||
//
|
||||
// {
|
||||
// {
|
||||
// mstore(0, 5)
|
||||
// let x := mload(0)
|
||||
// mstore(0, 8)
|
||||
// sstore(0, mload(0))
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
let x := 0
|
||||
|
||||
calldatacopy(0, 0, 115792089237316195423570985008687907853269984665640564039457584007913129639935)
|
||||
mstore(x, 20)
|
||||
return(0, 32)
|
||||
}
|
||||
// ----
|
||||
// step: unusedStoreEliminator
|
||||
//
|
||||
// {
|
||||
// {
|
||||
// let x := 0
|
||||
// calldatacopy(0, 0, 115792089237316195423570985008687907853269984665640564039457584007913129639935)
|
||||
// mstore(x, 20)
|
||||
// return(0, 32)
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
let _1 := 0
|
||||
if callvalue() { revert(_1, _1) }
|
||||
mstore(_1, shl(224, 0x4e487b71))
|
||||
mstore(4, 0x32)
|
||||
revert(_1, 0x24)
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >=constantinople
|
||||
// ----
|
||||
// step: unusedStoreEliminator
|
||||
//
|
||||
// {
|
||||
// {
|
||||
// let _1 := 0
|
||||
// if callvalue() { revert(_1, _1) }
|
||||
// mstore(_1, shl(224, 0x4e487b71))
|
||||
// mstore(4, 0x32)
|
||||
// revert(_1, 0x24)
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
let _1 := 0
|
||||
let _2 := callvalue()
|
||||
let _3 := 0x4e487b71
|
||||
let _4 := 224
|
||||
let _5 := 7
|
||||
mstore(_1, _5)
|
||||
let _6 := 0x32
|
||||
let _7 := 4
|
||||
mstore(_7, _6)
|
||||
let _8 := 0x24
|
||||
revert(_1, _8)
|
||||
}
|
||||
// ----
|
||||
// step: unusedStoreEliminator
|
||||
//
|
||||
// {
|
||||
// {
|
||||
// let _1 := 0
|
||||
// let _2 := callvalue()
|
||||
// let _3 := 0x4e487b71
|
||||
// let _4 := 224
|
||||
// mstore(_1, 7)
|
||||
// mstore(4, 0x32)
|
||||
// revert(_1, 0x24)
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
let c := calldataload(0)
|
||||
mstore(c, 4)
|
||||
if c {
|
||||
sstore(c, 2)
|
||||
}
|
||||
let d := 0
|
||||
revert(d, d)
|
||||
}
|
||||
// ----
|
||||
// step: unusedStoreEliminator
|
||||
//
|
||||
// {
|
||||
// {
|
||||
// let c := calldataload(0)
|
||||
// let _2 := 4
|
||||
// if c { let _3 := 2 }
|
||||
// let d := 0
|
||||
// revert(d, d)
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
let a
|
||||
switch calldataload(0)
|
||||
case 0 { a := calldataload(9) }
|
||||
case 1 { a := calldataload(10) }
|
||||
|
||||
calldatacopy(0x20, 0, a)
|
||||
let x := mload(0)
|
||||
sstore(0, x)
|
||||
}
|
||||
// ----
|
||||
// step: unusedStoreEliminator
|
||||
//
|
||||
// {
|
||||
// {
|
||||
// let a_9
|
||||
// let a := a_9
|
||||
// switch calldataload(0)
|
||||
// case 0 {
|
||||
// a := calldataload(9)
|
||||
// let a_10 := a
|
||||
// }
|
||||
// case 1 {
|
||||
// let a_12 := a
|
||||
// a := calldataload(10)
|
||||
// let a_11 := a
|
||||
// }
|
||||
// let a_13 := a
|
||||
// let _5 := 0
|
||||
// let _6 := 0x20
|
||||
// sstore(0, mload(0))
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
let c := calldataload(0)
|
||||
mstore(c, 4)
|
||||
mstore(add(c, 0x20), 8)
|
||||
sstore(0, mload(c))
|
||||
mstore(c, 9)
|
||||
mstore(add(c, 0x20), 20)
|
||||
}
|
||||
// ----
|
||||
// step: unusedStoreEliminator
|
||||
//
|
||||
// {
|
||||
// {
|
||||
// let c := calldataload(0)
|
||||
// mstore(c, 4)
|
||||
// let _3 := 8
|
||||
// let _5 := add(c, 0x20)
|
||||
// sstore(0, mload(c))
|
||||
// let _8 := 9
|
||||
// let _9 := 20
|
||||
// let _11 := add(c, 0x20)
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
sstore(0, 1)
|
||||
mstore(0, 2)
|
||||
f()
|
||||
function f() {
|
||||
g()
|
||||
}
|
||||
function g() {
|
||||
f()
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// step: unusedStoreEliminator
|
||||
//
|
||||
// {
|
||||
// {
|
||||
// let _1 := 1
|
||||
// let _2 := 0
|
||||
// let _3 := 2
|
||||
// let _4 := 0
|
||||
// f()
|
||||
// }
|
||||
// function f()
|
||||
// { g() }
|
||||
// function g()
|
||||
// { f() }
|
||||
// }
|
||||
Reference in New Issue
Block a user