aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libevmasm/ExpressionClasses.cpp14
-rw-r--r--test/libsolidity/SolidityOptimizer.cpp23
2 files changed, 36 insertions, 1 deletions
diff --git a/libevmasm/ExpressionClasses.cpp b/libevmasm/ExpressionClasses.cpp
index e32b2da2..d5ccd7e3 100644
--- a/libevmasm/ExpressionClasses.cpp
+++ b/libevmasm/ExpressionClasses.cpp
@@ -245,22 +245,25 @@ Rules::Rules()
// invariants involving known constants
{{Instruction::ADD, {X, 0}}, [=]{ return X; }},
+ {{Instruction::SUB, {X, 0}}, [=]{ return X; }},
{{Instruction::MUL, {X, 1}}, [=]{ return X; }},
{{Instruction::DIV, {X, 1}}, [=]{ return X; }},
{{Instruction::SDIV, {X, 1}}, [=]{ return X; }},
{{Instruction::OR, {X, 0}}, [=]{ return X; }},
{{Instruction::XOR, {X, 0}}, [=]{ return X; }},
{{Instruction::AND, {X, ~u256(0)}}, [=]{ return X; }},
+ {{Instruction::AND, {X, 0}}, [=]{ return u256(0); }},
{{Instruction::MUL, {X, 0}}, [=]{ return u256(0); }},
{{Instruction::DIV, {X, 0}}, [=]{ return u256(0); }},
+ {{Instruction::DIV, {0, X}}, [=]{ return u256(0); }},
{{Instruction::MOD, {X, 0}}, [=]{ return u256(0); }},
{{Instruction::MOD, {0, X}}, [=]{ return u256(0); }},
- {{Instruction::AND, {X, 0}}, [=]{ return u256(0); }},
{{Instruction::OR, {X, ~u256(0)}}, [=]{ return ~u256(0); }},
{{Instruction::EQ, {X, 0}}, [=]() -> Pattern { return {Instruction::ISZERO, {X}}; } },
// operations involving an expression and itself
{{Instruction::AND, {X, X}}, [=]{ return X; }},
{{Instruction::OR, {X, X}}, [=]{ return X; }},
+ {{Instruction::XOR, {X, X}}, [=]{ return u256(0); }},
{{Instruction::SUB, {X, X}}, [=]{ return u256(0); }},
{{Instruction::EQ, {X, X}}, [=]{ return u256(1); }},
{{Instruction::LT, {X, X}}, [=]{ return u256(0); }},
@@ -270,6 +273,11 @@ Rules::Rules()
{{Instruction::MOD, {X, X}}, [=]{ return u256(0); }},
{{Instruction::NOT, {{Instruction::NOT, {X}}}}, [=]{ return X; }},
+ {{Instruction::XOR, {{{X}, {Instruction::XOR, {X, Y}}}}}, [=]{ return Y; }},
+ {{Instruction::OR, {{{X}, {Instruction::AND, {X, Y}}}}}, [=]{ return X; }},
+ {{Instruction::AND, {{{X}, {Instruction::OR, {X, Y}}}}}, [=]{ return X; }},
+ {{Instruction::AND, {{{X}, {Instruction::NOT, {X}}}}}, [=]{ return u256(0); }},
+ {{Instruction::OR, {{{X}, {Instruction::NOT, {X}}}}}, [=]{ return ~u256(0); }},
};
// Double negation of opcodes with binary result
for (auto const& op: vector<Instruction>{
@@ -287,6 +295,10 @@ Rules::Rules()
{Instruction::ISZERO, {{Instruction::ISZERO, {{Instruction::ISZERO, {X}}}}}},
[=]() -> Pattern { return {Instruction::ISZERO, {X}}; }
});
+ m_rules.push_back({
+ {Instruction::ISZERO, {{Instruction::XOR, {X, Y}}}},
+ [=]() -> Pattern { return { Instruction::EQ, {X, Y} }; }
+ });
// Associative operations
for (auto const& opFun: vector<pair<Instruction,function<u256(u256 const&,u256 const&)>>>{
{Instruction::ADD, plus<u256>()},
diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp
index a53a2638..89c89adc 100644
--- a/test/libsolidity/SolidityOptimizer.cpp
+++ b/test/libsolidity/SolidityOptimizer.cpp
@@ -1304,6 +1304,29 @@ BOOST_AUTO_TEST_CASE(invalid_state_at_control_flow_join)
compareVersions("test()");
}
+BOOST_AUTO_TEST_CASE(cse_sub_zero)
+{
+ checkCSE({
+ u256(0),
+ Instruction::DUP2,
+ Instruction::SUB
+ }, {
+ Instruction::DUP1
+ });
+
+ checkCSE({
+ Instruction::DUP1,
+ u256(0),
+ Instruction::SUB
+ }, {
+ u256(0),
+ Instruction::DUP2,
+ Instruction::SWAP1,
+ Instruction::SUB
+ });
+}
+
+
BOOST_AUTO_TEST_SUITE_END()
}