Skip to content

Commit 975ee13

Browse files
committed
eof: Enable peephole optimizer for EOF.
1 parent 6d62ea0 commit 975ee13

File tree

7 files changed

+65
-11
lines changed

7 files changed

+65
-11
lines changed

libevmasm/Assembly.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -843,8 +843,7 @@ std::map<u256, u256> const& Assembly::optimiseInternal(
843843
}
844844
}
845845

846-
// TODO: verify this for EOF.
847-
if (_settings.runPeephole && !m_eofVersion.has_value())
846+
if (_settings.runPeephole)
848847
{
849848
for (auto& codeSection: m_codeSections)
850849
{

libevmasm/AssemblyItem.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ class AssemblyItem
244244
/// Shortcut that avoids constructing an AssemblyItem just to perform the comparison.
245245
bool operator==(Instruction _instr) const
246246
{
247-
return type() == Operation && instruction() == _instr;
247+
return hasInstruction() && instruction() == _instr;
248248
}
249249
bool operator!=(Instruction _instr) const { return !operator==(_instr); }
250250

libevmasm/PeepholeOptimiser.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,9 @@ struct TruthyAnd: SimplePeepholeOptimizerMethod<TruthyAnd>
563563
}
564564
};
565565

566-
/// Removes everything after a JUMP (or similar) until the next JUMPDEST.
566+
/// Removes everything after an non-continuing instruction until the next Tag.
567+
/// Note: JUMPF can return but to the caller's parent call frame.
568+
/// So it won't continue from the next to the JUMPF instruction
567569
struct UnreachableCode
568570
{
569571
static bool apply(OptimiserState& _state)
@@ -572,14 +574,18 @@ struct UnreachableCode
572574
auto end = _state.items.end();
573575
if (it == end)
574576
return false;
577+
575578
if (
576579
it[0] != Instruction::JUMP &&
577-
it[0] != Instruction::RJUMP &&
578580
it[0] != Instruction::RETURN &&
579581
it[0] != Instruction::STOP &&
580582
it[0] != Instruction::INVALID &&
581583
it[0] != Instruction::SELFDESTRUCT &&
582-
it[0] != Instruction::REVERT
584+
it[0] != Instruction::REVERT &&
585+
it[0] != Instruction::RJUMP &&
586+
it[0] != Instruction::JUMPF &&
587+
it[0] != Instruction::RETF &&
588+
it[0] != Instruction::RETURNCONTRACT
583589
)
584590
return false;
585591

test/Common.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,13 @@ boost::unit_test::precondition::predicate_t nonEOF()
313313
};
314314
}
315315

316+
boost::unit_test::precondition::predicate_t onEOF()
317+
{
318+
return [](boost::unit_test::test_unit_id) {
319+
return solidity::test::CommonOptions::get().eofVersion().has_value();
320+
};
321+
}
322+
316323
boost::unit_test::precondition::predicate_t minEVMVersionCheck(langutil::EVMVersion _minEVMVersion)
317324
{
318325
return [_minEVMVersion](boost::unit_test::test_unit_id) {

test/Common.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ boost::unit_test::precondition::predicate_t minEVMVersionCheck(langutil::EVMVers
116116
/// @return A predicate (function) that can be passed into @a boost::unit_test::precondition().
117117
boost::unit_test::precondition::predicate_t nonEOF();
118118

119+
/// Helper that can be used to skip tests when the legacy bytecode is not supported by the test case.
120+
/// @return A predicate (function) that can be passed into @a boost::unit_test::precondition().
121+
boost::unit_test::precondition::predicate_t onEOF();
122+
119123
bool loadVMs(CommonOptions const& _options);
120124

121125
/**

test/libevmasm/Optimiser.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,6 +1009,46 @@ BOOST_AUTO_TEST_CASE(clear_unreachable_code)
10091009
);
10101010
}
10111011

1012+
BOOST_AUTO_TEST_CASE(clear_unreachable_code_eof, *boost::unit_test::precondition(onEOF()))
1013+
{
1014+
for (auto const& blockTerminatingItem:
1015+
{
1016+
AssemblyItem::relativeJumpTo(AssemblyItem(Tag, 1)),
1017+
AssemblyItem::jumpToFunction(1, 0, 0),
1018+
AssemblyItem::functionReturn(),
1019+
AssemblyItem::returnContract(0),
1020+
}
1021+
)
1022+
{
1023+
AssemblyItems items{
1024+
blockTerminatingItem,
1025+
u256(0),
1026+
Instruction::SLOAD,
1027+
AssemblyItem(Tag, 2),
1028+
u256(5),
1029+
u256(6),
1030+
Instruction::SSTORE,
1031+
blockTerminatingItem,
1032+
u256(5),
1033+
u256(6)
1034+
};
1035+
AssemblyItems expectation{
1036+
blockTerminatingItem,
1037+
AssemblyItem(Tag, 2),
1038+
u256(5),
1039+
u256(6),
1040+
Instruction::SSTORE,
1041+
blockTerminatingItem,
1042+
};
1043+
PeepholeOptimiser peepOpt(items, solidity::test::CommonOptions::get().evmVersion());
1044+
BOOST_REQUIRE(peepOpt.optimise());
1045+
BOOST_CHECK_EQUAL_COLLECTIONS(
1046+
items.begin(), items.end(),
1047+
expectation.begin(), expectation.end()
1048+
);
1049+
}
1050+
}
1051+
10121052
BOOST_AUTO_TEST_CASE(deduplicateNextTagBlockSize3)
10131053
{
10141054
AssemblyItems items{

test/libyul/objectCompiler/eof/256_subcontainers.yul

Lines changed: 3 additions & 5 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)