diff options
-rw-r--r-- | Changelog.md | 1 | ||||
-rw-r--r-- | libevmasm/PeepholeOptimiser.cpp | 19 | ||||
-rw-r--r-- | test/libevmasm/Optimiser.cpp | 25 |
3 files changed, 44 insertions, 1 deletions
diff --git a/Changelog.md b/Changelog.md index f77ab809..3e63108e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -16,6 +16,7 @@ Breaking Changes: ``implements``, ``macro``, ``mutable``, ``override``, ``partial``, ``promise``, ``reference``, ``sealed``, ``sizeof``, ``supports``, ``typedef`` and ``unchecked``. * General: Remove assembly instruction aliases ``sha3`` and ``suicide`` + * Optimizer: Remove the no-op ``PUSH1 0 NOT AND`` sequence. * Parser: Disallow trailing dots that are not followed by a number. * Type Checker: Disallow arithmetic operations for boolean variables. * Type Checker: Disallow conversions between ``bytesX`` and ``uintY`` of different size. diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index 8a39de24..6d8e1df6 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -249,6 +249,23 @@ struct TagConjunctions: SimplePeepholeOptimizerMethod<TagConjunctions, 3> } }; +struct TruthyAnd: SimplePeepholeOptimizerMethod<TruthyAnd, 3> +{ + static bool applySimple( + AssemblyItem const& _push, + AssemblyItem const& _not, + AssemblyItem const& _and, + std::back_insert_iterator<AssemblyItems> + ) + { + return ( + _push.type() == Push && _push.data() == 0 && + _not == Instruction::NOT && + _and == Instruction::AND + ); + } +}; + /// Removes everything after a JUMP (or similar) until the next JUMPDEST. struct UnreachableCode { @@ -305,7 +322,7 @@ bool PeepholeOptimiser::optimise() { OptimiserState state {m_items, 0, std::back_inserter(m_optimisedItems)}; while (state.i < m_items.size()) - applyMethods(state, PushPop(), OpPop(), DoublePush(), DoubleSwap(), CommutativeSwap(), SwapComparison(), JumpToNext(), UnreachableCode(), TagConjunctions(), Identity()); + applyMethods(state, PushPop(), OpPop(), DoublePush(), DoubleSwap(), CommutativeSwap(), SwapComparison(), JumpToNext(), UnreachableCode(), TagConjunctions(), TruthyAnd(), Identity()); if (m_optimisedItems.size() < m_items.size() || ( m_optimisedItems.size() == m_items.size() && ( eth::bytesRequired(m_optimisedItems, 3) < eth::bytesRequired(m_items, 3) || diff --git a/test/libevmasm/Optimiser.cpp b/test/libevmasm/Optimiser.cpp index 4b399a14..5687ffcc 100644 --- a/test/libevmasm/Optimiser.cpp +++ b/test/libevmasm/Optimiser.cpp @@ -967,6 +967,31 @@ BOOST_AUTO_TEST_CASE(peephole_swap_comparison) } } +BOOST_AUTO_TEST_CASE(peephole_truthy_and) +{ + AssemblyItems items{ + AssemblyItem(Tag, 1), + Instruction::BALANCE, + u256(0), + Instruction::NOT, + Instruction::AND, + AssemblyItem(PushTag, 1), + Instruction::JUMPI + }; + AssemblyItems expectation{ + AssemblyItem(Tag, 1), + Instruction::BALANCE, + AssemblyItem(PushTag, 1), + Instruction::JUMPI + }; + PeepholeOptimiser peepOpt(items); + BOOST_REQUIRE(peepOpt.optimise()); + BOOST_CHECK_EQUAL_COLLECTIONS( + items.begin(), items.end(), + expectation.begin(), expectation.end() + ); +} + BOOST_AUTO_TEST_CASE(jumpdest_removal) { AssemblyItems items{ |