Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
74f4f94
Fixed applySimple return type
philippela Nov 28, 2025
855b140
Added CalldataSizeCheckSimplify pattern
philippela Nov 28, 2025
e6fde40
Added power of two multiplication to shl peephole pattern
philippela Nov 28, 2025
8751dfb
Added FunctionSelectorGuard pattern
philippela Nov 28, 2025
37e3dd9
Added ErrorDispatcherStandardPanic pattern
philippela Nov 28, 2025
fa04ac8
Revert "Added power of two multiplication to shl peephole pattern"
philippela Nov 28, 2025
4620f46
semantic tests have revealed CalldataSizeCheckSimplify to be unsound
philippela Dec 1, 2025
6c136b9
turns out ErrorDispatcherStandardPanic is a bad trade-off
philippela Dec 1, 2025
b34de94
FunctionSelectorGuard now passes all tests, both unit and semantic
philippela Dec 1, 2025
9aaec94
updated changelog
philippela Dec 1, 2025
9f362af
Merge branch 'develop' into philippecyberian/peepholes
philippecyberian Dec 1, 2025
2967b50
coding style fix: remove trailing whitespace
philippela Dec 1, 2025
58cd5eb
Merge remote-tracking branch 'personal/philippecyberian/peepholes' in…
philippela Dec 1, 2025
5a6e78c
reformatted with clang-format -i lib/optimiser/PeepholeOptimiser.cpp
philippela Dec 1, 2025
4f7edaf
Trigger CI rerun
philippela Dec 3, 2025
1679161
manual merge
philippela Dec 3, 2025
e9b34b2
Merge branch 'develop' into philippecyberian/peepholes
philippecyberian Dec 3, 2025
f02361b
Trigger CI rerun
philippela Dec 3, 2025
f76161b
Merge branch 'develop' into philippecyberian/peepholes
philippecyberian Dec 3, 2025
8e5fc2b
Merge branch 'develop' into philippecyberian/peepholes
philippecyberian Dec 3, 2025
6ada012
Merge branch 'develop' into philippecyberian/peepholes
philippecyberian Dec 3, 2025
995fcdd
Merge branch 'develop' into philippecyberian/peepholes
philippecyberian Dec 4, 2025
7e8f41a
Merge branch 'develop' into philippecyberian/peepholes
philippecyberian Dec 4, 2025
23a15df
Merge branch 'develop' into philippecyberian/peepholes
philippecyberian Dec 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Language Features:
* Type Checker: Warn about deprecation of `send` and `transfer` functions on instances of `address`.
* Type Checker: Warn about deprecation of comparisons between variables of contract types.
* Yul: Introduce builtin `clz(x)` for counting the number of leading zero bits in a 256-bit word.
* peepholeoptimiser: Peephole pattern FunctionSelectorGuard added.


Compiler Features:
Expand Down
49 changes: 48 additions & 1 deletion libevmasm/PeepholeOptimiser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ struct JumpToNext: SimplePeepholeOptimizerMethod<JumpToNext>

struct RJumpToNext: SimplePeepholeOptimizerMethod<RJumpToNext>
{
static size_t applySimple(
static bool applySimple(
AssemblyItem const& _rjump,
AssemblyItem const& _tag,
std::back_insert_iterator<AssemblyItems> _out
Expand Down Expand Up @@ -696,6 +696,52 @@ struct DeduplicateNextTagSize1 : SimplePeepholeOptimizerMethod<DeduplicateNextTa
}
};

struct FunctionSelectorGuard: SimplePeepholeOptimizerMethod<FunctionSelectorGuard>
{
static bool apply(OptimiserState& _state)
{
size_t window = 6;
if (_state.i + window > _state.items.size())
return false;

if (_state.i == 0)
return false;
if (_state.items[_state.i - 1].type() != Tag)
return false;

auto& a = _state.items[_state.i + 0];
auto& b = _state.items[_state.i + 1];
auto& c = _state.items[_state.i + 2];
auto& d = _state.items[_state.i + 3];
auto& e = _state.items[_state.i + 4];
auto& f = _state.items[_state.i + 5];

if (a.type() != Push || a.data() != u256(4))
return false;

if (!(b == Instruction::CALLDATASIZE))
return false;
if (!(c == Instruction::LT))
return false;
if (!(d == Instruction::ISZERO))
return false;

if (e.type() != PushTag)
return false;
if (!(f == Instruction::JUMPI))
return false;

*_state.out = AssemblyItem(u256(3), a.debugData());
*_state.out = AssemblyItem(Instruction::CALLDATASIZE, b.debugData());
*_state.out = AssemblyItem(Instruction::GT, c.debugData());
*_state.out = e;
*_state.out = f;

_state.i += window;
return true;
}
};

template <typename... Method>
void applyMethods(OptimiserState& _state)
{
Expand Down Expand Up @@ -746,6 +792,7 @@ bool PeepholeOptimiser::optimise()
DeduplicateNextTagSize2,
DeduplicateNextTagSize1,
TagConjunctions,
FunctionSelectorGuard,
TruthyAnd,
Identity
>(state);
Expand Down
38 changes: 38 additions & 0 deletions test/libevmasm/Optimiser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1479,6 +1479,44 @@ BOOST_AUTO_TEST_CASE(peephole_iszero_iszero_jumpi)
);
}

BOOST_AUTO_TEST_CASE(peephole_function_selector_guard)
{
AssemblyItem tag0 = AssemblyItem(Tag, 0);
AssemblyItem tag1 = AssemblyItem(Tag, 1);
AssemblyItem pushTag1 = AssemblyItem(PushTag, 1);

AssemblyItems items{
tag0,
u256(4),
Instruction::CALLDATASIZE,
Instruction::LT,
Instruction::ISZERO,
pushTag1,
Instruction::JUMPI,
tag1,
Instruction::STOP
};

AssemblyItems expectation{
tag0,
u256(3),
Instruction::CALLDATASIZE,
Instruction::GT,
pushTag1,
Instruction::JUMPI,
tag1,
Instruction::STOP
};

PeepholeOptimiser peepOpt(items, solidity::test::CommonOptions::get().evmVersion());
BOOST_REQUIRE(peepOpt.optimise());

BOOST_CHECK_EQUAL_COLLECTIONS(
items.begin(), items.end(),
expectation.begin(), expectation.end()
);
}

BOOST_AUTO_TEST_CASE(jumpdest_removal)
{
AssemblyItems items{
Expand Down