aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md1
-rw-r--r--libevmasm/PeepholeOptimiser.cpp19
-rw-r--r--test/libevmasm/Optimiser.cpp25
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{