Optimize obsolete ANDs in combination with certain SHIFTs

This commit is contained in:
Mathias Baumann 2019-03-13 12:23:01 +01:00
parent 84fbf605aa
commit 5c66ccc179
3 changed files with 103 additions and 0 deletions

View File

@ -6,6 +6,7 @@ Language Features:
Compiler Features:
* 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.

View File

@ -391,6 +391,30 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleListPart7(
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;
}

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)
{
vector<Instruction> ops{