From 894df0fba9749a167825f9407efe33859484f335 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Mon, 13 May 2019 17:22:43 +0200 Subject: [PATCH] Block deepener --- libyul/CMakeLists.txt | 2 + libyul/optimiser/BlockDeepener.cpp | 47 +++++++++++++++++++ libyul/optimiser/BlockDeepener.h | 31 ++++++++++++ test/libyul/YulOptimizerTest.cpp | 6 +++ .../yulOptimizerTests/blockDeepener/basic.yul | 27 +++++++++++ .../blockDeepener/for_stmt.yul | 14 ++++++ .../blockDeepener/if_stmt.yul | 19 ++++++++ .../blockDeepener/many_nested_blocks.yul | 35 ++++++++++++++ .../blockDeepener/switch_stmt.yul | 31 ++++++++++++ 9 files changed, 212 insertions(+) create mode 100644 libyul/optimiser/BlockDeepener.cpp create mode 100644 libyul/optimiser/BlockDeepener.h create mode 100644 test/libyul/yulOptimizerTests/blockDeepener/basic.yul create mode 100644 test/libyul/yulOptimizerTests/blockDeepener/for_stmt.yul create mode 100644 test/libyul/yulOptimizerTests/blockDeepener/if_stmt.yul create mode 100644 test/libyul/yulOptimizerTests/blockDeepener/many_nested_blocks.yul create mode 100644 test/libyul/yulOptimizerTests/blockDeepener/switch_stmt.yul diff --git a/libyul/CMakeLists.txt b/libyul/CMakeLists.txt index 3d6beefee..175a443a1 100644 --- a/libyul/CMakeLists.txt +++ b/libyul/CMakeLists.txt @@ -52,6 +52,8 @@ add_library(yul optimiser/ASTCopier.h optimiser/ASTWalker.cpp optimiser/ASTWalker.h + optimiser/BlockDeepener.cpp + optimiser/BlockDeepener.h optimiser/BlockFlattener.cpp optimiser/BlockFlattener.h optimiser/BlockClassFinder.cpp diff --git a/libyul/optimiser/BlockDeepener.cpp b/libyul/optimiser/BlockDeepener.cpp new file mode 100644 index 000000000..0c094b21e --- /dev/null +++ b/libyul/optimiser/BlockDeepener.cpp @@ -0,0 +1,47 @@ +/* + 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 . +*/ +#include +#include +#include +#include +#include + +using namespace std; +using namespace dev; +using namespace yul; + +void BlockDeepener::operator()(Block& _block) +{ + ASTModifier::operator()(_block); + + if (_block.statements.size() <= 1) + return ; + std::vector result; + std::vector *current = &result; + for (std::size_t i = 0; i < _block.statements.size() - 1; ++i) + { + current->emplace_back(std::move(_block.statements[i])); + current->emplace_back(Block{ + _block.location, + {} + }); + current = &boost::get(current->back()).statements; + } + current->emplace_back(std::move(_block.statements.back())); + + _block.statements = std::move(result); +} diff --git a/libyul/optimiser/BlockDeepener.h b/libyul/optimiser/BlockDeepener.h new file mode 100644 index 000000000..a0521fe95 --- /dev/null +++ b/libyul/optimiser/BlockDeepener.h @@ -0,0 +1,31 @@ +/* + 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 . +*/ +#pragma once + +#include + +namespace yul +{ + +class BlockDeepener: public ASTModifier +{ +public: + using ASTModifier::operator(); + void operator()(Block& _block) override; +}; + +} diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp index fedc2ff0b..229889809 100644 --- a/test/libyul/YulOptimizerTest.cpp +++ b/test/libyul/YulOptimizerTest.cpp @@ -19,6 +19,7 @@ #include +#include #include #include #include @@ -112,6 +113,11 @@ TestCase::TestResult YulOptimizerTest::run(ostream& _stream, string const& _line if (m_optimizerStep == "disambiguator") disambiguate(); + else if (m_optimizerStep == "blockDeepener") + { + disambiguate(); + BlockDeepener{}(*m_ast); + } else if (m_optimizerStep == "blockFlattener") { disambiguate(); diff --git a/test/libyul/yulOptimizerTests/blockDeepener/basic.yul b/test/libyul/yulOptimizerTests/blockDeepener/basic.yul new file mode 100644 index 000000000..776045df2 --- /dev/null +++ b/test/libyul/yulOptimizerTests/blockDeepener/basic.yul @@ -0,0 +1,27 @@ +{ + let _1 := mload(0) + let f_a := mload(1) + let f_r + f_a := mload(f_a) + f_r := add(f_a, calldatasize()) + let z := mload(2) +} +// ==== +// step: blockDeepener +// ---- +// { +// let _1 := mload(0) +// { +// let f_a := mload(1) +// { +// let f_r +// { +// f_a := mload(f_a) +// { +// f_r := add(f_a, calldatasize()) +// { let z := mload(2) } +// } +// } +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/blockDeepener/for_stmt.yul b/test/libyul/yulOptimizerTests/blockDeepener/for_stmt.yul new file mode 100644 index 000000000..efb88eb2d --- /dev/null +++ b/test/libyul/yulOptimizerTests/blockDeepener/for_stmt.yul @@ -0,0 +1,14 @@ +{ + for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } + { a := add(a, 1) a := add(a,1) } +} +// ==== +// step: blockDeepener +// ---- +// { +// for { let a := 1 } iszero(eq(a, 10)) { a := add(a, 1) } +// { +// a := add(a, 1) +// { a := add(a, 1) } +// } +// } diff --git a/test/libyul/yulOptimizerTests/blockDeepener/if_stmt.yul b/test/libyul/yulOptimizerTests/blockDeepener/if_stmt.yul new file mode 100644 index 000000000..5d9f1eb43 --- /dev/null +++ b/test/libyul/yulOptimizerTests/blockDeepener/if_stmt.yul @@ -0,0 +1,19 @@ +{ + if add(mload(7), sload(mload(3))) + { + let y := add(mload(3), 3) + y := add(y, 7) + } + let t := add(3, 9) +} +// ==== +// step: blockDeepener +// ---- +// { +// if add(mload(7), sload(mload(3))) +// { +// let y := add(mload(3), 3) +// { y := add(y, 7) } +// } +// { let t := add(3, 9) } +// } diff --git a/test/libyul/yulOptimizerTests/blockDeepener/many_nested_blocks.yul b/test/libyul/yulOptimizerTests/blockDeepener/many_nested_blocks.yul new file mode 100644 index 000000000..8d8d319b3 --- /dev/null +++ b/test/libyul/yulOptimizerTests/blockDeepener/many_nested_blocks.yul @@ -0,0 +1,35 @@ +{ + let a := 3 + let b := 4 + a := add(b, 3) + let c := 5 + b := add(b, 4) + c := add(a, 5) + b := add(a, b) + a := add(a, c) +} +// ==== +// step: blockDeepener +// ---- +// { +// let a := 3 +// { +// let b := 4 +// { +// a := add(b, 3) +// { +// let c := 5 +// { +// b := add(b, 4) +// { +// c := add(a, 5) +// { +// b := add(a, b) +// { a := add(a, c) } +// } +// } +// } +// } +// } +// } +// } diff --git a/test/libyul/yulOptimizerTests/blockDeepener/switch_stmt.yul b/test/libyul/yulOptimizerTests/blockDeepener/switch_stmt.yul new file mode 100644 index 000000000..b3d5288c0 --- /dev/null +++ b/test/libyul/yulOptimizerTests/blockDeepener/switch_stmt.yul @@ -0,0 +1,31 @@ +{ + let a := 1 + switch calldataload(0) + case 0 { + mstore(0, 1) + a := 8 + } + default { + a := 3 + a := 4 + } + a := 5 +} +// ==== +// step: blockDeepener +// ---- +// { +// let a := 1 +// { +// switch calldataload(0) +// case 0 { +// mstore(0, 1) +// { a := 8 } +// } +// default { +// a := 3 +// { a := 4 } +// } +// { a := 5 } +// } +// }