Unused store eliminator.

This commit is contained in:
chriseth
2022-02-15 11:03:44 +01:00
parent 6c36638624
commit 1c3a5c7373
66 changed files with 1113 additions and 129 deletions
+10
View File
@@ -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() }
// }