PeepholeOptimizer: StaticIfComparisons

This commit is contained in:
Reuben Rodrigues 2022-09-08 15:28:57 +02:00
parent 727591b984
commit 8047171a13
2 changed files with 151 additions and 1 deletions

View File

@ -428,6 +428,92 @@ struct TruthyAnd: SimplePeepholeOptimizerMethod<TruthyAnd>
}
};
// if(a == true) -> if (a)
struct TruthyEqualComparison: SimplePeepholeOptimizerMethod<TruthyEqualComparison>{
static bool applySimple(
AssemblyItem const& _iszero,
AssemblyItem const& _iszero1,
AssemblyItem const& _push1,
AssemblyItem const& _eq,
std::back_insert_iterator<AssemblyItems>
)
{
if (
_iszero == Instruction::ISZERO &&
_iszero1 == Instruction::ISZERO &&
_push1.type() == Push && _push1.data() == 1 &&
_eq == Instruction::EQ
)
{
return true;
} else
return false;
}
};
// if(a != true) -> if(!a)
struct TruthyInequalComparison: SimplePeepholeOptimizerMethod<TruthyInequalComparison>{
static bool applySimple(
AssemblyItem const& _iszero,
AssemblyItem const& _iszero1,
AssemblyItem const& _push1,
AssemblyItem const& _sub,
AssemblyItem const& _pushTag,
AssemblyItem const& _jumpi,
std::back_insert_iterator<AssemblyItems> _out
)
{
if (
_iszero == Instruction::ISZERO &&
_iszero1 == Instruction::ISZERO &&
_push1.type() == Push && _push1.data() == 1 &&
_sub == Instruction::SUB &&
_pushTag.type() == PushTag &&
_jumpi == Instruction::JUMPI
)
{
*_out = _iszero;
*_out = _pushTag;
*_out = _jumpi;
return true;
} else
return false;
}
};
// if(true != a) -> if(!a)
struct ReverseTruthyInequalComparison: SimplePeepholeOptimizerMethod<ReverseTruthyInequalComparison>{
static bool applySimple(
AssemblyItem const& _push1,
AssemblyItem const& _swap1,
AssemblyItem const& _iszero,
AssemblyItem const& _iszero1,
AssemblyItem const& _sub,
AssemblyItem const& _pushTag,
AssemblyItem const& _jumpi,
std::back_insert_iterator<AssemblyItems> _out
)
{
if (
_push1.type() == Push && _push1.data() == 1 &&
SemanticInformation::isSwapInstruction(_swap1) &&
getSwapNumber(_swap1.instruction()) == 1 &&
_iszero == Instruction::ISZERO &&
_iszero1 == Instruction::ISZERO &&
_sub == Instruction::SUB &&
_pushTag.type() == PushTag &&
_jumpi == Instruction::JUMPI
)
{
*_out = _iszero;
*_out = _pushTag;
*_out = _jumpi;
return true;
} else
return false;
}
};
/// Removes everything after a JUMP (or similar) until the next JUMPDEST.
struct UnreachableCode
{
@ -488,7 +574,7 @@ bool PeepholeOptimiser::optimise()
while (state.i < m_items.size())
applyMethods(
state,
PushPop(), OpPop(), OpStop(), OpReturnRevert(), DoublePush(), DoubleSwap(), CommutativeSwap(), SwapComparison(),
TruthyEqualComparison(), TruthyInequalComparison(), ReverseTruthyInequalComparison(), PushPop(), OpPop(), OpStop(), OpReturnRevert(), DoublePush(), DoubleSwap(), CommutativeSwap(), SwapComparison(),
DupSwap(), IsZeroIsZeroJumpI(), EqIsZeroJumpI(), DoubleJump(), JumpToNext(), UnreachableCode(),
TagConjunctions(), TruthyAnd(), Identity()
);

View File

@ -975,6 +975,70 @@ BOOST_AUTO_TEST_CASE(block_deduplicator_loops)
BOOST_CHECK_EQUAL(pushTags.size(), 1);
}
BOOST_AUTO_TEST_CASE(peephole_truthy_equal_comparison)
{
AssemblyItems items{
Instruction::ISZERO,
Instruction::ISZERO,
AssemblyItem(Push, 1),
Instruction::EQ,
};
AssemblyItems expectation{};
PeepholeOptimiser peepOpt(items);
BOOST_REQUIRE(peepOpt.optimise());
BOOST_CHECK_EQUAL_COLLECTIONS(
items.begin(), items.end(),
expectation.begin(), expectation.end()
);
}
BOOST_AUTO_TEST_CASE(peephole_truthy_inequal_comparison)
{
AssemblyItems items{
Instruction::ISZERO,
Instruction::ISZERO,
AssemblyItem(Push, 1),
Instruction::SUB,
AssemblyItem(PushTag, 1),
Instruction::JUMPI
};
AssemblyItems expectation{
Instruction::ISZERO,
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(peephole_reverse_truthy_inequal_comparison)
{
AssemblyItems items{
AssemblyItem(Push, 1),
Instruction::SWAP1,
Instruction::ISZERO,
Instruction::ISZERO,
Instruction::SUB,
AssemblyItem(PushTag, 1),
Instruction::JUMPI
};
AssemblyItems expectation{
Instruction::ISZERO,
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(clear_unreachable_code)
{
AssemblyItems items{