Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 libyul/backends/evm/ssa/Stack.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ class Stack
bool dupReachable(Depth const& _depth) const noexcept { return _depth < size() && _depth.value + 1 <= reachableStackDepth; }
bool isValidSwapTarget(Offset const& _offset) const noexcept { return isValidSwapTarget(offsetToDepth(_offset)); }
bool isValidSwapTarget(Depth const& _depth) const noexcept { return _depth < size() && 1 <= _depth.value && _depth.value <= reachableStackDepth; }
bool isBeyondSwapRange(Offset const& _offset) const noexcept { return isBeyondSwapRange(offsetToDepth(_offset)); }
bool isBeyondSwapRange(Depth const& _depth) const noexcept { return _depth > reachableStackDepth; }

void declareJunk(Offset const& _offset) { (*m_data)[_offset.value] = Slot::makeJunk(); }
Expand Down
3 changes: 2 additions & 1 deletion libyul/backends/evm/ssa/StackShuffler.h
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,8 @@ class StackShuffler
// swap up any slot in args that is out of position and has a slot available in args that it can occupy
for (StackOffset offset: _state.stackArgsRange())
{
bool const reachable = _stack.isValidSwapTarget(offset);
// when offset is already top no swap-up is needed, so it doesn't have to be a valid swap target itself
bool const reachable = !_stack.isBeyondSwapRange(offset);
bool const identical = _state.isArgsCompatible(offset, stackTop) && !_state.targetArbitrary(stackTop);
if (
reachable &&
Expand Down
34 changes: 3 additions & 31 deletions test/libyul/ssa/stackShuffler/loop-fuzzer.stack
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,8 @@ targetStackSize: 7
// | 0 1 | 2 3 4 5 6
// +-------------- +-----------------------------------
// (initial)| v0 phi0 | phi0 lit0 v0 v0
// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0
// POP| v0 phi0 | phi0 lit0 v0 v0
// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0
// POP| v0 phi0 | phi0 lit0 v0 v0
// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0
// POP| v0 phi0 | phi0 lit0 v0 v0
// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0
// POP| v0 phi0 | phi0 lit0 v0 v0
// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0
// POP| v0 phi0 | phi0 lit0 v0 v0
// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0
// POP| v0 phi0 | phi0 lit0 v0 v0
// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0
// POP| v0 phi0 | phi0 lit0 v0 v0
// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0
// POP| v0 phi0 | phi0 lit0 v0 v0
// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0
// POP| v0 phi0 | phi0 lit0 v0 v0
// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0
// POP| v0 phi0 | phi0 lit0 v0 v0
// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0
// POP| v0 phi0 | phi0 lit0 v0 v0
// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0
// POP| v0 phi0 | phi0 lit0 v0 v0
// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0
// POP| v0 phi0 | phi0 lit0 v0 v0
// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0
// POP| v0 phi0 | phi0 lit0 v0 v0
// DUP4| v0 phi0 | phi0 lit0 v0 v0 phi0
// ...|
// SWAP2| v0 phi0 | phi0 v0 v0 lit0
// DUP4| v0 phi0 | phi0 v0 v0 lit0 phi0
// +-------------- +-----------------------------------
// (target)| {v0} | phi0 v0 v0 * phi0
// Status: MaxIterationsReached
// Status: Admissible