Merge pull request #6160 from ethereum/rulelist-reject

Optimize obsolete ANDs in combination with certain SHIFTs
This commit is contained in:
chriseth 2019-03-29 18:01:33 +01:00 committed by GitHub
commit 91a54f9b4d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 163 additions and 1 deletions

View File

@ -5,6 +5,8 @@ Language Features:
Compiler Features: Compiler Features:
* SMTChecker: Support arithmetic compound assignment operators. * SMTChecker: Support arithmetic compound assignment operators.
* Optimizer: Add rule for shifts by constants larger than 255 for Constantinople.
* Optimizer: Add rule to simplify certain ANDs and SHL combinations
* Yul: Adds break and continue keywords to for-loop syntax. * Yul: Adds break and continue keywords to for-loop syntax.

View File

@ -216,7 +216,7 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleListPart4(
template <class Pattern> template <class Pattern>
std::vector<SimplificationRule<Pattern>> simplificationRuleListPart5( std::vector<SimplificationRule<Pattern>> simplificationRuleListPart5(
Pattern, Pattern A,
Pattern, Pattern,
Pattern, Pattern,
Pattern X, Pattern X,
@ -236,6 +236,22 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleListPart5(
}); });
} }
// Replace SHL >=256, X with 0
rules.push_back({
{Instruction::SHL, {A, X}},
[=]() -> Pattern { return u256(0); },
true,
[=]() { return A.d() >= 256; }
});
// Replace SHR >=256, X with 0
rules.push_back({
{Instruction::SHR, {A, X}},
[=]() -> Pattern { return u256(0); },
true,
[=]() { return A.d() >= 256; }
});
for (auto const& op: std::vector<Instruction>{ for (auto const& op: std::vector<Instruction>{
Instruction::ADDRESS, Instruction::ADDRESS,
Instruction::CALLER, Instruction::CALLER,
@ -375,6 +391,30 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleListPart7(
false false
}); });
std::function<bool()> feasibilityFunction = [=]() {
if (B.d() > 256)
return false;
unsigned bAsUint = static_cast<unsigned>(B.d());
return (A.d() & (u256(-1) >> bAsUint)) == (u256(-1) >> bAsUint);
};
rules.push_back({
// AND(A, SHR(B, X)) -> A & ((2^256-1) >> B) == ((2^256-1) >> B)
{Instruction::AND, {A, {Instruction::SHR, {B, X}}}},
[=]() -> Pattern { return {Instruction::SHR, {B, X}}; },
false,
feasibilityFunction
});
rules.push_back({
// AND(SHR(B, X), A) -> ((2^256-1) >> B) & A == ((2^256-1) >> B)
{Instruction::AND, {{Instruction::SHR, {B, X}}, A}},
[=]() -> Pattern { return {Instruction::SHR, {B, X}}; },
false,
feasibilityFunction
});
return rules; return rules;
} }

View File

@ -1180,6 +1180,84 @@ BOOST_AUTO_TEST_CASE(cse_sub_zero)
}); });
} }
BOOST_AUTO_TEST_CASE(cse_remove_redundant_shift_masking)
{
if (!dev::test::Options::get().evmVersion().hasBitwiseShifting())
return;
for (int i = 1; i < 256; i++)
{
checkCSE({
u256(boost::multiprecision::pow(u256(2), i)-1),
Instruction::CALLVALUE,
u256(256-i),
Instruction::SHR,
Instruction::AND
}, {
Instruction::CALLVALUE,
u256(256-i),
Instruction::SHR,
});
checkCSE({
Instruction::CALLVALUE,
u256(256-i),
Instruction::SHR,
u256(boost::multiprecision::pow(u256(2), i)-1),
Instruction::AND
}, {
Instruction::CALLVALUE,
u256(256-i),
Instruction::SHR,
});
}
// Check that opt. does NOT trigger
for (int i = 1; i < 255; i++)
{
checkCSE({
u256(boost::multiprecision::pow(u256(2), i)-1),
Instruction::CALLVALUE,
u256(255-i),
Instruction::SHR,
Instruction::AND
}, { // Opt. did some reordering
Instruction::CALLVALUE,
u256(255-i),
Instruction::SHR,
u256(boost::multiprecision::pow(u256(2), i)-1),
Instruction::AND
});
checkCSE({
Instruction::CALLVALUE,
u256(255-i),
Instruction::SHR,
u256(boost::multiprecision::pow(u256(2), i)-1),
Instruction::AND
}, { // Opt. did some reordering
u256(boost::multiprecision::pow(u256(2), i)-1),
Instruction::CALLVALUE,
u256(255-i),
Instruction::SHR,
Instruction::AND
});
}
//(x >> (31*8)) & 0xffffffff
checkCSE({
Instruction::CALLVALUE,
u256(31*8),
Instruction::SHR,
u256(0xffffffff),
Instruction::AND
}, {
Instruction::CALLVALUE,
u256(31*8),
Instruction::SHR
});
}
BOOST_AUTO_TEST_CASE(cse_remove_unwanted_masking_of_address) BOOST_AUTO_TEST_CASE(cse_remove_unwanted_masking_of_address)
{ {
vector<Instruction> ops{ vector<Instruction> ops{
@ -1250,6 +1328,48 @@ BOOST_AUTO_TEST_CASE(cse_remove_unwanted_masking_of_address)
}); });
} }
BOOST_AUTO_TEST_CASE(cse_replace_too_large_shift)
{
if (!dev::test::Options::get().evmVersion().hasBitwiseShifting())
return;
checkCSE({
Instruction::CALLVALUE,
u256(299),
Instruction::SHL
}, {
u256(0)
});
checkCSE({
Instruction::CALLVALUE,
u256(299),
Instruction::SHR
}, {
u256(0)
});
checkCSE({
Instruction::CALLVALUE,
u256(255),
Instruction::SHL
}, {
Instruction::CALLVALUE,
u256(255),
Instruction::SHL
});
checkCSE({
Instruction::CALLVALUE,
u256(255),
Instruction::SHR
}, {
Instruction::CALLVALUE,
u256(255),
Instruction::SHR
});
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
} }