From 33ac415f7fd3e05727959d2fd4963910f2763ab8 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 11 Oct 2018 14:48:57 +0200 Subject: Move common subexpression eliminator tests. --- test/libjulia/CommonSubexpression.cpp | 102 --------------------- test/libjulia/YulOptimizerTest.cpp | 7 ++ .../commonSubexpressionEliminator/branches_for.yul | 24 +++++ .../commonSubexpressionEliminator/branches_if.yul | 15 +++ .../non_movable_instr.yul | 10 ++ .../non_movable_instr2.yul | 10 ++ .../commonSubexpressionEliminator/smoke.yul | 5 + .../commonSubexpressionEliminator/trivial.yul | 10 ++ 8 files changed, 81 insertions(+), 102 deletions(-) delete mode 100644 test/libjulia/CommonSubexpression.cpp create mode 100644 test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/branches_for.yul create mode 100644 test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/branches_if.yul create mode 100644 test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr.yul create mode 100644 test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr2.yul create mode 100644 test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/smoke.yul create mode 100644 test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/trivial.yul diff --git a/test/libjulia/CommonSubexpression.cpp b/test/libjulia/CommonSubexpression.cpp deleted file mode 100644 index 6c8edf1f..00000000 --- a/test/libjulia/CommonSubexpression.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** - * Unit tests for the common subexpression eliminator optimizer stage. - */ - -#include - -#include - -#include - -#include - -#include -#include - -using namespace std; -using namespace dev; -using namespace dev::julia; -using namespace dev::julia::test; -using namespace dev::solidity; - - -#define CHECK(_original, _expectation)\ -do\ -{\ - assembly::AsmPrinter p;\ - Block b = disambiguate(_original, false);\ - (CommonSubexpressionEliminator{})(b);\ - string result = p(b);\ - BOOST_CHECK_EQUAL(result, format(_expectation, false));\ -}\ -while(false) - -BOOST_AUTO_TEST_SUITE(YulCSE) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - CHECK("{ }", "{ }"); -} - -BOOST_AUTO_TEST_CASE(trivial) -{ - CHECK( - "{ let a := mul(1, codesize()) let b := mul(1, codesize()) }", - "{ let a := mul(1, codesize()) let b := a }" - ); -} - -BOOST_AUTO_TEST_CASE(non_movable_instr) -{ - CHECK( - "{ let a := mload(1) let b := mload(1) }", - "{ let a := mload(1) let b := mload(1) }" - ); -} - -BOOST_AUTO_TEST_CASE(non_movable_instr2) -{ - CHECK( - "{ let a := gas() let b := gas() }", - "{ let a := gas() let b := gas() }" - ); -} - -BOOST_AUTO_TEST_CASE(branches_if) -{ - CHECK( - "{ let b := 1 if b { b := 1 } let c := 1 }", - "{ let b := 1 if b { b := b } let c := 1 }" - ); -} - -BOOST_AUTO_TEST_CASE(branches_for) -{ - CHECK( - "{ let a := 1 let b := codesize()" - "for { } lt(1, codesize()) { mstore(1, codesize()) a := add(a, codesize()) }" - "{ mstore(1, codesize()) } mstore(1, codesize()) }", - - "{ let a := 1 let b := codesize()" - "for { } lt(1, b) { mstore(1, b) a := add(a, b) }" - "{ mstore(1, b) } mstore(1, b) }" - ); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libjulia/YulOptimizerTest.cpp b/test/libjulia/YulOptimizerTest.cpp index fd15623c..75a3d69b 100644 --- a/test/libjulia/YulOptimizerTest.cpp +++ b/test/libjulia/YulOptimizerTest.cpp @@ -22,6 +22,8 @@ #include #include +#include + #include #include #include @@ -80,6 +82,11 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con if (m_optimizerStep == "disambiguator") disambiguate(); + else if (m_optimizerStep == "commonSubexpressionEliminator") + { + disambiguate(); + (CommonSubexpressionEliminator{})(*m_ast); + } else { FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Invalid optimizer step: " << m_optimizerStep << endl; diff --git a/test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/branches_for.yul b/test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/branches_for.yul new file mode 100644 index 00000000..c59bced7 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/branches_for.yul @@ -0,0 +1,24 @@ +{ + let a := 1 let b := codesize() + for { } lt(1, codesize()) { mstore(1, codesize()) a := add(a, codesize()) } { + mstore(1, codesize()) + } + mstore(1, codesize()) +} +// ---- +// commonSubexpressionEliminator +// { +// let a := 1 +// let b := codesize() +// for { +// } +// lt(1, b) +// { +// mstore(1, b) +// a := add(a, b) +// } +// { +// mstore(1, b) +// } +// mstore(1, b) +// } diff --git a/test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/branches_if.yul b/test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/branches_if.yul new file mode 100644 index 00000000..5b8200d9 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/branches_if.yul @@ -0,0 +1,15 @@ +{ + let b := 1 + if b { b := 1 } + let c := 1 +} +// ---- +// commonSubexpressionEliminator +// { +// let b := 1 +// if b +// { +// b := b +// } +// let c := 1 +// } diff --git a/test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr.yul b/test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr.yul new file mode 100644 index 00000000..cb0ca38d --- /dev/null +++ b/test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr.yul @@ -0,0 +1,10 @@ +{ + let a := mload(1) + let b := mload(1) +} +// ---- +// commonSubexpressionEliminator +// { +// let a := mload(1) +// let b := mload(1) +// } diff --git a/test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr2.yul b/test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr2.yul new file mode 100644 index 00000000..ebc17446 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/non_movable_instr2.yul @@ -0,0 +1,10 @@ +{ + let a := gas() + let b := gas() +} +// ---- +// commonSubexpressionEliminator +// { +// let a := gas() +// let b := gas() +// } diff --git a/test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/smoke.yul b/test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/smoke.yul new file mode 100644 index 00000000..b9457229 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/smoke.yul @@ -0,0 +1,5 @@ +{ } +// ---- +// commonSubexpressionEliminator +// { +// } diff --git a/test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/trivial.yul b/test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/trivial.yul new file mode 100644 index 00000000..684272f5 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/commonSubexpressionEliminator/trivial.yul @@ -0,0 +1,10 @@ +{ + let a := mul(1, codesize()) + let b := mul(1, codesize()) +} +// ---- +// commonSubexpressionEliminator +// { +// let a := mul(1, codesize()) +// let b := a +// } -- cgit From 424a77b48e0cf226ea9b8ec2c0ed42d0679a45e0 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 11 Oct 2018 15:13:42 +0200 Subject: Move expression splitter tests. --- test/libjulia/ExpressionSplitter.cpp | 156 --------------------- test/libjulia/YulOptimizerTest.cpp | 8 ++ .../expressionSplitter/control_flow.yul | 33 +++++ .../expressionSplitter/inside_function.yul | 24 ++++ .../yulOptimizerTests/expressionSplitter/smoke.yul | 5 + .../expressionSplitter/switch.yul | 25 ++++ .../expressionSplitter/trivial.yul | 11 ++ 7 files changed, 106 insertions(+), 156 deletions(-) delete mode 100644 test/libjulia/ExpressionSplitter.cpp create mode 100644 test/libjulia/yulOptimizerTests/expressionSplitter/control_flow.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionSplitter/inside_function.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionSplitter/smoke.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionSplitter/switch.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionSplitter/trivial.yul diff --git a/test/libjulia/ExpressionSplitter.cpp b/test/libjulia/ExpressionSplitter.cpp deleted file mode 100644 index 9707fa86..00000000 --- a/test/libjulia/ExpressionSplitter.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** - * Unit tests for the expression breaker. - */ - -#include - -#include -#include - -#include - -#include - -#include -#include - -using namespace std; -using namespace dev; -using namespace dev::julia; -using namespace dev::julia::test; -using namespace dev::solidity; - - -#define CHECK(_original, _expectation)\ -do\ -{\ - auto result = parse(_original, false);\ - NameDispenser nameDispenser;\ - nameDispenser.m_usedNames = NameCollector(*result.first).names();\ - ExpressionSplitter{nameDispenser}(*result.first);\ - BOOST_CHECK_EQUAL(assembly::AsmPrinter{}(*result.first), format(_expectation, false));\ -}\ -while(false) - -BOOST_AUTO_TEST_SUITE(YulExpressionSplitter) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - CHECK("{ }", "{ }"); -} - -BOOST_AUTO_TEST_CASE(trivial) -{ - CHECK( - "{ mstore(add(calldataload(2), mload(3)), 8) }", - "{ let _1 := mload(3) let _2 := calldataload(2) let _3 := add(_2, _1) mstore(_3, 8) }" - ); -} - -BOOST_AUTO_TEST_CASE(control_flow) -{ - string input = R"({ - let x := calldataload(0) - if mul(add(x, 2), 3) { - for { let a := 2 } lt(a, mload(a)) { a := add(a, mul(a, 2)) } { - let b := mul(add(a, 2), 4) - sstore(b, mul(b, 2)) - } - } - })"; - string expectation = R"({ - let x := calldataload(0) - let _1 := add(x, 2) - let _2 := mul(_1, 3) - if _2 - { - for { let a := 2 } lt(a, mload(a)) - { - let _3 := mul(a, 2) - a := add(a, _3) - } - { - let _4 := add(a, 2) - let b := mul(_4, 4) - let _5 := mul(b, 2) - sstore(b, _5) - } - } - })"; - CHECK(input, expectation); -} - -BOOST_AUTO_TEST_CASE(switch_) -{ - string input = R"({ - let x := 8 - switch add(2, calldataload(0)) - case 0 { sstore(0, mload(2)) } - default { mstore(0, mload(3)) } - x := add(mload(3), 4) - })"; - string expectation = R"({ - let x := 8 - let _1 := calldataload(0) - let _2 := add(2, _1) - switch _2 - case 0 { - let _3 := mload(2) - sstore(0, _3) - } - default { - let _4 := mload(3) - mstore(0, _4) - } - let _5 := mload(3) - x := add(_5, 4) - })"; - - CHECK(input, expectation); -} - -BOOST_AUTO_TEST_CASE(inside_function) -{ - string input = R"({ - let x := mul(f(0, mload(7)), 3) - function f(a, b) -> c { - c := mul(a, mload(add(b, c))) - } - sstore(x, f(mload(2), mload(2))) - })"; - string expectation = R"({ - let _1 := mload(7) - let _2 := f(0, _1) - let x := mul(_2, 3) - function f(a, b) -> c - { - let _3 := add(b, c) - let _4 := mload(_3) - c := mul(a, _4) - } - let _5 := mload(2) - let _6 := mload(2) - let _7 := f(_6, _5) - sstore(x, _7) - })"; - - CHECK(input, expectation); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libjulia/YulOptimizerTest.cpp b/test/libjulia/YulOptimizerTest.cpp index 75a3d69b..e8c88b67 100644 --- a/test/libjulia/YulOptimizerTest.cpp +++ b/test/libjulia/YulOptimizerTest.cpp @@ -23,6 +23,8 @@ #include #include +#include +#include #include #include @@ -87,6 +89,12 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con disambiguate(); (CommonSubexpressionEliminator{})(*m_ast); } + else if (m_optimizerStep == "expressionSplitter") + { + NameDispenser nameDispenser; + nameDispenser.m_usedNames = NameCollector(*m_ast).names(); + ExpressionSplitter{nameDispenser}(*m_ast); + } else { FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Invalid optimizer step: " << m_optimizerStep << endl; diff --git a/test/libjulia/yulOptimizerTests/expressionSplitter/control_flow.yul b/test/libjulia/yulOptimizerTests/expressionSplitter/control_flow.yul new file mode 100644 index 00000000..5cc5a17d --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionSplitter/control_flow.yul @@ -0,0 +1,33 @@ +{ + let x := calldataload(0) + if mul(add(x, 2), 3) { + for { let a := 2 } lt(a, mload(a)) { a := add(a, mul(a, 2)) } { + let b := mul(add(a, 2), 4) + sstore(b, mul(b, 2)) + } + } +} +// ---- +// expressionSplitter +// { +// let x := calldataload(0) +// let _1 := add(x, 2) +// let _2 := mul(_1, 3) +// if _2 +// { +// for { +// let a := 2 +// } +// lt(a, mload(a)) +// { +// let _3 := mul(a, 2) +// a := add(a, _3) +// } +// { +// let _4 := add(a, 2) +// let b := mul(_4, 4) +// let _5 := mul(b, 2) +// sstore(b, _5) +// } +// } +// } diff --git a/test/libjulia/yulOptimizerTests/expressionSplitter/inside_function.yul b/test/libjulia/yulOptimizerTests/expressionSplitter/inside_function.yul new file mode 100644 index 00000000..8623f15d --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionSplitter/inside_function.yul @@ -0,0 +1,24 @@ +{ + let x := mul(f(0, mload(7)), 3) + function f(a, b) -> c { + c := mul(a, mload(add(b, c))) + } + sstore(x, f(mload(2), mload(2))) +} +// ---- +// expressionSplitter +// { +// let _1 := mload(7) +// let _2 := f(0, _1) +// let x := mul(_2, 3) +// function f(a, b) -> c +// { +// let _3 := add(b, c) +// let _4 := mload(_3) +// c := mul(a, _4) +// } +// let _5 := mload(2) +// let _6 := mload(2) +// let _7 := f(_6, _5) +// sstore(x, _7) +// } diff --git a/test/libjulia/yulOptimizerTests/expressionSplitter/smoke.yul b/test/libjulia/yulOptimizerTests/expressionSplitter/smoke.yul new file mode 100644 index 00000000..f69f60b6 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionSplitter/smoke.yul @@ -0,0 +1,5 @@ +{ } +// ---- +// expressionSplitter +// { +// } diff --git a/test/libjulia/yulOptimizerTests/expressionSplitter/switch.yul b/test/libjulia/yulOptimizerTests/expressionSplitter/switch.yul new file mode 100644 index 00000000..bda613b7 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionSplitter/switch.yul @@ -0,0 +1,25 @@ +{ + let x := 8 + switch add(2, calldataload(0)) + case 0 { sstore(0, mload(2)) } + default { mstore(0, mload(3)) } + x := add(mload(3), 4) +} +// ---- +// expressionSplitter +// { +// let x := 8 +// let _1 := calldataload(0) +// let _2 := add(2, _1) +// switch _2 +// case 0 { +// let _3 := mload(2) +// sstore(0, _3) +// } +// default { +// let _4 := mload(3) +// mstore(0, _4) +// } +// let _5 := mload(3) +// x := add(_5, 4) +// } diff --git a/test/libjulia/yulOptimizerTests/expressionSplitter/trivial.yul b/test/libjulia/yulOptimizerTests/expressionSplitter/trivial.yul new file mode 100644 index 00000000..632855a5 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionSplitter/trivial.yul @@ -0,0 +1,11 @@ +{ + mstore(add(calldataload(2), mload(3)), 8) +} +// ---- +// expressionSplitter +// { +// let _1 := mload(3) +// let _2 := calldataload(2) +// let _3 := add(_2, _1) +// mstore(_3, 8) +// } -- cgit From e021be4609e676dda9e9e08704e14bc50e5e7f97 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 11 Oct 2018 15:42:31 +0200 Subject: Move function grouper tests. --- test/libjulia/FunctionGrouper.cpp | 85 ---------------------- test/libjulia/YulOptimizerTest.cpp | 6 ++ .../functionGrouper/empty_block.yul | 24 ++++++ .../functionGrouper/multi_fun_mixed.yul | 24 ++++++ .../functionGrouper/nested_fun.yul | 27 +++++++ .../functionGrouper/single_fun.yul | 14 ++++ .../yulOptimizerTests/functionGrouper/smoke.yul | 7 ++ 7 files changed, 102 insertions(+), 85 deletions(-) delete mode 100644 test/libjulia/FunctionGrouper.cpp create mode 100644 test/libjulia/yulOptimizerTests/functionGrouper/empty_block.yul create mode 100644 test/libjulia/yulOptimizerTests/functionGrouper/multi_fun_mixed.yul create mode 100644 test/libjulia/yulOptimizerTests/functionGrouper/nested_fun.yul create mode 100644 test/libjulia/yulOptimizerTests/functionGrouper/single_fun.yul create mode 100644 test/libjulia/yulOptimizerTests/functionGrouper/smoke.yul diff --git a/test/libjulia/FunctionGrouper.cpp b/test/libjulia/FunctionGrouper.cpp deleted file mode 100644 index f1e83449..00000000 --- a/test/libjulia/FunctionGrouper.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** - * @date 2017 - * Unit tests for the Yul function grouper. - */ - -#include - -#include - -#include - -#include - -using namespace std; -using namespace dev::julia; -using namespace dev::julia::test; -using namespace dev::solidity; - -#define CHECK(_original, _expectation)\ -do\ -{\ - assembly::AsmPrinter p(true);\ - Block b = disambiguate(_original);\ - (FunctionGrouper{})(b);\ - string result = p(b);\ - BOOST_CHECK_EQUAL(result, format(_expectation));\ -}\ -while(false) - -BOOST_AUTO_TEST_SUITE(YulFunctionGrouper) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - CHECK("{ }", "{ { } }"); -} - -BOOST_AUTO_TEST_CASE(single_fun) -{ - CHECK( - "{ let a:u256 function f() {} }", - "{ { let a:u256 } function f() {} }" - ); -} - -BOOST_AUTO_TEST_CASE(multi_fun_mixed) -{ - CHECK( - "{ let a:u256 function f() { let b:u256 } let c:u256 function g() { let d:u256 } let e:u256 }", - "{ { let a:u256 let c:u256 let e:u256 } function f() { let b:u256 } function g() { let d:u256 } }" - ); -} - -BOOST_AUTO_TEST_CASE(nested_fun) -{ - CHECK( - "{ let a:u256 function f() { let b:u256 function g() { let c:u256} let d:u256 } }", - "{ { let a:u256 } function f() { let b:u256 function g() { let c:u256} let d:u256 } }" - ); -} - -BOOST_AUTO_TEST_CASE(empty_block) -{ - CHECK( - "{ let a:u256 { } function f() -> x:bool { let b:u256 := 4:u256 {} for {} f() {} {} } }", - "{ { let a:u256 { } } function f() -> x:bool { let b:u256 := 4:u256 {} for {} f() {} {} } }" - ); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libjulia/YulOptimizerTest.cpp b/test/libjulia/YulOptimizerTest.cpp index e8c88b67..31707890 100644 --- a/test/libjulia/YulOptimizerTest.cpp +++ b/test/libjulia/YulOptimizerTest.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -95,6 +96,11 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con nameDispenser.m_usedNames = NameCollector(*m_ast).names(); ExpressionSplitter{nameDispenser}(*m_ast); } + else if (m_optimizerStep == "functionGrouper") + { + disambiguate(); + (FunctionGrouper{})(*m_ast); + } else { FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Invalid optimizer step: " << m_optimizerStep << endl; diff --git a/test/libjulia/yulOptimizerTests/functionGrouper/empty_block.yul b/test/libjulia/yulOptimizerTests/functionGrouper/empty_block.yul new file mode 100644 index 00000000..f0d49d7b --- /dev/null +++ b/test/libjulia/yulOptimizerTests/functionGrouper/empty_block.yul @@ -0,0 +1,24 @@ +// yul +{ let a:u256 { } function f() -> x:bool { let b:u256 := 4:u256 {} for {} f() {} {} } } +// ---- +// functionGrouper +// { +// { +// let a:u256 +// { +// } +// } +// function f() -> x:bool +// { +// let b:u256 := 4:u256 +// { +// } +// for { +// } +// f() +// { +// } +// { +// } +// } +// } diff --git a/test/libjulia/yulOptimizerTests/functionGrouper/multi_fun_mixed.yul b/test/libjulia/yulOptimizerTests/functionGrouper/multi_fun_mixed.yul new file mode 100644 index 00000000..c830d5da --- /dev/null +++ b/test/libjulia/yulOptimizerTests/functionGrouper/multi_fun_mixed.yul @@ -0,0 +1,24 @@ +// yul +{ + let a:u256 + function f() { let b:u256 } + let c:u256 function g() { let d:u256 } + let e:u256 +} +// ---- +// functionGrouper +// { +// { +// let a:u256 +// let c:u256 +// let e:u256 +// } +// function f() +// { +// let b:u256 +// } +// function g() +// { +// let d:u256 +// } +// } diff --git a/test/libjulia/yulOptimizerTests/functionGrouper/nested_fun.yul b/test/libjulia/yulOptimizerTests/functionGrouper/nested_fun.yul new file mode 100644 index 00000000..4a8be86a --- /dev/null +++ b/test/libjulia/yulOptimizerTests/functionGrouper/nested_fun.yul @@ -0,0 +1,27 @@ +// yul +{ + let a:u256 + function f() { + let b:u256 + function g() { + let c:u256 + } + let d:u256 + } +} +// ---- +// functionGrouper +// { +// { +// let a:u256 +// } +// function f() +// { +// let b:u256 +// function g() +// { +// let c:u256 +// } +// let d:u256 +// } +// } diff --git a/test/libjulia/yulOptimizerTests/functionGrouper/single_fun.yul b/test/libjulia/yulOptimizerTests/functionGrouper/single_fun.yul new file mode 100644 index 00000000..149a44eb --- /dev/null +++ b/test/libjulia/yulOptimizerTests/functionGrouper/single_fun.yul @@ -0,0 +1,14 @@ +// yul +{ + let a:u256 function f() {} +} +// ---- +// functionGrouper +// { +// { +// let a:u256 +// } +// function f() +// { +// } +// } diff --git a/test/libjulia/yulOptimizerTests/functionGrouper/smoke.yul b/test/libjulia/yulOptimizerTests/functionGrouper/smoke.yul new file mode 100644 index 00000000..650a163e --- /dev/null +++ b/test/libjulia/yulOptimizerTests/functionGrouper/smoke.yul @@ -0,0 +1,7 @@ +{ } +// ---- +// functionGrouper +// { +// { +// } +// } -- cgit From 7a34fc12915d9c6ce0a126a5c283c107a25c41dd Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 11 Oct 2018 15:47:49 +0200 Subject: Move function hoister tests. --- test/libjulia/FunctionHoister.cpp | 85 ---------------------- test/libjulia/YulOptimizerTest.cpp | 6 ++ .../functionHoister/empty_block.yul | 26 +++++++ .../functionHoister/multi_mixed.yul | 23 ++++++ .../yulOptimizerTests/functionHoister/nested.yul | 23 ++++++ .../yulOptimizerTests/functionHoister/single.yul | 13 ++++ .../yulOptimizerTests/functionHoister/smoke.yul | 6 ++ 7 files changed, 97 insertions(+), 85 deletions(-) delete mode 100644 test/libjulia/FunctionHoister.cpp create mode 100644 test/libjulia/yulOptimizerTests/functionHoister/empty_block.yul create mode 100644 test/libjulia/yulOptimizerTests/functionHoister/multi_mixed.yul create mode 100644 test/libjulia/yulOptimizerTests/functionHoister/nested.yul create mode 100644 test/libjulia/yulOptimizerTests/functionHoister/single.yul create mode 100644 test/libjulia/yulOptimizerTests/functionHoister/smoke.yul diff --git a/test/libjulia/FunctionHoister.cpp b/test/libjulia/FunctionHoister.cpp deleted file mode 100644 index 348963b4..00000000 --- a/test/libjulia/FunctionHoister.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** - * @date 2017 - * Unit tests for the Yul function hoister. - */ - -#include - -#include - -#include - -#include - -using namespace std; -using namespace dev::julia; -using namespace dev::julia::test; -using namespace dev::solidity; - -#define CHECK(_original, _expectation)\ -do\ -{\ - assembly::AsmPrinter p(true);\ - Block b = disambiguate(_original);\ - (FunctionHoister{})(b);\ - string result = p(b);\ - BOOST_CHECK_EQUAL(result, format(_expectation));\ -}\ -while(false) - -BOOST_AUTO_TEST_SUITE(YulFunctionHoister) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - CHECK("{ }", "{ }"); -} - -BOOST_AUTO_TEST_CASE(single_fun) -{ - CHECK( - "{ let a:u256 function f() {} }", - "{ let a:u256 function f() {} }" - ); -} - -BOOST_AUTO_TEST_CASE(multi_fun_mixed) -{ - CHECK( - "{ let a:u256 function f() { let b:u256 } let c:u256 function g() { let d:u256 } let e:u256 }", - "{ let a:u256 let c:u256 let e:u256 function f() { let b:u256 } function g() { let d:u256 } }" - ); -} - -BOOST_AUTO_TEST_CASE(nested_fun) -{ - CHECK( - "{ let a:u256 function f() { let b:u256 function g() { let c:u256} let d:u256 } }", - "{ let a:u256 function g() { let c:u256 } function f() { let b:u256 let d:u256 } }" - ); -} - -BOOST_AUTO_TEST_CASE(empty_block) -{ - CHECK( - "{ let a:u256 { } function f() -> x:bool { let b:u256 := 4:u256 {} for {} f() {} {} } }", - "{ let a:u256 function f() -> x:bool { let b:u256 := 4:u256 for {} f() {} {} } }" - ); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libjulia/YulOptimizerTest.cpp b/test/libjulia/YulOptimizerTest.cpp index 31707890..1ac2ddf5 100644 --- a/test/libjulia/YulOptimizerTest.cpp +++ b/test/libjulia/YulOptimizerTest.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -101,6 +102,11 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con disambiguate(); (FunctionGrouper{})(*m_ast); } + else if (m_optimizerStep == "functionHoister") + { + disambiguate(); + (FunctionHoister{})(*m_ast); + } else { FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Invalid optimizer step: " << m_optimizerStep << endl; diff --git a/test/libjulia/yulOptimizerTests/functionHoister/empty_block.yul b/test/libjulia/yulOptimizerTests/functionHoister/empty_block.yul new file mode 100644 index 00000000..6ea9f59d --- /dev/null +++ b/test/libjulia/yulOptimizerTests/functionHoister/empty_block.yul @@ -0,0 +1,26 @@ +// yul +{ + let a:u256 + { } + function f() -> x:bool { + let b:u256 := 4:u256 + { } + for {} f() {} {} + } +} +// ---- +// functionHoister +// { +// let a:u256 +// function f() -> x:bool +// { +// let b:u256 := 4:u256 +// for { +// } +// f() +// { +// } +// { +// } +// } +// } diff --git a/test/libjulia/yulOptimizerTests/functionHoister/multi_mixed.yul b/test/libjulia/yulOptimizerTests/functionHoister/multi_mixed.yul new file mode 100644 index 00000000..1e3bc5a1 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/functionHoister/multi_mixed.yul @@ -0,0 +1,23 @@ +// yul +{ + let a:u256 + function f() { let b:u256 } + let c:u256 + function g() { let d:u256 } + let e:u256 +} +// ---- +// functionHoister +// { +// let a:u256 +// let c:u256 +// let e:u256 +// function f() +// { +// let b:u256 +// } +// function g() +// { +// let d:u256 +// } +// } diff --git a/test/libjulia/yulOptimizerTests/functionHoister/nested.yul b/test/libjulia/yulOptimizerTests/functionHoister/nested.yul new file mode 100644 index 00000000..20f094f1 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/functionHoister/nested.yul @@ -0,0 +1,23 @@ +// yul +{ + let a:u256 + function f() { + let b:u256 + function g() { let c:u256 } + let d:u256 + } +} +// ---- +// functionHoister +// { +// let a:u256 +// function g() +// { +// let c:u256 +// } +// function f() +// { +// let b:u256 +// let d:u256 +// } +// } diff --git a/test/libjulia/yulOptimizerTests/functionHoister/single.yul b/test/libjulia/yulOptimizerTests/functionHoister/single.yul new file mode 100644 index 00000000..ba922612 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/functionHoister/single.yul @@ -0,0 +1,13 @@ +// yul +{ + let a:u256 + function f() {} +} +// ---- +// functionHoister +// { +// let a:u256 +// function f() +// { +// } +// } diff --git a/test/libjulia/yulOptimizerTests/functionHoister/smoke.yul b/test/libjulia/yulOptimizerTests/functionHoister/smoke.yul new file mode 100644 index 00000000..35c1ce5f --- /dev/null +++ b/test/libjulia/yulOptimizerTests/functionHoister/smoke.yul @@ -0,0 +1,6 @@ +{ +} +// ---- +// functionHoister +// { +// } -- cgit From 83ab8e7f7897d87e90e534e3272e916f714a9727 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 11 Oct 2018 16:58:21 +0200 Subject: Move expression inliner tests. --- test/libjulia/Inliner.cpp | 95 ---------------------- test/libjulia/YulOptimizerTest.cpp | 6 ++ .../expressionInliner/complex_with_evm.yul | 13 +++ .../expressionInliner/double_calls.yul | 18 ++++ .../expressionInliner/double_recursive_calls.yul | 18 ++++ .../expressionInliner/no_inline_mload.yul | 14 ++++ .../expressionInliner/no_move_with_sideeffects.yul | 27 ++++++ .../yulOptimizerTests/expressionInliner/simple.yul | 14 ++++ .../expressionInliner/with_args.yul | 14 ++++ 9 files changed, 124 insertions(+), 95 deletions(-) create mode 100644 test/libjulia/yulOptimizerTests/expressionInliner/complex_with_evm.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionInliner/double_calls.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionInliner/double_recursive_calls.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionInliner/no_inline_mload.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionInliner/no_move_with_sideeffects.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionInliner/simple.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionInliner/with_args.yul diff --git a/test/libjulia/Inliner.cpp b/test/libjulia/Inliner.cpp index d0ecd42f..165e23ad 100644 --- a/test/libjulia/Inliner.cpp +++ b/test/libjulia/Inliner.cpp @@ -55,12 +55,6 @@ string inlinableFunctions(string const& _source) ); } -string inlineFunctions(string const& _source, bool _yul = true) -{ - auto ast = disambiguate(_source, _yul); - ExpressionInliner(ast).run(); - return assembly::AsmPrinter(_yul)(ast); -} string fullInline(string const& _source, bool _yul = true) { Block ast = disambiguate(_source, _yul); @@ -122,95 +116,6 @@ BOOST_AUTO_TEST_CASE(negative) } -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(YulFunctionInliner) - -BOOST_AUTO_TEST_CASE(simple) -{ - BOOST_CHECK_EQUAL( - inlineFunctions("{ function f() -> x:u256 { x := 2:u256 } let y:u256 := f() }"), - format("{ function f() -> x:u256 { x := 2:u256 } let y:u256 := 2:u256 }") - ); -} - -BOOST_AUTO_TEST_CASE(with_args) -{ - BOOST_CHECK_EQUAL( - inlineFunctions("{ function f(a:u256) -> x:u256 { x := a } let y:u256 := f(7:u256) }"), - format("{ function f(a:u256) -> x:u256 { x := a } let y:u256 := 7:u256 }") - ); -} - -BOOST_AUTO_TEST_CASE(no_inline_with_mload) -{ - // Does not inline because mload could be moved out of sequence - BOOST_CHECK_EQUAL( - inlineFunctions("{ function f(a) -> x { x := a } let y := f(mload(2)) }", false), - format("{ function f(a) -> x { x := a } let y := f(mload(2)) }", false) - ); -} - -BOOST_AUTO_TEST_CASE(no_move_with_side_effects) -{ - // The calls to g and h cannot be moved because g and h are not movable. Therefore, the call - // to f is not inlined. - BOOST_CHECK_EQUAL( - inlineFunctions("{" - "function f(a, b) -> x { x := add(b, a) }" - "function g() -> y { y := mload(0) mstore(0, 4) }" - "function h() -> z { mstore(0, 4) z := mload(0) }" - "let r := f(g(), h())" - "}", false), - format("{" - "function f(a, b) -> x { x := add(b, a) }" - "function g() -> y { y := mload(0) mstore(0, 4) }" - "function h() -> z { mstore(0, 4) z := mload(0) }" - "let r := f(g(), h())" - "}", false) - ); -} - -BOOST_AUTO_TEST_CASE(complex_with_evm) -{ - BOOST_CHECK_EQUAL( - inlineFunctions("{ function f(a) -> x { x := add(a, a) } let y := f(calldatasize()) }", false), - format("{ function f(a) -> x { x := add(a, a) } let y := add(calldatasize(), calldatasize()) }", false) - ); -} - -BOOST_AUTO_TEST_CASE(double_calls) -{ - BOOST_CHECK_EQUAL( - inlineFunctions("{" - "function f(a) -> x { x := add(a, a) }" - "function g(b, c) -> y { y := mul(mload(c), f(b)) }" - "let y := g(calldatasize(), 7)" - "}", false), - format("{" - "function f(a) -> x { x := add(a, a) }" - "function g(b, c) -> y { y := mul(mload(c), add(b, b)) }" - "let y_1 := mul(mload(7), add(calldatasize(), calldatasize()))" - "}", false) - ); -} - -BOOST_AUTO_TEST_CASE(double_recursive_calls) -{ - BOOST_CHECK_EQUAL( - inlineFunctions("{" - "function f(a, r) -> x { x := g(a, g(r, r)) }" - "function g(b, s) -> y { y := f(b, f(s, s)) }" - "let y := g(calldatasize(), 7)" - "}", false), - format("{" - "function f(a, r) -> x { x := g(a, f(r, f(r, r))) }" - "function g(b, s) -> y { y := f(b, g(s, f(s, f(s, s))))}" - "let y_1 := f(calldatasize(), g(7, f(7, f(7, 7))))" - "}", false) - ); -} - BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE(YulFullInliner) diff --git a/test/libjulia/YulOptimizerTest.cpp b/test/libjulia/YulOptimizerTest.cpp index 1ac2ddf5..878f1297 100644 --- a/test/libjulia/YulOptimizerTest.cpp +++ b/test/libjulia/YulOptimizerTest.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -107,6 +108,11 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con disambiguate(); (FunctionHoister{})(*m_ast); } + else if (m_optimizerStep == "expressionInliner") + { + disambiguate(); + ExpressionInliner(*m_ast).run(); + } else { FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Invalid optimizer step: " << m_optimizerStep << endl; diff --git a/test/libjulia/yulOptimizerTests/expressionInliner/complex_with_evm.yul b/test/libjulia/yulOptimizerTests/expressionInliner/complex_with_evm.yul new file mode 100644 index 00000000..519a2af8 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionInliner/complex_with_evm.yul @@ -0,0 +1,13 @@ +{ + function f(a) -> x { x := add(a, a) } + let y := f(calldatasize()) +} +// ---- +// expressionInliner +// { +// function f(a) -> x +// { +// x := add(a, a) +// } +// let y := add(calldatasize(), calldatasize()) +// } diff --git a/test/libjulia/yulOptimizerTests/expressionInliner/double_calls.yul b/test/libjulia/yulOptimizerTests/expressionInliner/double_calls.yul new file mode 100644 index 00000000..e1da8e07 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionInliner/double_calls.yul @@ -0,0 +1,18 @@ +{ + function f(a) -> x { x := add(a, a) } + function g(b, c) -> y { y := mul(mload(c), f(b)) } + let y := g(calldatasize(), 7) +} +// ---- +// expressionInliner +// { +// function f(a) -> x +// { +// x := add(a, a) +// } +// function g(b, c) -> y +// { +// y := mul(mload(c), add(b, b)) +// } +// let y_1 := mul(mload(7), add(calldatasize(), calldatasize())) +// } diff --git a/test/libjulia/yulOptimizerTests/expressionInliner/double_recursive_calls.yul b/test/libjulia/yulOptimizerTests/expressionInliner/double_recursive_calls.yul new file mode 100644 index 00000000..082cb53f --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionInliner/double_recursive_calls.yul @@ -0,0 +1,18 @@ +{ + function f(a, r) -> x { x := g(a, g(r, r)) } + function g(b, s) -> y { y := f(b, f(s, s)) } + let y := g(calldatasize(), 7) +} +// ---- +// expressionInliner +// { +// function f(a, r) -> x +// { +// x := g(a, f(r, f(r, r))) +// } +// function g(b, s) -> y +// { +// y := f(b, g(s, f(s, f(s, s)))) +// } +// let y_1 := f(calldatasize(), g(7, f(7, f(7, 7)))) +// } diff --git a/test/libjulia/yulOptimizerTests/expressionInliner/no_inline_mload.yul b/test/libjulia/yulOptimizerTests/expressionInliner/no_inline_mload.yul new file mode 100644 index 00000000..0fb43a9d --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionInliner/no_inline_mload.yul @@ -0,0 +1,14 @@ +// Does not inline because mload could be moved out of sequence +{ + function f(a) -> x { x := a } + let y := f(mload(2)) +} +// ---- +// expressionInliner +// { +// function f(a) -> x +// { +// x := a +// } +// let y := f(mload(2)) +// } diff --git a/test/libjulia/yulOptimizerTests/expressionInliner/no_move_with_sideeffects.yul b/test/libjulia/yulOptimizerTests/expressionInliner/no_move_with_sideeffects.yul new file mode 100644 index 00000000..7fdad6c4 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionInliner/no_move_with_sideeffects.yul @@ -0,0 +1,27 @@ +// The calls to g and h cannot be moved because g and h are not movable. Therefore, the call +// to f is not inlined. +{ + function f(a, b) -> x { x := add(b, a) } + function g() -> y { y := mload(0) mstore(0, 4) } + function h() -> z { mstore(0, 4) z := mload(0) } + let r := f(g(), h()) +} +// ---- +// expressionInliner +// { +// function f(a, b) -> x +// { +// x := add(b, a) +// } +// function g() -> y +// { +// y := mload(0) +// mstore(0, 4) +// } +// function h() -> z +// { +// mstore(0, 4) +// z := mload(0) +// } +// let r := f(g(), h()) +// } diff --git a/test/libjulia/yulOptimizerTests/expressionInliner/simple.yul b/test/libjulia/yulOptimizerTests/expressionInliner/simple.yul new file mode 100644 index 00000000..c186eafd --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionInliner/simple.yul @@ -0,0 +1,14 @@ +// yul +{ + function f() -> x:u256 { x := 2:u256 } + let y:u256 := f() +} +// ---- +// expressionInliner +// { +// function f() -> x:u256 +// { +// x := 2:u256 +// } +// let y:u256 := 2:u256 +// } diff --git a/test/libjulia/yulOptimizerTests/expressionInliner/with_args.yul b/test/libjulia/yulOptimizerTests/expressionInliner/with_args.yul new file mode 100644 index 00000000..b5f4d515 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionInliner/with_args.yul @@ -0,0 +1,14 @@ +// yul +{ + function f(a:u256) -> x:u256 { x := a } + let y:u256 := f(7:u256) +} +// ---- +// expressionInliner +// { +// function f(a:u256) -> x:u256 +// { +// x := a +// } +// let y:u256 := 7:u256 +// } -- cgit From 9cd577abe9d6a04147160ec2b14988dc5b4f5a28 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 11 Oct 2018 17:14:59 +0200 Subject: Move tests for full inliner. --- test/libjulia/Inliner.cpp | 175 --------------------- test/libjulia/YulOptimizerTest.cpp | 8 + .../fullInliner/inside_condition.yul | 32 ++++ .../fullInliner/move_up_rightwards_argument.yul | 28 ++++ .../yulOptimizerTests/fullInliner/multi_fun.yul | 40 +++++ .../yulOptimizerTests/fullInliner/multi_return.yul | 21 +++ .../yulOptimizerTests/fullInliner/no_return.yul | 22 +++ .../yulOptimizerTests/fullInliner/pop_result.yul | 28 ++++ .../yulOptimizerTests/fullInliner/simple.yul | 26 +++ 9 files changed, 205 insertions(+), 175 deletions(-) create mode 100644 test/libjulia/yulOptimizerTests/fullInliner/inside_condition.yul create mode 100644 test/libjulia/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul create mode 100644 test/libjulia/yulOptimizerTests/fullInliner/multi_fun.yul create mode 100644 test/libjulia/yulOptimizerTests/fullInliner/multi_return.yul create mode 100644 test/libjulia/yulOptimizerTests/fullInliner/no_return.yul create mode 100644 test/libjulia/yulOptimizerTests/fullInliner/pop_result.yul create mode 100644 test/libjulia/yulOptimizerTests/fullInliner/simple.yul diff --git a/test/libjulia/Inliner.cpp b/test/libjulia/Inliner.cpp index 165e23ad..95b61b29 100644 --- a/test/libjulia/Inliner.cpp +++ b/test/libjulia/Inliner.cpp @@ -55,14 +55,6 @@ string inlinableFunctions(string const& _source) ); } -string fullInline(string const& _source, bool _yul = true) -{ - Block ast = disambiguate(_source, _yul); - (FunctionHoister{})(ast); - (FunctionGrouper{})(ast);\ - FullInliner(ast).run(); - return assembly::AsmPrinter(_yul)(ast); -} } @@ -116,171 +108,4 @@ BOOST_AUTO_TEST_CASE(negative) } -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(YulFullInliner) - -BOOST_AUTO_TEST_CASE(simple) -{ - BOOST_CHECK_EQUAL( - fullInline("{" - "function f(a) -> x { let r := mul(a, a) x := add(r, r) }" - "let y := add(f(sload(mload(2))), mload(7))" - "}", false), - format("{" - "{" - "let _1 := mload(7)" - "let f_a := sload(mload(2))" - "let f_x" - "{" - "let f_r := mul(f_a, f_a)" - "f_x := add(f_r, f_r)" - "}" - "let y := add(f_x, _1)" - "}" - "function f(a) -> x" - "{" - "let r := mul(a, a)" - "x := add(r, r)" - "}" - "}", false) - ); -} - -BOOST_AUTO_TEST_CASE(multi_fun) -{ - BOOST_CHECK_EQUAL( - fullInline("{" - "function f(a) -> x { x := add(a, a) }" - "function g(b, c) -> y { y := mul(mload(c), f(b)) }" - "let y := g(f(3), 7)" - "}", false), - format("{" - "{" - "let g_c := 7 " - "let f_a_1 := 3 " - "let f_x_1 " - "{ f_x_1 := add(f_a_1, f_a_1) } " - "let g_y " - "{" - "let g_f_a := f_x_1 " - "let g_f_x " - "{" - "g_f_x := add(g_f_a, g_f_a)" - "}" - "g_y := mul(mload(g_c), g_f_x)" - "}" - "let y_1 := g_y" - "}" - "function f(a) -> x" - "{" - "x := add(a, a)" - "}" - "function g(b, c) -> y" - "{" - "let f_a := b " - "let f_x " - "{" - "f_x := add(f_a, f_a)" - "}" - "y := mul(mload(c), f_x)" - "}" - "}", false) - ); -} - -BOOST_AUTO_TEST_CASE(move_up_rightwards_arguments) -{ - BOOST_CHECK_EQUAL( - fullInline("{" - "function f(a, b, c) -> x { x := add(a, b) x := mul(x, c) }" - "let y := add(mload(1), add(f(mload(2), mload(3), mload(4)), mload(5)))" - "}", false), - format("{" - "{" - "let _1 := mload(5)" - "let f_c := mload(4)" - "let f_b := mload(3)" - "let f_a := mload(2)" - "let f_x" - "{" - "f_x := add(f_a, f_b)" - "f_x := mul(f_x, f_c)" - "}" - "let y := add(mload(1), add(f_x, _1))" - "}" - "function f(a, b, c) -> x" - "{" - "x := add(a, b)" - "x := mul(x, c)" - "}" - "}", false) - ); -} - -BOOST_AUTO_TEST_CASE(pop_result) -{ - // This tests that `pop(r)` is removed. - BOOST_CHECK_EQUAL( - fullInline("{" - "function f(a) -> x { let r := mul(a, a) x := add(r, r) }" - "pop(add(f(7), 2))" - "}", false), - format("{" - "{" - "let _1 := 2 " - "let f_a := 7 " - "let f_x " - "{" - "let f_r := mul(f_a, f_a) " - "f_x := add(f_r, f_r)" - "}" - "{" - "}" - "}" - "function f(a) -> x" - "{" - "let r := mul(a, a) " - "x := add(r, r)" - "}" - "}", false) - ); -} - -BOOST_AUTO_TEST_CASE(inside_condition) -{ - // This tests that breaking the expression inside the condition works properly. - BOOST_CHECK_EQUAL( - fullInline("{" - "if gt(f(mload(1)), mload(0)) {" - "sstore(0, 2)" - "}" - "function f(a) -> r {" - "a := mload(a)" - "r := add(a, calldatasize())" - "}" - "}", false), - format("{" - "{" - "let _1 := mload(0)" - "let f_a := mload(1)" - "let f_r" - "{" - "f_a := mload(f_a)" - "f_r := add(f_a, calldatasize())" - "}" - "if gt(f_r, _1)" - "{" - "sstore(0, 2)" - "}" - "}" - "function f(a) -> r" - "{" - "a := mload(a)" - "r := add(a, calldatasize())" - "}" - "}", false) - ); -} - BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libjulia/YulOptimizerTest.cpp b/test/libjulia/YulOptimizerTest.cpp index 878f1297..9f028bcd 100644 --- a/test/libjulia/YulOptimizerTest.cpp +++ b/test/libjulia/YulOptimizerTest.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -113,6 +114,13 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con disambiguate(); ExpressionInliner(*m_ast).run(); } + else if (m_optimizerStep == "fullInliner") + { + disambiguate(); + (FunctionHoister{})(*m_ast); + (FunctionGrouper{})(*m_ast); + FullInliner(*m_ast).run(); + } else { FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Invalid optimizer step: " << m_optimizerStep << endl; diff --git a/test/libjulia/yulOptimizerTests/fullInliner/inside_condition.yul b/test/libjulia/yulOptimizerTests/fullInliner/inside_condition.yul new file mode 100644 index 00000000..ae25e9a3 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/fullInliner/inside_condition.yul @@ -0,0 +1,32 @@ +// This tests that breaking the expression inside the condition works properly. +{ + if gt(f(mload(1)), mload(0)) { + sstore(0, 2) + } + function f(a) -> r { + a := mload(a) + r := add(a, calldatasize()) + } +} +// ---- +// fullInliner +// { +// { +// let _1 := mload(0) +// let f_a := mload(1) +// let f_r +// { +// f_a := mload(f_a) +// f_r := add(f_a, calldatasize()) +// } +// if gt(f_r, _1) +// { +// sstore(0, 2) +// } +// } +// function f(a) -> r +// { +// a := mload(a) +// r := add(a, calldatasize()) +// } +// } diff --git a/test/libjulia/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul b/test/libjulia/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul new file mode 100644 index 00000000..e1def585 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/fullInliner/move_up_rightwards_argument.yul @@ -0,0 +1,28 @@ +{ + function f(a, b, c) -> x { + x := add(a, b) + x := mul(x, c) + } + let y := add(mload(1), add(f(mload(2), mload(3), mload(4)), mload(5))) +} +// ---- +// fullInliner +// { +// { +// let _1 := mload(5) +// let f_c := mload(4) +// let f_b := mload(3) +// let f_a := mload(2) +// let f_x +// { +// f_x := add(f_a, f_b) +// f_x := mul(f_x, f_c) +// } +// let y := add(mload(1), add(f_x, _1)) +// } +// function f(a, b, c) -> x +// { +// x := add(a, b) +// x := mul(x, c) +// } +// } diff --git a/test/libjulia/yulOptimizerTests/fullInliner/multi_fun.yul b/test/libjulia/yulOptimizerTests/fullInliner/multi_fun.yul new file mode 100644 index 00000000..94bbe5dc --- /dev/null +++ b/test/libjulia/yulOptimizerTests/fullInliner/multi_fun.yul @@ -0,0 +1,40 @@ +{ + function f(a) -> x { x := add(a, a) } + function g(b, c) -> y { y := mul(mload(c), f(b)) } + let y := g(f(3), 7) +} +// ---- +// fullInliner +// { +// { +// let g_c := 7 +// let f_a_1 := 3 +// let f_x_1 +// { +// f_x_1 := add(f_a_1, f_a_1) +// } +// let g_y +// { +// let g_f_a := f_x_1 +// let g_f_x +// { +// g_f_x := add(g_f_a, g_f_a) +// } +// g_y := mul(mload(g_c), g_f_x) +// } +// let y_1 := g_y +// } +// function f(a) -> x +// { +// x := add(a, a) +// } +// function g(b, c) -> y +// { +// let f_a := b +// let f_x +// { +// f_x := add(f_a, f_a) +// } +// y := mul(mload(c), f_x) +// } +// } diff --git a/test/libjulia/yulOptimizerTests/fullInliner/multi_return.yul b/test/libjulia/yulOptimizerTests/fullInliner/multi_return.yul new file mode 100644 index 00000000..f3c5b0ee --- /dev/null +++ b/test/libjulia/yulOptimizerTests/fullInliner/multi_return.yul @@ -0,0 +1,21 @@ +// The full inliner currently does not work with +// functions returning multiple values. +{ + function f(a) -> x, y { + x := mul(a, a) + y := add(a, x) + } + let a, b := f(mload(0)) +} +// ---- +// fullInliner +// { +// { +// let a_1, b := f(mload(0)) +// } +// function f(a) -> x, y +// { +// x := mul(a, a) +// y := add(a, x) +// } +// } diff --git a/test/libjulia/yulOptimizerTests/fullInliner/no_return.yul b/test/libjulia/yulOptimizerTests/fullInliner/no_return.yul new file mode 100644 index 00000000..53fe3527 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/fullInliner/no_return.yul @@ -0,0 +1,22 @@ +{ + function f(a) { + sstore(a, a) + } + f(mload(0)) +} +// ---- +// fullInliner +// { +// { +// let f_a := mload(0) +// { +// sstore(f_a, f_a) +// } +// { +// } +// } +// function f(a) +// { +// sstore(a, a) +// } +// } diff --git a/test/libjulia/yulOptimizerTests/fullInliner/pop_result.yul b/test/libjulia/yulOptimizerTests/fullInliner/pop_result.yul new file mode 100644 index 00000000..3883c67c --- /dev/null +++ b/test/libjulia/yulOptimizerTests/fullInliner/pop_result.yul @@ -0,0 +1,28 @@ +// This tests that `pop(r)` is removed. +{ + function f(a) -> x { + let r := mul(a, a) + x := add(r, r) + } + pop(add(f(7), 2)) +} +// ---- +// fullInliner +// { +// { +// let _1 := 2 +// let f_a := 7 +// let f_x +// { +// let f_r := mul(f_a, f_a) +// f_x := add(f_r, f_r) +// } +// { +// } +// } +// function f(a) -> x +// { +// let r := mul(a, a) +// x := add(r, r) +// } +// } diff --git a/test/libjulia/yulOptimizerTests/fullInliner/simple.yul b/test/libjulia/yulOptimizerTests/fullInliner/simple.yul new file mode 100644 index 00000000..dd1a4e0a --- /dev/null +++ b/test/libjulia/yulOptimizerTests/fullInliner/simple.yul @@ -0,0 +1,26 @@ +{ + function f(a) -> x { + let r := mul(a, a) + x := add(r, r) + } + let y := add(f(sload(mload(2))), mload(7)) +} +// ---- +// fullInliner +// { +// { +// let _1 := mload(7) +// let f_a := sload(mload(2)) +// let f_x +// { +// let f_r := mul(f_a, f_a) +// f_x := add(f_r, f_r) +// } +// let y := add(f_x, _1) +// } +// function f(a) -> x +// { +// let r := mul(a, a) +// x := add(r, r) +// } +// } -- cgit From 49958e4720528e4ba325dfc0892888f319649aa9 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 11 Oct 2018 17:45:12 +0200 Subject: Move main function tests. --- test/libjulia/MainFunction.cpp | 87 ---------------------- test/libjulia/YulOptimizerTest.cpp | 7 ++ .../yulOptimizerTests/mainFunction/empty_block.yul | 33 ++++++++ .../mainFunction/multi_fun_mixed.yul | 26 +++++++ .../yulOptimizerTests/mainFunction/nested_fun.yul | 26 +++++++ .../yulOptimizerTests/mainFunction/sigle_fun.yul | 16 ++++ .../yulOptimizerTests/mainFunction/smoke.yul | 9 +++ 7 files changed, 117 insertions(+), 87 deletions(-) delete mode 100644 test/libjulia/MainFunction.cpp create mode 100644 test/libjulia/yulOptimizerTests/mainFunction/empty_block.yul create mode 100644 test/libjulia/yulOptimizerTests/mainFunction/multi_fun_mixed.yul create mode 100644 test/libjulia/yulOptimizerTests/mainFunction/nested_fun.yul create mode 100644 test/libjulia/yulOptimizerTests/mainFunction/sigle_fun.yul create mode 100644 test/libjulia/yulOptimizerTests/mainFunction/smoke.yul diff --git a/test/libjulia/MainFunction.cpp b/test/libjulia/MainFunction.cpp deleted file mode 100644 index e7263d13..00000000 --- a/test/libjulia/MainFunction.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** - * @date 2018 - * Unit tests for the Yul MainFunction transformation. - */ - -#include - -#include -#include - -#include - -#include - -using namespace std; -using namespace dev::julia; -using namespace dev::julia::test; -using namespace dev::solidity; - -#define CHECK(_original, _expectation)\ -do\ -{\ - assembly::AsmPrinter p(true);\ - Block b = disambiguate(_original);\ - (FunctionGrouper{})(b);\ - (MainFunction{})(b);\ - string result = p(b);\ - BOOST_CHECK_EQUAL(result, format(_expectation));\ -}\ -while(false) - -BOOST_AUTO_TEST_SUITE(YulMainFunction) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - CHECK("{ }", "{ function main() { } }"); -} - -BOOST_AUTO_TEST_CASE(single_fun) -{ - CHECK( - "{ let a:u256 function f() {} }", - "{ function main() { let a:u256 } function f() {} }" - ); -} - -BOOST_AUTO_TEST_CASE(multi_fun_mixed) -{ - CHECK( - "{ let a:u256 function f() { let b:u256 } let c:u256 function g() { let d:u256 } let e:u256 }", - "{ function main() { let a:u256 let c:u256 let e:u256 } function f() { let b:u256 } function g() { let d:u256 } }" - ); -} - -BOOST_AUTO_TEST_CASE(nested_fun) -{ - CHECK( - "{ let a:u256 function f() { let b:u256 function g() { let c:u256} let d:u256 } }", - "{ function main() { let a:u256 } function f() { let b:u256 function g() { let c:u256} let d:u256 } }" - ); -} - -BOOST_AUTO_TEST_CASE(empty_block) -{ - CHECK( - "{ let a:u256 { } function f() -> x:bool { let b:u256 := 4:u256 {} for {} f() {} {} } }", - "{ function main() { let a:u256 { } } function f() -> x:bool { let b:u256 := 4:u256 {} for {} f() {} {} } }" - ); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libjulia/YulOptimizerTest.cpp b/test/libjulia/YulOptimizerTest.cpp index 9f028bcd..0e55c87d 100644 --- a/test/libjulia/YulOptimizerTest.cpp +++ b/test/libjulia/YulOptimizerTest.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -121,6 +122,12 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con (FunctionGrouper{})(*m_ast); FullInliner(*m_ast).run(); } + else if (m_optimizerStep == "mainFunction") + { + disambiguate(); + (FunctionGrouper{})(*m_ast); + (MainFunction{})(*m_ast); + } else { FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Invalid optimizer step: " << m_optimizerStep << endl; diff --git a/test/libjulia/yulOptimizerTests/mainFunction/empty_block.yul b/test/libjulia/yulOptimizerTests/mainFunction/empty_block.yul new file mode 100644 index 00000000..bae6bd48 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/mainFunction/empty_block.yul @@ -0,0 +1,33 @@ +// yul +{ + let a:u256 + { } + function f() -> x:bool { + let b:u256 := 4:u256 + {} + for {} f() {} {} + } +} +// ---- +// mainFunction +// { +// function main() +// { +// let a:u256 +// { +// } +// } +// function f() -> x:bool +// { +// let b:u256 := 4:u256 +// { +// } +// for { +// } +// f() +// { +// } +// { +// } +// } +// } diff --git a/test/libjulia/yulOptimizerTests/mainFunction/multi_fun_mixed.yul b/test/libjulia/yulOptimizerTests/mainFunction/multi_fun_mixed.yul new file mode 100644 index 00000000..dd5caaec --- /dev/null +++ b/test/libjulia/yulOptimizerTests/mainFunction/multi_fun_mixed.yul @@ -0,0 +1,26 @@ +// yul +{ + let a:u256 + function f() { let b:u256 } + let c:u256 + function g() { let d:u256 } + let e:u256 +} +// ---- +// mainFunction +// { +// function main() +// { +// let a:u256 +// let c:u256 +// let e:u256 +// } +// function f() +// { +// let b:u256 +// } +// function g() +// { +// let d:u256 +// } +// } diff --git a/test/libjulia/yulOptimizerTests/mainFunction/nested_fun.yul b/test/libjulia/yulOptimizerTests/mainFunction/nested_fun.yul new file mode 100644 index 00000000..309b97cc --- /dev/null +++ b/test/libjulia/yulOptimizerTests/mainFunction/nested_fun.yul @@ -0,0 +1,26 @@ +// yul +{ + let a:u256 + function f() { + let b:u256 + function g() { let c:u256} + let d:u256 + } +} +// ---- +// mainFunction +// { +// function main() +// { +// let a:u256 +// } +// function f() +// { +// let b:u256 +// function g() +// { +// let c:u256 +// } +// let d:u256 +// } +// } diff --git a/test/libjulia/yulOptimizerTests/mainFunction/sigle_fun.yul b/test/libjulia/yulOptimizerTests/mainFunction/sigle_fun.yul new file mode 100644 index 00000000..fa9a8f41 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/mainFunction/sigle_fun.yul @@ -0,0 +1,16 @@ +// yul +{ + let a:u256 + function f() {} +} +// ---- +// mainFunction +// { +// function main() +// { +// let a:u256 +// } +// function f() +// { +// } +// } diff --git a/test/libjulia/yulOptimizerTests/mainFunction/smoke.yul b/test/libjulia/yulOptimizerTests/mainFunction/smoke.yul new file mode 100644 index 00000000..7be14746 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/mainFunction/smoke.yul @@ -0,0 +1,9 @@ +// yul +{} +// ---- +// mainFunction +// { +// function main() +// { +// } +// } -- cgit From 6dfd0adc0ba5673071f280ee5f68806f5aeecebd Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 11 Oct 2018 17:59:45 +0200 Subject: Move rematerialiser tests. --- test/libjulia/Rematerialiser.cpp | 179 --------------------- test/libjulia/YulOptimizerTest.cpp | 6 + .../rematerialiser/branches_for1.yul | 21 +++ .../rematerialiser/branches_for2.yul | 25 +++ .../branches_for_declared_in_init1.yul | 23 +++ .../branches_for_declared_in_init2.yul | 24 +++ .../rematerialiser/branches_if.yul | 18 +++ .../rematerialiser/branches_switch.yul | 24 +++ .../rematerialiser/do_not_move_out_of_scope.yul | 19 +++ .../do_not_remat_large_amounts_of_code1.yul | 10 ++ .../do_not_remat_large_amounts_of_code2.yul | 10 ++ .../rematerialiser/expression.yul | 10 ++ .../rematerialiser/non_movable_function.yul | 18 +++ .../rematerialiser/non_movable_instruction.yul | 14 ++ .../yulOptimizerTests/rematerialiser/reassign.yul | 21 +++ .../rematerialiser/reassignment.yul | 19 +++ .../yulOptimizerTests/rematerialiser/smoke.yul | 5 + .../yulOptimizerTests/rematerialiser/trivial.yul | 12 ++ .../rematerialiser/update_asignment_remat.yul | 13 ++ 19 files changed, 292 insertions(+), 179 deletions(-) delete mode 100644 test/libjulia/Rematerialiser.cpp create mode 100644 test/libjulia/yulOptimizerTests/rematerialiser/branches_for1.yul create mode 100644 test/libjulia/yulOptimizerTests/rematerialiser/branches_for2.yul create mode 100644 test/libjulia/yulOptimizerTests/rematerialiser/branches_for_declared_in_init1.yul create mode 100644 test/libjulia/yulOptimizerTests/rematerialiser/branches_for_declared_in_init2.yul create mode 100644 test/libjulia/yulOptimizerTests/rematerialiser/branches_if.yul create mode 100644 test/libjulia/yulOptimizerTests/rematerialiser/branches_switch.yul create mode 100644 test/libjulia/yulOptimizerTests/rematerialiser/do_not_move_out_of_scope.yul create mode 100644 test/libjulia/yulOptimizerTests/rematerialiser/do_not_remat_large_amounts_of_code1.yul create mode 100644 test/libjulia/yulOptimizerTests/rematerialiser/do_not_remat_large_amounts_of_code2.yul create mode 100644 test/libjulia/yulOptimizerTests/rematerialiser/expression.yul create mode 100644 test/libjulia/yulOptimizerTests/rematerialiser/non_movable_function.yul create mode 100644 test/libjulia/yulOptimizerTests/rematerialiser/non_movable_instruction.yul create mode 100644 test/libjulia/yulOptimizerTests/rematerialiser/reassign.yul create mode 100644 test/libjulia/yulOptimizerTests/rematerialiser/reassignment.yul create mode 100644 test/libjulia/yulOptimizerTests/rematerialiser/smoke.yul create mode 100644 test/libjulia/yulOptimizerTests/rematerialiser/trivial.yul create mode 100644 test/libjulia/yulOptimizerTests/rematerialiser/update_asignment_remat.yul diff --git a/test/libjulia/Rematerialiser.cpp b/test/libjulia/Rematerialiser.cpp deleted file mode 100644 index 63e525d5..00000000 --- a/test/libjulia/Rematerialiser.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** - * @date 2017 - * Unit tests for the rematerialiser optimizer stage. - */ - -#include - -#include - -#include - -#include - -#include -#include - -using namespace std; -using namespace dev; -using namespace dev::julia; -using namespace dev::julia::test; -using namespace dev::solidity; - - -#define CHECK(_original, _expectation)\ -do\ -{\ - assembly::AsmPrinter p;\ - Block b = disambiguate(_original, false);\ - (Rematerialiser{})(b);\ - string result = p(b);\ - BOOST_CHECK_EQUAL(result, format(_expectation, false));\ -}\ -while(false) - -BOOST_AUTO_TEST_SUITE(YulRematerialiser) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - CHECK("{ }", "{ }"); -} - -BOOST_AUTO_TEST_CASE(trivial) -{ - CHECK( - "{ let a := 1 let b := a mstore(0, b) }", - "{ let a := 1 let b := 1 mstore(0, 1) }" - ); -} - -BOOST_AUTO_TEST_CASE(expression) -{ - CHECK( - "{ let a := add(mul(calldatasize(), 2), number()) let b := add(a, a) }", - "{ let a := add(mul(calldatasize(), 2), number()) let b := add(" - "add(mul(calldatasize(), 2), number())," - "add(mul(calldatasize(), 2), number())" - ") }" - ); -} - -BOOST_AUTO_TEST_CASE(reassign) -{ - CHECK( - "{ let a := extcodesize(0) let b := a let c := b a := 2 let d := add(b, c) pop(a) pop(b) pop(c) pop(d) }", - "{ let a := extcodesize(0) let b := a let c := a a := 2 let d := add(b, c) pop(2) pop(b) pop(c) pop(add(b, c)) }" - ); -} - -BOOST_AUTO_TEST_CASE(non_movable_instr) -{ - CHECK( - "{ let a := 1 let b := mload(a) let c := a mstore(add(a, b), c) }", - "{ let a := 1 let b := mload(1) let c := 1 mstore(add(1, b), 1) }" - ); -} - -BOOST_AUTO_TEST_CASE(non_movable_fun) -{ - CHECK( - "{ function f(x) -> y {} let a := 1 let b := f(a) let c := a mstore(add(a, b), c) }", - "{ function f(x) -> y {} let a := 1 let b := f(1) let c := 1 mstore(add(1, b), 1) }" - ); -} - -BOOST_AUTO_TEST_CASE(branches_if) -{ - CHECK( - "{ let a := 1 let b := 2 if b { pop(b) b := a } let c := b }", - "{ let a := 1 let b := 2 if 2 { pop(2) b := 1 } let c := b }" - ); -} - -BOOST_AUTO_TEST_CASE(branches_switch) -{ - CHECK( - "{ let a := 1 let b := 2 switch number() case 1 { b := a } default { let x := a let y := b b := a } pop(add(a, b)) }", - "{ let a := 1 let b := 2 switch number() case 1 { b := 1 } default { let x := 1 let y := b b := 1 } pop(add(1, b)) }" - ); -} - -BOOST_AUTO_TEST_CASE(branches_for) -{ - CHECK( - "{ let a := 1 for { pop(a) } a { pop(a) } { pop(a) } }", - "{ let a := 1 for { pop(1) } 1 { pop(1) } { pop(1) } }" - ); - CHECK( - "{ let a := 1 for { pop(a) } a { pop(a) } { a := 7 let c := a } let x := a }", - "{ let a := 1 for { pop(1) } a { pop(7) } { a := 7 let c := 7 } let x := a }" - ); -} - -BOOST_AUTO_TEST_CASE(branches_for_declared_in_init) -{ - CHECK( - "{ let b := 0 for { let a := 1 pop(a) } a { pop(a) } { b := 1 pop(a) } }", - "{ let b := 0 for { let a := 1 pop(1) } 1 { pop(1) } { b := 1 pop(1) } }" - ); - CHECK( - "{ let b := 0 for { let a := 1 pop(a) } lt(a, 0) { pop(a) a := add(a, 3) } { b := 1 pop(a) } }", - "{ let b := 0 for { let a := 1 pop(1) } lt(a, 0) { pop(a) a := add(a, 3) } { b := 1 pop(a) } }" - ); -} - -BOOST_AUTO_TEST_CASE(reassignment) -{ - CHECK( - "{ let a := 1 pop(a) if a { a := 2 } let b := mload(a) pop(b) }", - "{ let a := 1 pop(1) if 1 { a := 2 } let b := mload(a) pop(b) }" - ); -} - -BOOST_AUTO_TEST_CASE(update_assignment_remat) -{ - // We cannot substitute `a` in `let b := a` - CHECK( - "{ let a := extcodesize(0) a := mul(a, 2) let b := a }", - "{ let a := extcodesize(0) a := mul(a, 2) let b := a }" - ); -} - -BOOST_AUTO_TEST_CASE(do_not_move_out_of_scope) -{ - // Cannot replace by `let b := x` by `let b := a` since a is out of scope. - CHECK( - "{ let x { let a := sload(0) x := a } let b := x }", - "{ let x { let a := sload(0) x := a } let b := x }" - ); -} - -BOOST_AUTO_TEST_CASE(do_not_remat_large_amounts_of_code) -{ - CHECK( - "{ let x := add(mul(calldataload(2), calldataload(4)), mul(2, calldatasize())) let b := x }", - "{ let x := add(mul(calldataload(2), calldataload(4)), mul(2, calldatasize())) let b := x }" - ); - CHECK( - "{ let x := add(mul(calldataload(2), calldataload(4)), calldatasize()) let b := x }", - "{ let x := add(mul(calldataload(2), calldataload(4)), calldatasize()) let b := add(mul(calldataload(2), calldataload(4)), calldatasize()) }" - ); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libjulia/YulOptimizerTest.cpp b/test/libjulia/YulOptimizerTest.cpp index 0e55c87d..4cd063a8 100644 --- a/test/libjulia/YulOptimizerTest.cpp +++ b/test/libjulia/YulOptimizerTest.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -128,6 +129,11 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con (FunctionGrouper{})(*m_ast); (MainFunction{})(*m_ast); } + else if (m_optimizerStep == "rematerialiser") + { + disambiguate(); + (Rematerialiser{})(*m_ast); + } else { FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Invalid optimizer step: " << m_optimizerStep << endl; diff --git a/test/libjulia/yulOptimizerTests/rematerialiser/branches_for1.yul b/test/libjulia/yulOptimizerTests/rematerialiser/branches_for1.yul new file mode 100644 index 00000000..dbd1ee63 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/rematerialiser/branches_for1.yul @@ -0,0 +1,21 @@ +{ + let a := 1 + for { pop(a) } a { pop(a) } { + pop(a) + } +} +// ---- +// rematerialiser +// { +// let a := 1 +// for { +// pop(1) +// } +// 1 +// { +// pop(1) +// } +// { +// pop(1) +// } +// } diff --git a/test/libjulia/yulOptimizerTests/rematerialiser/branches_for2.yul b/test/libjulia/yulOptimizerTests/rematerialiser/branches_for2.yul new file mode 100644 index 00000000..6a52e045 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/rematerialiser/branches_for2.yul @@ -0,0 +1,25 @@ +{ + let a := 1 + for { pop(a) } a { pop(a) } { + a := 7 + let c := a + } + let x := a +} +// ---- +// rematerialiser +// { +// let a := 1 +// for { +// pop(1) +// } +// a +// { +// pop(7) +// } +// { +// a := 7 +// let c := 7 +// } +// let x := a +// } diff --git a/test/libjulia/yulOptimizerTests/rematerialiser/branches_for_declared_in_init1.yul b/test/libjulia/yulOptimizerTests/rematerialiser/branches_for_declared_in_init1.yul new file mode 100644 index 00000000..fc816419 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/rematerialiser/branches_for_declared_in_init1.yul @@ -0,0 +1,23 @@ +{ + let b := 0 + for { let a := 1 pop(a) } a { pop(a) } { + b := 1 pop(a) + } +} +// ---- +// rematerialiser +// { +// let b := 0 +// for { +// let a := 1 +// pop(1) +// } +// 1 +// { +// pop(1) +// } +// { +// b := 1 +// pop(1) +// } +// } diff --git a/test/libjulia/yulOptimizerTests/rematerialiser/branches_for_declared_in_init2.yul b/test/libjulia/yulOptimizerTests/rematerialiser/branches_for_declared_in_init2.yul new file mode 100644 index 00000000..3d916890 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/rematerialiser/branches_for_declared_in_init2.yul @@ -0,0 +1,24 @@ +{ + let b := 0 + for { let a := 1 pop(a) } lt(a, 0) { pop(a) a := add(a, 3) } { + b := 1 pop(a) + } +} +// ---- +// rematerialiser +// { +// let b := 0 +// for { +// let a := 1 +// pop(1) +// } +// lt(a, 0) +// { +// pop(a) +// a := add(a, 3) +// } +// { +// b := 1 +// pop(a) +// } +// } diff --git a/test/libjulia/yulOptimizerTests/rematerialiser/branches_if.yul b/test/libjulia/yulOptimizerTests/rematerialiser/branches_if.yul new file mode 100644 index 00000000..c148c2f2 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/rematerialiser/branches_if.yul @@ -0,0 +1,18 @@ +{ + let a := 1 + let b := 2 + if b { pop(b) b := a } + let c := b +} +// ---- +// rematerialiser +// { +// let a := 1 +// let b := 2 +// if 2 +// { +// pop(2) +// b := 1 +// } +// let c := b +// } diff --git a/test/libjulia/yulOptimizerTests/rematerialiser/branches_switch.yul b/test/libjulia/yulOptimizerTests/rematerialiser/branches_switch.yul new file mode 100644 index 00000000..8f70a79d --- /dev/null +++ b/test/libjulia/yulOptimizerTests/rematerialiser/branches_switch.yul @@ -0,0 +1,24 @@ +{ + let a := 1 + let b := 2 + switch number() + case 1 { b := a } + default { let x := a let y := b b := a } + pop(add(a, b)) +} +// ---- +// rematerialiser +// { +// let a := 1 +// let b := 2 +// switch number() +// case 1 { +// b := 1 +// } +// default { +// let x := 1 +// let y := b +// b := 1 +// } +// pop(add(1, b)) +// } diff --git a/test/libjulia/yulOptimizerTests/rematerialiser/do_not_move_out_of_scope.yul b/test/libjulia/yulOptimizerTests/rematerialiser/do_not_move_out_of_scope.yul new file mode 100644 index 00000000..891a5043 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/rematerialiser/do_not_move_out_of_scope.yul @@ -0,0 +1,19 @@ +// Cannot replace `let b := x` by `let b := a` since a is out of scope. +{ + let x + { + let a := sload(0) + x := a + } + let b := x +} +// ---- +// rematerialiser +// { +// let x +// { +// let a := sload(0) +// x := a +// } +// let b := x +// } diff --git a/test/libjulia/yulOptimizerTests/rematerialiser/do_not_remat_large_amounts_of_code1.yul b/test/libjulia/yulOptimizerTests/rematerialiser/do_not_remat_large_amounts_of_code1.yul new file mode 100644 index 00000000..016fa0d7 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/rematerialiser/do_not_remat_large_amounts_of_code1.yul @@ -0,0 +1,10 @@ +{ + let x := add(mul(calldataload(2), calldataload(4)), mul(2, calldatasize())) + let b := x +} +// ---- +// rematerialiser +// { +// let x := add(mul(calldataload(2), calldataload(4)), mul(2, calldatasize())) +// let b := x +// } diff --git a/test/libjulia/yulOptimizerTests/rematerialiser/do_not_remat_large_amounts_of_code2.yul b/test/libjulia/yulOptimizerTests/rematerialiser/do_not_remat_large_amounts_of_code2.yul new file mode 100644 index 00000000..d95dc1fc --- /dev/null +++ b/test/libjulia/yulOptimizerTests/rematerialiser/do_not_remat_large_amounts_of_code2.yul @@ -0,0 +1,10 @@ +{ + let x := add(mul(calldataload(2), calldataload(4)), calldatasize()) + let b := x +} +// ---- +// rematerialiser +// { +// let x := add(mul(calldataload(2), calldataload(4)), calldatasize()) +// let b := add(mul(calldataload(2), calldataload(4)), calldatasize()) +// } diff --git a/test/libjulia/yulOptimizerTests/rematerialiser/expression.yul b/test/libjulia/yulOptimizerTests/rematerialiser/expression.yul new file mode 100644 index 00000000..a801677d --- /dev/null +++ b/test/libjulia/yulOptimizerTests/rematerialiser/expression.yul @@ -0,0 +1,10 @@ +{ + let a := add(mul(calldatasize(), 2), number()) + let b := add(a, a) +} +// ---- +// rematerialiser +// { +// let a := add(mul(calldatasize(), 2), number()) +// let b := add(add(mul(calldatasize(), 2), number()), add(mul(calldatasize(), 2), number())) +// } diff --git a/test/libjulia/yulOptimizerTests/rematerialiser/non_movable_function.yul b/test/libjulia/yulOptimizerTests/rematerialiser/non_movable_function.yul new file mode 100644 index 00000000..9a041dfc --- /dev/null +++ b/test/libjulia/yulOptimizerTests/rematerialiser/non_movable_function.yul @@ -0,0 +1,18 @@ +{ + function f(x) -> y {} + let a := 1 + let b := f(a) + let c := a + mstore(add(a, b), c) +} +// ---- +// rematerialiser +// { +// function f(x) -> y +// { +// } +// let a := 1 +// let b := f(1) +// let c := 1 +// mstore(add(1, b), 1) +// } diff --git a/test/libjulia/yulOptimizerTests/rematerialiser/non_movable_instruction.yul b/test/libjulia/yulOptimizerTests/rematerialiser/non_movable_instruction.yul new file mode 100644 index 00000000..8767abc9 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/rematerialiser/non_movable_instruction.yul @@ -0,0 +1,14 @@ +{ + let a := 1 + let b := mload(a) + let c := a + mstore(add(a, b), c) +} +// ---- +// rematerialiser +// { +// let a := 1 +// let b := mload(1) +// let c := 1 +// mstore(add(1, b), 1) +// } diff --git a/test/libjulia/yulOptimizerTests/rematerialiser/reassign.yul b/test/libjulia/yulOptimizerTests/rematerialiser/reassign.yul new file mode 100644 index 00000000..47124658 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/rematerialiser/reassign.yul @@ -0,0 +1,21 @@ +{ + let a := extcodesize(0) + let b := a + let c := b + a := 2 + let d := add(b, c) + pop(a) pop(b) pop(c) pop(d) +} +// ---- +// rematerialiser +// { +// let a := extcodesize(0) +// let b := a +// let c := a +// a := 2 +// let d := add(b, c) +// pop(2) +// pop(b) +// pop(c) +// pop(add(b, c)) +// } diff --git a/test/libjulia/yulOptimizerTests/rematerialiser/reassignment.yul b/test/libjulia/yulOptimizerTests/rematerialiser/reassignment.yul new file mode 100644 index 00000000..13238780 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/rematerialiser/reassignment.yul @@ -0,0 +1,19 @@ +{ + let a := 1 + pop(a) + if a { a := 2 } + let b := mload(a) + pop(b) +} +// ---- +// rematerialiser +// { +// let a := 1 +// pop(1) +// if 1 +// { +// a := 2 +// } +// let b := mload(a) +// pop(b) +// } diff --git a/test/libjulia/yulOptimizerTests/rematerialiser/smoke.yul b/test/libjulia/yulOptimizerTests/rematerialiser/smoke.yul new file mode 100644 index 00000000..2423db32 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/rematerialiser/smoke.yul @@ -0,0 +1,5 @@ +{} +// ---- +// rematerialiser +// { +// } diff --git a/test/libjulia/yulOptimizerTests/rematerialiser/trivial.yul b/test/libjulia/yulOptimizerTests/rematerialiser/trivial.yul new file mode 100644 index 00000000..d29ea98a --- /dev/null +++ b/test/libjulia/yulOptimizerTests/rematerialiser/trivial.yul @@ -0,0 +1,12 @@ +{ + let a := 1 + let b := a + mstore(0, b) +} +// ---- +// rematerialiser +// { +// let a := 1 +// let b := 1 +// mstore(0, 1) +// } diff --git a/test/libjulia/yulOptimizerTests/rematerialiser/update_asignment_remat.yul b/test/libjulia/yulOptimizerTests/rematerialiser/update_asignment_remat.yul new file mode 100644 index 00000000..7d35fee0 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/rematerialiser/update_asignment_remat.yul @@ -0,0 +1,13 @@ +// We cannot substitute `a` in `let b := a` +{ + let a := extcodesize(0) + a := mul(a, 2) + let b := a +} +// ---- +// rematerialiser +// { +// let a := extcodesize(0) +// a := mul(a, 2) +// let b := a +// } -- cgit From 463642996ada7ac53ca6baef82626083367f4877 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 11 Oct 2018 18:35:13 +0200 Subject: Move expression simplifier tests. --- test/libjulia/Simplifier.cpp | 178 --------------------- test/libjulia/YulOptimizerTest.cpp | 6 + .../expressionSimplifier/constant_propagation.yul | 6 + .../expressionSimplifier/constants.yul | 6 + .../identity_rules_complex.yul | 6 + .../identity_rules_negative.yul | 6 + .../expressionSimplifier/identity_rules_simple.yul | 10 ++ .../including_function_calls.yul | 12 ++ .../expressionSimplifier/inside_for.yul | 16 ++ .../expressionSimplifier/invariant.yul | 10 ++ .../expressionSimplifier/mod_and_1.yul | 8 + .../expressionSimplifier/mod_and_2.yul | 8 + ...t_applied_function_call_different_arguments.yul | 12 ++ .../not_applied_function_call_different_names.yul | 16 ++ ..._applied_function_call_equality_not_movable.yul | 13 ++ ...pplied_removes_non_constant_and_not_movable.yul | 10 ++ .../expressionSimplifier/reversed.yul | 8 + .../expressionSimplifier/smoke.yul | 5 + 18 files changed, 158 insertions(+), 178 deletions(-) delete mode 100644 test/libjulia/Simplifier.cpp create mode 100644 test/libjulia/yulOptimizerTests/expressionSimplifier/constant_propagation.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionSimplifier/constants.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionSimplifier/identity_rules_complex.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionSimplifier/identity_rules_negative.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionSimplifier/identity_rules_simple.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionSimplifier/including_function_calls.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionSimplifier/inside_for.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionSimplifier/invariant.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionSimplifier/mod_and_1.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionSimplifier/mod_and_2.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_arguments.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_names.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionSimplifier/not_applied_function_call_equality_not_movable.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionSimplifier/not_applied_removes_non_constant_and_not_movable.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionSimplifier/reversed.yul create mode 100644 test/libjulia/yulOptimizerTests/expressionSimplifier/smoke.yul diff --git a/test/libjulia/Simplifier.cpp b/test/libjulia/Simplifier.cpp deleted file mode 100644 index 3cc95b7a..00000000 --- a/test/libjulia/Simplifier.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** - * @date 2017 - * Unit tests for the expression simplifier optimizer stage. - */ - -#include - -#include - -#include - -#include - -#include -#include - -using namespace std; -using namespace dev; -using namespace dev::julia; -using namespace dev::julia::test; -using namespace dev::solidity; - - -#define CHECK(_original, _expectation)\ -do\ -{\ - assembly::AsmPrinter p;\ - Block b = *(parse(_original, false).first);\ - (ExpressionSimplifier{})(b);\ - string result = p(b);\ - BOOST_CHECK_EQUAL(result, format(_expectation, false));\ -}\ -while(false) - -BOOST_AUTO_TEST_SUITE(YulSimplifier) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - CHECK("{ }", "{ }"); -} - -BOOST_AUTO_TEST_CASE(constants) -{ - CHECK( - "{ let a := add(1, mul(3, 4)) }", - "{ let a := 13 }" - ); -} - -BOOST_AUTO_TEST_CASE(invariant) -{ - CHECK( - "{ let a := mload(sub(7, 7)) let b := sub(a, 0) }", - "{ let a := mload(0) let b := a }" - ); -} - -BOOST_AUTO_TEST_CASE(reversed) -{ - CHECK( - "{ let a := add(0, mload(0)) }", - "{ let a := mload(0) }" - ); -} - -BOOST_AUTO_TEST_CASE(constant_propagation) -{ - CHECK( - "{ let a := add(7, sub(mload(0), 7)) }", - "{ let a := mload(0) }" - ); -} - -BOOST_AUTO_TEST_CASE(identity_rules_simple) -{ - CHECK( - "{ let a := mload(0) let b := sub(a, a) }", - "{ let a := mload(0) let b := 0 }" - ); -} - -BOOST_AUTO_TEST_CASE(identity_rules_complex) -{ - CHECK( - "{ let a := sub(calldataload(0), calldataload(0)) }", - "{ let a := 0 }" - ); -} - -BOOST_AUTO_TEST_CASE(identity_rules_negative) -{ - CHECK( - "{ let a := sub(calldataload(1), calldataload(0)) }", - "{ let a := sub(calldataload(1), calldataload(0)) }" - ); -} - -BOOST_AUTO_TEST_CASE(including_function_calls) -{ - CHECK( - "{ function f() -> a {} let b := add(7, sub(f(), 7)) }", - "{ function f() -> a {} let b := f() }" - ); -} - -BOOST_AUTO_TEST_CASE(inside_for) -{ - CHECK( - "{ for { let a := 10 } iszero(eq(a, 0)) { a := add(a, 1) } {} }", - "{ for { let a := 10 } iszero(iszero(a)) { a := add(a, 1) } {} }" - ); -} - -BOOST_AUTO_TEST_CASE(mod_and) -{ - CHECK( - "{ mstore(0, mod(calldataload(0), exp(2, 8))) }", - "{ mstore(0, and(calldataload(0), 255)) }" - ); - CHECK( - "{ mstore(0, mod(calldataload(0), exp(2, 255))) }", - "{ mstore(0, and(calldataload(0), 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)) }" - ); -} - -BOOST_AUTO_TEST_CASE(not_applied_removes_non_constant_and_not_movable) -{ - CHECK( - // The first argument of div is not constant. - // keccak256 is not movable. - "{ let a := div(keccak256(0, 0), 0) }", - "{ let a := div(keccak256(0, 0), 0) }" - ); -} - -BOOST_AUTO_TEST_CASE(not_applied_function_call_different_names) -{ - CHECK( - "{ function f1() -> a { } function f2() -> b {} let c := sub(f1(), f2()) }", - "{ function f1() -> a { } function f2() -> b {} let c := sub(f1(), f2()) }" - ); -} - -BOOST_AUTO_TEST_CASE(not_applied_function_call_different_arguments) -{ - CHECK( - "{ function f(a) -> b { } let c := sub(f(0), f(1)) }", - "{ function f(a) -> b { } let c := sub(f(0), f(1)) }" - ); -} - -BOOST_AUTO_TEST_CASE(not_applied_function_call_equality_not_movable) -{ - CHECK( - // Even if the functions pass the equality check, they are not movable. - "{ function f() -> a { } let b := sub(f(), f()) }", - "{ function f() -> a { } let b := sub(f(), f()) }" - ); -} - - -BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libjulia/YulOptimizerTest.cpp b/test/libjulia/YulOptimizerTest.cpp index 4cd063a8..2d79674b 100644 --- a/test/libjulia/YulOptimizerTest.cpp +++ b/test/libjulia/YulOptimizerTest.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -134,6 +135,11 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con disambiguate(); (Rematerialiser{})(*m_ast); } + else if (m_optimizerStep == "expressionSimplifier") + { + disambiguate(); + (ExpressionSimplifier{})(*m_ast); + } else { FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Invalid optimizer step: " << m_optimizerStep << endl; diff --git a/test/libjulia/yulOptimizerTests/expressionSimplifier/constant_propagation.yul b/test/libjulia/yulOptimizerTests/expressionSimplifier/constant_propagation.yul new file mode 100644 index 00000000..0b55adc5 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionSimplifier/constant_propagation.yul @@ -0,0 +1,6 @@ +{ let a := add(7, sub(mload(0), 7)) } +// ---- +// expressionSimplifier +// { +// let a := mload(0) +// } diff --git a/test/libjulia/yulOptimizerTests/expressionSimplifier/constants.yul b/test/libjulia/yulOptimizerTests/expressionSimplifier/constants.yul new file mode 100644 index 00000000..bd1a5a53 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionSimplifier/constants.yul @@ -0,0 +1,6 @@ +{ let a := add(1, mul(3, 4)) } +// ---- +// expressionSimplifier +// { +// let a := 13 +// } diff --git a/test/libjulia/yulOptimizerTests/expressionSimplifier/identity_rules_complex.yul b/test/libjulia/yulOptimizerTests/expressionSimplifier/identity_rules_complex.yul new file mode 100644 index 00000000..f6190622 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionSimplifier/identity_rules_complex.yul @@ -0,0 +1,6 @@ +{ let a := sub(calldataload(0), calldataload(0)) } +// ---- +// expressionSimplifier +// { +// let a := 0 +// } diff --git a/test/libjulia/yulOptimizerTests/expressionSimplifier/identity_rules_negative.yul b/test/libjulia/yulOptimizerTests/expressionSimplifier/identity_rules_negative.yul new file mode 100644 index 00000000..e91403cd --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionSimplifier/identity_rules_negative.yul @@ -0,0 +1,6 @@ +{ let a := sub(calldataload(1), calldataload(0)) } +// ---- +// expressionSimplifier +// { +// let a := sub(calldataload(1), calldataload(0)) +// } diff --git a/test/libjulia/yulOptimizerTests/expressionSimplifier/identity_rules_simple.yul b/test/libjulia/yulOptimizerTests/expressionSimplifier/identity_rules_simple.yul new file mode 100644 index 00000000..d35686cd --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionSimplifier/identity_rules_simple.yul @@ -0,0 +1,10 @@ +{ + let a := mload(0) + let b := sub(a, a) +} +// ---- +// expressionSimplifier +// { +// let a := mload(0) +// let b := 0 +// } diff --git a/test/libjulia/yulOptimizerTests/expressionSimplifier/including_function_calls.yul b/test/libjulia/yulOptimizerTests/expressionSimplifier/including_function_calls.yul new file mode 100644 index 00000000..c2ca504a --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionSimplifier/including_function_calls.yul @@ -0,0 +1,12 @@ +{ + function f() -> a {} + let b := add(7, sub(f(), 7)) +} +// ---- +// expressionSimplifier +// { +// function f() -> a +// { +// } +// let b := f() +// } diff --git a/test/libjulia/yulOptimizerTests/expressionSimplifier/inside_for.yul b/test/libjulia/yulOptimizerTests/expressionSimplifier/inside_for.yul new file mode 100644 index 00000000..42c37826 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionSimplifier/inside_for.yul @@ -0,0 +1,16 @@ +{ + for { let a := 10 } iszero(eq(a, 0)) { a := add(a, 1) } {} +} +// ---- +// expressionSimplifier +// { +// for { +// let a := 10 +// } +// iszero(iszero(a)) +// { +// a := add(a, 1) +// } +// { +// } +// } diff --git a/test/libjulia/yulOptimizerTests/expressionSimplifier/invariant.yul b/test/libjulia/yulOptimizerTests/expressionSimplifier/invariant.yul new file mode 100644 index 00000000..e6d84552 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionSimplifier/invariant.yul @@ -0,0 +1,10 @@ +{ + let a := mload(sub(7, 7)) + let b := sub(a, 0) +} +// ---- +// expressionSimplifier +// { +// let a := mload(0) +// let b := a +// } diff --git a/test/libjulia/yulOptimizerTests/expressionSimplifier/mod_and_1.yul b/test/libjulia/yulOptimizerTests/expressionSimplifier/mod_and_1.yul new file mode 100644 index 00000000..88714ce0 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionSimplifier/mod_and_1.yul @@ -0,0 +1,8 @@ +{ + mstore(0, mod(calldataload(0), exp(2, 8))) +} +// ---- +// expressionSimplifier +// { +// mstore(0, and(calldataload(0), 255)) +// } diff --git a/test/libjulia/yulOptimizerTests/expressionSimplifier/mod_and_2.yul b/test/libjulia/yulOptimizerTests/expressionSimplifier/mod_and_2.yul new file mode 100644 index 00000000..4d52abe8 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionSimplifier/mod_and_2.yul @@ -0,0 +1,8 @@ +{ + mstore(0, mod(calldataload(0), exp(2, 255))) +} +// ---- +// expressionSimplifier +// { +// mstore(0, and(calldataload(0), 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)) +// } diff --git a/test/libjulia/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_arguments.yul b/test/libjulia/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_arguments.yul new file mode 100644 index 00000000..53270b72 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_arguments.yul @@ -0,0 +1,12 @@ +{ + function f(a) -> b { } + let c := sub(f(0), f(1)) +} +// ---- +// expressionSimplifier +// { +// function f(a) -> b +// { +// } +// let c := sub(f(0), f(1)) +// } diff --git a/test/libjulia/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_names.yul b/test/libjulia/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_names.yul new file mode 100644 index 00000000..6ab65d29 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionSimplifier/not_applied_function_call_different_names.yul @@ -0,0 +1,16 @@ +{ + function f1() -> a { } + function f2() -> b { } + let c := sub(f1(), f2()) +} +// ---- +// expressionSimplifier +// { +// function f1() -> a +// { +// } +// function f2() -> b +// { +// } +// let c := sub(f1(), f2()) +// } diff --git a/test/libjulia/yulOptimizerTests/expressionSimplifier/not_applied_function_call_equality_not_movable.yul b/test/libjulia/yulOptimizerTests/expressionSimplifier/not_applied_function_call_equality_not_movable.yul new file mode 100644 index 00000000..ab1bd128 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionSimplifier/not_applied_function_call_equality_not_movable.yul @@ -0,0 +1,13 @@ +// Even if the functions pass the equality check, they are not movable. +{ + function f() -> a { } + let b := sub(f(), f()) +} +// ---- +// expressionSimplifier +// { +// function f() -> a +// { +// } +// let b := sub(f(), f()) +// } diff --git a/test/libjulia/yulOptimizerTests/expressionSimplifier/not_applied_removes_non_constant_and_not_movable.yul b/test/libjulia/yulOptimizerTests/expressionSimplifier/not_applied_removes_non_constant_and_not_movable.yul new file mode 100644 index 00000000..fc61c3df --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionSimplifier/not_applied_removes_non_constant_and_not_movable.yul @@ -0,0 +1,10 @@ +// The first argument of div is not constant. +// keccak256 is not movable. +{ + let a := div(keccak256(0, 0), 0) +} +// ---- +// expressionSimplifier +// { +// let a := div(keccak256(0, 0), 0) +// } diff --git a/test/libjulia/yulOptimizerTests/expressionSimplifier/reversed.yul b/test/libjulia/yulOptimizerTests/expressionSimplifier/reversed.yul new file mode 100644 index 00000000..6353cda9 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionSimplifier/reversed.yul @@ -0,0 +1,8 @@ +{ + let a := add(0, mload(0)) +} +// ---- +// expressionSimplifier +// { +// let a := mload(0) +// } diff --git a/test/libjulia/yulOptimizerTests/expressionSimplifier/smoke.yul b/test/libjulia/yulOptimizerTests/expressionSimplifier/smoke.yul new file mode 100644 index 00000000..88420e92 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/expressionSimplifier/smoke.yul @@ -0,0 +1,5 @@ +{ } +// ---- +// expressionSimplifier +// { +// } -- cgit From a937a449df81928437bb6f367289c776fe842dc9 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 11 Oct 2018 18:41:01 +0200 Subject: Move unused pruner tests. --- test/libjulia/UnusedPruner.cpp | 129 --------------------- test/libjulia/YulOptimizerTest.cpp | 6 + .../yulOptimizerTests/unusedPruner/functions.yul | 8 ++ .../unusedPruner/intermediate_assignment.yul | 11 ++ .../unusedPruner/intermediate_multi_assignment.yul | 16 +++ .../unusedPruner/multi_assign.yul | 16 +++ .../unusedPruner/multi_assignments.yul | 12 ++ .../unusedPruner/multi_declarations.yul | 7 ++ .../unusedPruner/multi_declare.yul | 12 ++ .../unusedPruner/multi_partial_assignments.yul | 10 ++ .../yulOptimizerTests/unusedPruner/smoke.yul | 5 + .../yulOptimizerTests/unusedPruner/trivial.yul | 10 ++ 12 files changed, 113 insertions(+), 129 deletions(-) delete mode 100644 test/libjulia/UnusedPruner.cpp create mode 100644 test/libjulia/yulOptimizerTests/unusedPruner/functions.yul create mode 100644 test/libjulia/yulOptimizerTests/unusedPruner/intermediate_assignment.yul create mode 100644 test/libjulia/yulOptimizerTests/unusedPruner/intermediate_multi_assignment.yul create mode 100644 test/libjulia/yulOptimizerTests/unusedPruner/multi_assign.yul create mode 100644 test/libjulia/yulOptimizerTests/unusedPruner/multi_assignments.yul create mode 100644 test/libjulia/yulOptimizerTests/unusedPruner/multi_declarations.yul create mode 100644 test/libjulia/yulOptimizerTests/unusedPruner/multi_declare.yul create mode 100644 test/libjulia/yulOptimizerTests/unusedPruner/multi_partial_assignments.yul create mode 100644 test/libjulia/yulOptimizerTests/unusedPruner/smoke.yul create mode 100644 test/libjulia/yulOptimizerTests/unusedPruner/trivial.yul diff --git a/test/libjulia/UnusedPruner.cpp b/test/libjulia/UnusedPruner.cpp deleted file mode 100644 index 649ee149..00000000 --- a/test/libjulia/UnusedPruner.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - This file is part of solidity. - - solidity is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - solidity is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with solidity. If not, see . -*/ -/** - * @date 2017 - * Unit tests for the pruning of unused variables and functions. - */ - -#include - -#include - -#include - -#include - -#include -#include - -using namespace std; -using namespace dev; -using namespace dev::julia; -using namespace dev::julia::test; -using namespace dev::solidity; - - -#define CHECK(_original, _expectation)\ -do\ -{\ - assembly::AsmPrinter p;\ - Block b = disambiguate(_original, false);\ - UnusedPruner::runUntilStabilised(b);\ - string result = p(b);\ - BOOST_CHECK_EQUAL(result, format(_expectation, false));\ -}\ -while(false) - -BOOST_AUTO_TEST_SUITE(YulUnusedPruner) - -BOOST_AUTO_TEST_CASE(smoke_test) -{ - CHECK("{ }", "{ }"); -} - -BOOST_AUTO_TEST_CASE(trivial) -{ - CHECK( - "{ let a := 1 let b := 1 mstore(0, 1) }", - "{ mstore(0, 1) }" - ); -} - -BOOST_AUTO_TEST_CASE(multi_declarations) -{ - CHECK( - "{ let x, y }", - "{ }" - ); -} - -BOOST_AUTO_TEST_CASE(multi_assignments) -{ - CHECK( - "{ let x, y x := 1 y := 2 }", - "{ let x, y x := 1 y := 2 }" - ); -} - -BOOST_AUTO_TEST_CASE(multi_partial_assignments) -{ - CHECK( - "{ let x, y x := 1 }", - "{ let x, y x := 1 }" - ); -} - -BOOST_AUTO_TEST_CASE(functions) -{ - CHECK( - "{ function f() { let a := 1 } function g() { f() } }", - "{ }" - ); -} - -BOOST_AUTO_TEST_CASE(intermediate_assignment) -{ - CHECK( - "{ let a := 1 a := 4 let b := 1 }", - "{ let a := 1 a := 4 }" - ); -} - -BOOST_AUTO_TEST_CASE(intermediate_multi_assignment){ - CHECK( - "{ let a, b function f() -> x { } a := f() b := 1 }", - "{ let a, b function f() -> x { } a := f() b := 1 }" - ); -} - -BOOST_AUTO_TEST_CASE(multi_declare) -{ - CHECK( - "{ function f() -> x, y { } let a, b := f() }", - "{ function f() -> x, y { } let a, b := f() }" - ); -} - -BOOST_AUTO_TEST_CASE(multi_assign) -{ - CHECK( - "{ let a let b function f() -> x, y { } a, b := f() }", - "{ let a let b function f() -> x, y { } a, b := f() }" - ); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libjulia/YulOptimizerTest.cpp b/test/libjulia/YulOptimizerTest.cpp index 2d79674b..96e36a5b 100644 --- a/test/libjulia/YulOptimizerTest.cpp +++ b/test/libjulia/YulOptimizerTest.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -140,6 +141,11 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con disambiguate(); (ExpressionSimplifier{})(*m_ast); } + else if (m_optimizerStep == "unusedPruner") + { + disambiguate(); + UnusedPruner::runUntilStabilised(*m_ast); + } else { FormattedScope(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Invalid optimizer step: " << m_optimizerStep << endl; diff --git a/test/libjulia/yulOptimizerTests/unusedPruner/functions.yul b/test/libjulia/yulOptimizerTests/unusedPruner/functions.yul new file mode 100644 index 00000000..ec9cdda8 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/unusedPruner/functions.yul @@ -0,0 +1,8 @@ +{ + function f() { let a := 1 } + function g() { f() } +} +// ---- +// unusedPruner +// { +// } diff --git a/test/libjulia/yulOptimizerTests/unusedPruner/intermediate_assignment.yul b/test/libjulia/yulOptimizerTests/unusedPruner/intermediate_assignment.yul new file mode 100644 index 00000000..4ed6dd2c --- /dev/null +++ b/test/libjulia/yulOptimizerTests/unusedPruner/intermediate_assignment.yul @@ -0,0 +1,11 @@ +{ + let a := 1 + a := 4 + let b := 1 +} +// ---- +// unusedPruner +// { +// let a := 1 +// a := 4 +// } diff --git a/test/libjulia/yulOptimizerTests/unusedPruner/intermediate_multi_assignment.yul b/test/libjulia/yulOptimizerTests/unusedPruner/intermediate_multi_assignment.yul new file mode 100644 index 00000000..94d101e9 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/unusedPruner/intermediate_multi_assignment.yul @@ -0,0 +1,16 @@ +{ + let a, b + function f() -> x { } + a := f() + b := 1 +} +// ---- +// unusedPruner +// { +// let a, b +// function f() -> x +// { +// } +// a := f() +// b := 1 +// } diff --git a/test/libjulia/yulOptimizerTests/unusedPruner/multi_assign.yul b/test/libjulia/yulOptimizerTests/unusedPruner/multi_assign.yul new file mode 100644 index 00000000..a14dc28c --- /dev/null +++ b/test/libjulia/yulOptimizerTests/unusedPruner/multi_assign.yul @@ -0,0 +1,16 @@ +{ + let a + let b + function f() -> x, y { } + a, b := f() +} +// ---- +// unusedPruner +// { +// let a +// let b +// function f() -> x, y +// { +// } +// a, b := f() +// } diff --git a/test/libjulia/yulOptimizerTests/unusedPruner/multi_assignments.yul b/test/libjulia/yulOptimizerTests/unusedPruner/multi_assignments.yul new file mode 100644 index 00000000..fe94edb8 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/unusedPruner/multi_assignments.yul @@ -0,0 +1,12 @@ +{ + let x, y + x := 1 + y := 2 +} +// ---- +// unusedPruner +// { +// let x, y +// x := 1 +// y := 2 +// } diff --git a/test/libjulia/yulOptimizerTests/unusedPruner/multi_declarations.yul b/test/libjulia/yulOptimizerTests/unusedPruner/multi_declarations.yul new file mode 100644 index 00000000..3cf35007 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/unusedPruner/multi_declarations.yul @@ -0,0 +1,7 @@ +{ + let x, y +} +// ---- +// unusedPruner +// { +// } diff --git a/test/libjulia/yulOptimizerTests/unusedPruner/multi_declare.yul b/test/libjulia/yulOptimizerTests/unusedPruner/multi_declare.yul new file mode 100644 index 00000000..adabac87 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/unusedPruner/multi_declare.yul @@ -0,0 +1,12 @@ +{ + function f() -> x, y { } + let a, b := f() +} +// ---- +// unusedPruner +// { +// function f() -> x, y +// { +// } +// let a, b := f() +// } diff --git a/test/libjulia/yulOptimizerTests/unusedPruner/multi_partial_assignments.yul b/test/libjulia/yulOptimizerTests/unusedPruner/multi_partial_assignments.yul new file mode 100644 index 00000000..5db0ade9 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/unusedPruner/multi_partial_assignments.yul @@ -0,0 +1,10 @@ +{ + let x, y + x := 1 +} +// ---- +// unusedPruner +// { +// let x, y +// x := 1 +// } diff --git a/test/libjulia/yulOptimizerTests/unusedPruner/smoke.yul b/test/libjulia/yulOptimizerTests/unusedPruner/smoke.yul new file mode 100644 index 00000000..ca2ed942 --- /dev/null +++ b/test/libjulia/yulOptimizerTests/unusedPruner/smoke.yul @@ -0,0 +1,5 @@ +{ } +// ---- +// unusedPruner +// { +// } diff --git a/test/libjulia/yulOptimizerTests/unusedPruner/trivial.yul b/test/libjulia/yulOptimizerTests/unusedPruner/trivial.yul new file mode 100644 index 00000000..9b4cf9fd --- /dev/null +++ b/test/libjulia/yulOptimizerTests/unusedPruner/trivial.yul @@ -0,0 +1,10 @@ +{ + let a := 1 + let b := 1 + mstore(0, 1) +} +// ---- +// unusedPruner +// { +// mstore(0, 1) +// } -- cgit