From 03cbc5f6e73107b7895799dd9d5c9a3b57b59d2c Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Tue, 20 Oct 2020 13:48:50 +0200 Subject: [PATCH] Tests for UnusedReturnParameterPruner --- Changelog.md | 1 + test/cmdlineTests/evm_to_wasm_break/output | 8 ++-- test/libsolidity/StandardCompiler.cpp | 6 +-- test/libyul/YulOptimizerTest.cpp | 7 ++++ .../yulOptimizerTests/fullSuite/abi2.yul | 5 +-- ...usedFunctionReturnParameterPruner_loop.yul | 34 +++++++++++++++++ ...nusedFunctionReturnParameterPruner_pop.yul | 30 +++++++++++++++ ...edFunctionReturnParameterPruner_simple.yul | 22 +++++++++++ ...FunctionReturnParamterPruner_recursion.yul | 30 +++++++++++++++ .../all_return_unused.yul | 26 +++++++++++++ .../all_return_used.yul | 30 +++++++++++++++ .../multiple_return.yul | 26 +++++++++++++ .../pop.yul | 32 ++++++++++++++++ .../should_not_prune.yul | 20 ++++++++++ .../simple.yul | 24 ++++++++++++ .../smoke.yul | 5 +++ .../tricky_unused.yul | 38 +++++++++++++++++++ .../tricky_used.yul | 22 +++++++++++ .../tricky_used_loop.yul | 25 ++++++++++++ .../unusedPruner/pop_function.yul | 15 ++++++++ 20 files changed, 396 insertions(+), 10 deletions(-) create mode 100644 test/libyul/yulOptimizerTests/fullSuite/unusedFunctionReturnParameterPruner_loop.yul create mode 100644 test/libyul/yulOptimizerTests/fullSuite/unusedFunctionReturnParameterPruner_pop.yul create mode 100644 test/libyul/yulOptimizerTests/fullSuite/unusedFunctionReturnParameterPruner_simple.yul create mode 100644 test/libyul/yulOptimizerTests/fullSuite/unusedFunctionReturnParamterPruner_recursion.yul create mode 100644 test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/all_return_unused.yul create mode 100644 test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/all_return_used.yul create mode 100644 test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/multiple_return.yul create mode 100644 test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/pop.yul create mode 100644 test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/should_not_prune.yul create mode 100644 test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/simple.yul create mode 100644 test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/smoke.yul create mode 100644 test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/tricky_unused.yul create mode 100644 test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/tricky_used.yul create mode 100644 test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/tricky_used_loop.yul create mode 100644 test/libyul/yulOptimizerTests/unusedPruner/pop_function.yul diff --git a/Changelog.md b/Changelog.md index 85c71df8e..e4edcbf7e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,7 @@ Compiler Features: * SMTChecker: Support named arguments in function calls. + * Yul Optimizer: Prune return parameters of functions that are unused at callsite. ### 0.7.5 (2020-11-18) diff --git a/test/cmdlineTests/evm_to_wasm_break/output b/test/cmdlineTests/evm_to_wasm_break/output index 3c63bc830..bcbfee231 100644 --- a/test/cmdlineTests/evm_to_wasm_break/output +++ b/test/cmdlineTests/evm_to_wasm_break/output @@ -43,7 +43,7 @@ object "object" { x_7 := x_11 } { - let _5, _6, _7, _8 := iszero_169_788(_1, _1, _1, lt_171(x_4, x_5, x_6, x_7, _1, _1, _1, 10)) + let _5, _6, _7, _8 := iszero_169_864(_1, _1, _1, lt_171(x_4, x_5, x_6, x_7, _1, _1, _1, 10)) if i32.eqz(i64.eqz(i64.or(i64.or(_5, _6), i64.or(_7, _8)))) { break } if i32.eqz(i64.eqz(i64.or(_3, i64.or(_1, eq(x_4, x_5, x_6, x_7, _1, _1, _1, 2))))) { break } if i32.eqz(i64.eqz(i64.or(_3, i64.or(_1, eq(x_4, x_5, x_6, x_7, _1, _1, _1, 4))))) { continue } @@ -67,7 +67,7 @@ object "object" { let r1_1, carry_2 := add_carry(x1, y1, carry_1) r1 := r1_1 } - function iszero_169_788(x1, x2, x3, x4) -> r1, r2, r3, r4 + function iszero_169_864(x1, x2, x3, x4) -> r1, r2, r3, r4 { r4 := i64.extend_i32_u(i64.eqz(i64.or(i64.or(x1, x2), i64.or(x3, x4)))) } @@ -206,7 +206,7 @@ Text representation: (br_if $label__3 (i32.eqz (i32.eqz (local.get $_4)))) (block $label__4 (block - (local.set $_5 (call $iszero_169_788 (local.get $_1) (local.get $_1) (local.get $_1) (call $lt_171 (local.get $x_4) (local.get $x_5) (local.get $x_6) (local.get $x_7) (local.get $_1) (local.get $_1) (local.get $_1) (i64.const 10)))) + (local.set $_5 (call $iszero_169_864 (local.get $_1) (local.get $_1) (local.get $_1) (call $lt_171 (local.get $x_4) (local.get $x_5) (local.get $x_6) (local.get $x_7) (local.get $_1) (local.get $_1) (local.get $_1) (i64.const 10)))) (local.set $_6 (global.get $global_)) (local.set $_7 (global.get $global__1)) (local.set $_8 (global.get $global__2)) @@ -310,7 +310,7 @@ Text representation: (local.get $r1) ) -(func $iszero_169_788 +(func $iszero_169_864 (param $x1 i64) (param $x2 i64) (param $x3 i64) diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index 887e0ac32..fa010192c 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -1396,11 +1396,11 @@ BOOST_AUTO_TEST_CASE(use_stack_optimization) BOOST_REQUIRE(contract["evm"]["bytecode"]["object"].isString()); BOOST_CHECK(contract["evm"]["bytecode"]["object"].asString().length() > 20); - // Now disable stack optimizations and UnusedFunctionParameterPruner (p) - // results in "stack too deep" + // Now disable stack optimizations, UnusedFunctionParameterPruner (p) and + // UnusedFunctionReturnParameterPruner (P). Results in "stack too deep" string optimiserSteps = OptimiserSettings::DefaultYulOptimiserSteps; optimiserSteps.erase( - remove_if(optimiserSteps.begin(), optimiserSteps.end(), [](char ch) { return ch == 'p'; }), + remove_if(optimiserSteps.begin(), optimiserSteps.end(), [](char ch) { return ch == 'p' || ch == 'P'; }), optimiserSteps.end() ); parsedInput["settings"]["optimizer"]["details"]["yulDetails"]["stackAllocation"] = false; diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index e61b5d2d8..7b819689a 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -264,6 +265,12 @@ TestCase::TestResult YulOptimizerTest::run(ostream& _stream, string const& _line LiteralRematerialiser::run(*m_context, *m_object->code); UnusedFunctionParameterPruner::run(*m_context, *m_object->code); } + else if (m_optimizerStep == "unusedFunctionReturnParameterPruner") + { + disambiguate(); + FunctionHoister::run(*m_context, *m_object->code); + UnusedFunctionReturnParameterPruner::run(*m_context, *m_object->code); + } else if (m_optimizerStep == "unusedPruner") { disambiguate(); diff --git a/test/libyul/yulOptimizerTests/fullSuite/abi2.yul b/test/libyul/yulOptimizerTests/fullSuite/abi2.yul index 248fcc661..92ff7ea90 100644 --- a/test/libyul/yulOptimizerTests/fullSuite/abi2.yul +++ b/test/libyul/yulOptimizerTests/fullSuite/abi2.yul @@ -1085,7 +1085,7 @@ // sstore(x1, x0) // sstore(x3, x2) // sstore(1, x4) -// pop(abi_encode_bytes32_t_address_t_uint256_t_bytes32_t_enum$_Operation_t_uint256_t_uint256_t_uint256_t_address_t_address_t_uint(mload(30), mload(31), mload(32), mload(33), mload(34), mload(35), mload(36), mload(37), mload(38), mload(39), mload(40), mload(41))) +// abi_encode_bytes32_t_address_t_uint256_t_bytes32_t_enum$_Operation_t_uint256_t_uint256_t_uint256_t_address_t_address_t_uint_461(mload(30), mload(31), mload(32), mload(33), mload(34), mload(35), mload(36), mload(37), mload(38), mload(39), mload(40), mload(41)) // } // function abi_decode_addresst_uint256t_bytes_calldatat_enum$_Operation(headStart, dataEnd) -> value0, value1, value2, value3, value4 // { @@ -1106,9 +1106,8 @@ // if iszero(lt(_3, 3)) { revert(value4, value4) } // value4 := _3 // } -// function abi_encode_bytes32_t_address_t_uint256_t_bytes32_t_enum$_Operation_t_uint256_t_uint256_t_uint256_t_address_t_address_t_uint(headStart, value10, value9, value8, value7, value6, value5, value4, value3, value2, value1, value0) -> tail +// function abi_encode_bytes32_t_address_t_uint256_t_bytes32_t_enum$_Operation_t_uint256_t_uint256_t_uint256_t_address_t_address_t_uint_461(headStart, value10, value9, value8, value7, value6, value5, value4, value3, value2, value1, value0) // { -// tail := add(headStart, 352) // mstore(headStart, value0) // let _1 := sub(shl(160, 1), 1) // mstore(add(headStart, 32), and(value1, _1)) diff --git a/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionReturnParameterPruner_loop.yul b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionReturnParameterPruner_loop.yul new file mode 100644 index 000000000..3e6d78c3f --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionReturnParameterPruner_loop.yul @@ -0,0 +1,34 @@ +// A test to see if loop condition is properly split +{ + let b := f() + // Return value of f is used in for loop condition. So f cannot be rewritten, + // unless LoopConditionIntoBody and ExpressionSplitter is run. + for {let a := 1} iszero(sub(f(), a)) {a := add(a, 1)} + {} + function f() -> x + { + x := sload(1) + sstore(x, x) + if calldataload(0) { leave } + } +} +// ---- +// step: fullSuite +// +// { +// { +// pop(f()) +// let a := 1 +// let a_1 := a +// for { } true { a_1 := add(a_1, a) } +// { +// if iszero(iszero(sub(f(), a_1))) { break } +// } +// } +// function f() -> x +// { +// x := sload(1) +// sstore(x, x) +// if calldataload(0) { leave } +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionReturnParameterPruner_pop.yul b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionReturnParameterPruner_pop.yul new file mode 100644 index 000000000..4e325407a --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionReturnParameterPruner_pop.yul @@ -0,0 +1,30 @@ +// A test to see if UnusedFunctionReturnParameterPruner can deal with pop +// Expression splitter converts `pop(f(a))` into +// { +// let z := f(a) +// pop(z) +// } +// Unless `pop(z)` is removed, `f` cannot be rewritten. +{ + let a := sload(1) + pop(f(a)) + function f(x) -> y + { + if iszero(calldataload(0)) { leave } + sstore(x, x) + y := sload(x) + } +} +// ---- +// step: fullSuite +// +// { +// { pop(f_17(sload(1))) } +// function f(x) +// { +// if iszero(calldataload(0)) { leave } +// sstore(x, x) +// } +// function f_17(x) -> y +// { f(x) } +// } diff --git a/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionReturnParameterPruner_simple.yul b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionReturnParameterPruner_simple.yul new file mode 100644 index 000000000..d66bd59f5 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionReturnParameterPruner_simple.yul @@ -0,0 +1,22 @@ +{ + let c, d := f(calldataload(0), calldataload(1)) + sstore(c, 1) + function f(x, y) -> a, b + { + // to prevent the function getting inlined + if iszero(calldataload(0)) {leave} + a := sload(x) + b := sload(y) + } +} +// ---- +// step: fullSuite +// +// { +// { sstore(f(calldataload(0)), 1) } +// function f(x) -> a +// { +// if iszero(calldataload(a)) { leave } +// a := sload(x) +// } +// } diff --git a/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionReturnParamterPruner_recursion.yul b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionReturnParamterPruner_recursion.yul new file mode 100644 index 000000000..31f9a05b0 --- /dev/null +++ b/test/libyul/yulOptimizerTests/fullSuite/unusedFunctionReturnParamterPruner_recursion.yul @@ -0,0 +1,30 @@ +{ + // second return paramter is unused + let j, k, l := f(1, 2, 3) + sstore(0, j) + sstore(1, l) + function f(a, b, c) -> x, y, z + { + // second return parameter is unused + let x_1, y_1, z_1 := f(1, 2, 3) + x := x_1 + z := z_1 + x := add(x, 1) + } +} +// ---- +// step: fullSuite +// +// { +// { +// let x, z := f() +// sstore(0, x) +// sstore(1, z) +// } +// function f() -> x, z +// { +// let x_1, z_1 := f() +// z := z_1 +// x := add(x_1, 1) +// } +// } diff --git a/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/all_return_unused.yul b/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/all_return_unused.yul new file mode 100644 index 000000000..2c6567e65 --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/all_return_unused.yul @@ -0,0 +1,26 @@ +{ + let a, b, c := f(sload(0)) + function f(d) -> x, y, z + { + y := mload(d) + z := mload(2) + sstore(y, z) + } +} +// ---- +// step: unusedFunctionReturnParameterPruner +// +// { +// let a, b, c := f_1(sload(0)) +// function f(d) +// { +// let x +// let y +// let z +// y := mload(d) +// z := mload(2) +// sstore(y, z) +// } +// function f_1(d_2) -> x_3, y_4, z_5 +// { f(d_2) } +// } diff --git a/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/all_return_used.yul b/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/all_return_used.yul new file mode 100644 index 000000000..4113affbd --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/all_return_used.yul @@ -0,0 +1,30 @@ +// A test where the function should not be rewritten, since each parameter is used eventually. +{ + let a, b, c := f(sload(0)) + sstore(a, 0) + let a1, b1, c1 := f(sload(2)) + sstore(b1, 0) + let a2, b2, c3 := f(sload(3)) + sstore(c3, 0) + function f(d) -> x, y, z + { + y := mload(d) + z := mload(2) + } +} +// ---- +// step: unusedFunctionReturnParameterPruner +// +// { +// let a, b, c := f(sload(0)) +// sstore(a, 0) +// let a1, b1, c1 := f(sload(2)) +// sstore(b1, 0) +// let a2, b2, c3 := f(sload(3)) +// sstore(c3, 0) +// function f(d) -> x, y, z +// { +// y := mload(d) +// z := mload(2) +// } +// } diff --git a/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/multiple_return.yul b/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/multiple_return.yul new file mode 100644 index 000000000..c5f3d3b18 --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/multiple_return.yul @@ -0,0 +1,26 @@ +{ + // b and c are unused + let a, b, c := f(sload(0)) + sstore(a, 0) + function f(d) -> x, y, z + { + y := mload(d) + z := mload(2) + } +} +// ---- +// step: unusedFunctionReturnParameterPruner +// +// { +// let a, b, c := f_1(sload(0)) +// sstore(a, 0) +// function f(d) -> x +// { +// let y +// let z +// y := mload(d) +// z := mload(2) +// } +// function f_1(d_2) -> x_3, y_4, z_5 +// { x_3 := f(d_2) } +// } diff --git a/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/pop.yul b/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/pop.yul new file mode 100644 index 000000000..dae6430a2 --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/pop.yul @@ -0,0 +1,32 @@ +// A test to see if the optimization step can deal with pop +// Expression splitter converts `pop(f(a))` into +// { +// let z := f(a) +// pop(z) +// } +// Unless `pop(z)` is removed, `f` cannot be rewritten. +{ + let a := sload(1) + let z := f(a) + pop(z) + function f(x) -> y + { + sstore(x, x) + y := sload(x) + } +} +// ---- +// step: unusedFunctionReturnParameterPruner +// +// { +// let a := sload(1) +// let z := f_1(a) +// function f(x) +// { +// let y +// sstore(x, x) +// y := sload(x) +// } +// function f_1(x_2) -> y_3 +// { f(x_2) } +// } diff --git a/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/should_not_prune.yul b/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/should_not_prune.yul new file mode 100644 index 000000000..627fd7935 --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/should_not_prune.yul @@ -0,0 +1,20 @@ +// An example where the return parameter of the function should not be pruned +{ + function f() -> y { + y := sload(1) + } + + // return value is unused here + let x := f() + // return value is used here, so f cannot be pruned. + sstore(1, f()) +} +// ---- +// step: unusedFunctionReturnParameterPruner +// +// { +// let x := f() +// sstore(1, f()) +// function f() -> y +// { y := sload(1) } +// } diff --git a/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/simple.yul b/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/simple.yul new file mode 100644 index 000000000..c45342a67 --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/simple.yul @@ -0,0 +1,24 @@ +{ + let c, d := f(1, 2) + sstore(c, 1) + function f(x, y) -> a, b + { + a := sload(x) + b := sload(y) + } +} +// ---- +// step: unusedFunctionReturnParameterPruner +// +// { +// let c, d := f_1(1, 2) +// sstore(c, 1) +// function f(x, y) -> a +// { +// let b +// a := sload(x) +// b := sload(y) +// } +// function f_1(x_2, y_3) -> a_4, b_5 +// { a_4 := f(x_2, y_3) } +// } diff --git a/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/smoke.yul b/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/smoke.yul new file mode 100644 index 000000000..5a969a511 --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/smoke.yul @@ -0,0 +1,5 @@ +{ } +// ---- +// step: unusedFunctionReturnParameterPruner +// +// { } diff --git a/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/tricky_unused.yul b/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/tricky_unused.yul new file mode 100644 index 000000000..cc60e71f8 --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/tricky_unused.yul @@ -0,0 +1,38 @@ +{ + // The third and the last return value is unused + let a, b, c, d, e := f(sload(0)) + sstore(a, b) + let a1, b1, c1, d1, e1 := f(sload(1)) + sstore(a1, d1) + let a2, b2, c2, d2, e2 := f(sload(2)) + sstore(d2, b2) + function f(a_1) -> v, w, x, y, z + { + w := mload(a_1) + y := mload(w) + z := mload(y) + sstore(y, z) + } +} +// ---- +// step: unusedFunctionReturnParameterPruner +// +// { +// let a, b, c, d, e := f_1(sload(0)) +// sstore(a, b) +// let a1, b1, c1, d1, e1 := f_1(sload(1)) +// sstore(a1, d1) +// let a2, b2, c2, d2, e2 := f_1(sload(2)) +// sstore(d2, b2) +// function f(a_1) -> v, w, y +// { +// let x +// let z +// w := mload(a_1) +// y := mload(w) +// z := mload(y) +// sstore(y, z) +// } +// function f_1(a_1_2) -> v_3, w_4, x_5, y_6, z_7 +// { v_3, w_4, y_6 := f(a_1_2) } +// } diff --git a/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/tricky_used.yul b/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/tricky_used.yul new file mode 100644 index 000000000..4e489ee79 --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/tricky_used.yul @@ -0,0 +1,22 @@ +{ + let a := f() + // Return value of f is used here. So f cannot be rewritten. + sstore(sload(f()), 2) + function f() -> x + { + x := sload(1) + sstore(x, x) + } +} +// ---- +// step: unusedFunctionReturnParameterPruner +// +// { +// let a := f() +// sstore(sload(f()), 2) +// function f() -> x +// { +// x := sload(1) +// sstore(x, x) +// } +// } diff --git a/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/tricky_used_loop.yul b/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/tricky_used_loop.yul new file mode 100644 index 000000000..1cd77f102 --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedFunctionReturnParameterPruner/tricky_used_loop.yul @@ -0,0 +1,25 @@ +// A test to see if loop condition is properly split +{ + let b := f() + // Return value of f is used in for loop condition. So f cannot be rewritten. + for {let a := 1} iszero(sub(f(), a)) {a := add(a, 1)} + {} + function f() -> x + { + x := sload(1) + sstore(x, x) + } +} +// ---- +// step: unusedFunctionReturnParameterPruner +// +// { +// let b := f() +// for { let a := 1 } iszero(sub(f(), a)) { a := add(a, 1) } +// { } +// function f() -> x +// { +// x := sload(1) +// sstore(x, x) +// } +// } diff --git a/test/libyul/yulOptimizerTests/unusedPruner/pop_function.yul b/test/libyul/yulOptimizerTests/unusedPruner/pop_function.yul new file mode 100644 index 000000000..32ce68b95 --- /dev/null +++ b/test/libyul/yulOptimizerTests/unusedPruner/pop_function.yul @@ -0,0 +1,15 @@ +{ + let a := f() + pop(a) + function f() -> y { + sstore(1, sload(1)) + } +} +// ---- +// step: unusedPruner +// +// { +// pop(f()) +// function f() -> y +// { sstore(1, sload(1)) } +// }