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
10 changes: 8 additions & 2 deletions libyul/backends/evm/ssa/StackShuffler.h
Original file line number Diff line number Diff line change
Expand Up @@ -807,12 +807,18 @@ class StackShuffler
{
if (_state.isArgsCompatible(offset, offset))
continue;

auto const& targetArg = _state.targetArg(offset);
// if the target arg is junk, we can simply push0 and it's fine
if (targetArg.isJunk())
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this condition should in the future, i think, be extended to "is it junk or a lit that is cheap to push or we don't care about bytecode size and simply want fast execution"

continue;

// find first occurrence of the slot
std::optional<StackDepth> depth = _stack.findSlotDepth(_state.targetArg(offset));
std::optional<StackDepth> const depth = _stack.findSlotDepth(targetArg);
if (!depth)
{
// if there is no occurrence of the slot anywhere, we must be able to freely generate it
yulAssert(_stack.canBeFreelyGenerated(_state.targetArg(offset)));
yulAssert(_stack.canBeFreelyGenerated(targetArg));
}
else
{
Expand Down
12 changes: 12 additions & 0 deletions test/libyul/ssa/stackShuffler/stack_top_is_junk.stack
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
initial: [JUNK, JUNK, v0, v0, lit0, v0, lit0, v0, v0, v0, lit0, v0, v0, v0, lit0, v0, lit0, lit0, v0]
targetStackTop: [JUNK, lit0, v0, lit0, v0, JUNK, v0, lit0, JUNK, v0, v0, lit0, v0, JUNK, lit0, v0, JUNK]
targetStackTailSet: {v0}
targetStackSize: 20
// ----
// | 0 1 2 | 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// +--------------------- +-----------------------------------------------------------------------------------------------------------------------
// (initial)| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0
// PUSH JUNK| * * v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 *
// +--------------------- +-----------------------------------------------------------------------------------------------------------------------
// (target)| {v0} | * lit0 v0 lit0 v0 * v0 lit0 * v0 v0 lit0 v0 * lit0 v0 *
// Status: Admissible
18 changes: 18 additions & 0 deletions test/libyul/ssa/stackShuffler/stack_top_is_lit.stack
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
initial: [lit1, lit1, v0, v0, lit0, v0, lit0, v0, v0, v0, lit0, v0, v0, v0, lit0, v0, lit0, lit0, v0]
targetStackTop: [JUNK, lit0, v0, lit0, v0, JUNK, v0, lit0, JUNK, v0, v0, lit0, v0, JUNK, lit0, v0, lit1]
targetStackTailSet: {v0}
targetStackSize: 20
Comment on lines +1 to +4
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a bit confused.
Why is it trying to reach for lit1 instead of just doing PUSH lit1?
This should be just one instruction, similar to the JUNK case.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, now I understand your comment.
PUSH lit1 is potentially expensive, if lit1 is large.
As you say, at some point it would be good to come up with some heuristic to re-create the literal instead of trying to dup/swap existing one.

// ----
// | 0 1 2 | 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// +--------------------- +-----------------------------------------------------------------------------------------------------------------------
// (initial)| lit1 lit1 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0
// SWAP1| lit1 lit1 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0
// POP| lit1 lit1 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0
// SWAP16| lit1 v0 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit1
// DUP2| lit1 v0 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit1 lit0
// SWAP1| lit1 v0 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 lit1
// DUP4| lit1 v0 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 lit1 v0
// SWAP1| lit1 v0 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 lit1
// +--------------------- +-----------------------------------------------------------------------------------------------------------------------
// (target)| {v0} | * lit0 v0 lit0 v0 * v0 lit0 * v0 v0 lit0 v0 * lit0 v0 lit1
// Status: Admissible
18 changes: 18 additions & 0 deletions test/libyul/ssa/stackShuffler/stack_top_is_var.stack
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
initial: [v1, v1, v0, v0, lit0, v0, lit0, v0, v0, v0, lit0, v0, v0, v0, lit0, v0, lit0, lit0, v0]
targetStackTop: [JUNK, lit0, v0, lit0, v0, JUNK, v0, lit0, JUNK, v0, v0, lit0, v0, JUNK, lit0, v0, v1]
targetStackTailSet: {v0}
targetStackSize: 20
// ----
// | 0 1 2 | 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// +--------------------- +-----------------------------------------------------------------------------------------------------------------------
// (initial)| v1 v1 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0
// SWAP1| v1 v1 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0 lit0
// POP| v1 v1 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v0
// SWAP16| v1 v0 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v1
// DUP2| v1 v0 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 v1 lit0
// SWAP1| v1 v0 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v1
// DUP4| v1 v0 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v1 v0
// SWAP1| v1 v0 v0 | v0 lit0 v0 lit0 v0 v0 v0 lit0 v0 v0 v0 lit0 v0 lit0 lit0 v0 v1
// +--------------------- +-----------------------------------------------------------------------------------------------------------------------
// (target)| {v0} | * lit0 v0 lit0 v0 * v0 lit0 * v0 v0 lit0 v0 * lit0 v0 v1
// Status: Admissible