@@ -65,7 +65,6 @@ inline std::string stackToString(Stack const& _stack, Dialect const& _dialect)
6565// in the interface below.
6666// Based on that information the shuffler decides which is the next optimal operation to perform on the stack
6767// and calls the corresponding entry point in the shuffling operations (swap, pushOrDupTarget or pop).
68- /*
6968template <typename ShuffleOperations>
7069concept ShuffleOperationConcept = requires (ShuffleOperations ops, size_t sourceOffset, size_t targetOffset, size_t depth) {
7170 // Returns true, iff the current slot at sourceOffset in source layout is a suitable slot at targetOffset.
@@ -98,11 +97,13 @@ concept ShuffleOperationConcept = requires(ShuffleOperations ops, size_t sourceO
9897 { ops.pop () };
9998 // Dups or pushes the slot that is supposed to end up at the given target offset.
10099 { ops.pushOrDupTarget (targetOffset) };
100+ // Maximum reachable depth with swaps and dups.
101+ { ops.reachableStackDepth } -> std::convertible_to<size_t >;
101102};
102- */
103+
103104// / Helper class that can perform shuffling of a source stack layout to a target stack layout via
104105// / abstracted shuffle operations.
105- template </* ShuffleOperationConcept*/ typename ShuffleOperations>
106+ template <ShuffleOperationConcept ShuffleOperations>
106107class Shuffler
107108{
108109public:
@@ -128,10 +129,10 @@ class Shuffler
128129 static bool dupDeepSlotIfRequired (ShuffleOperations& _ops)
129130 {
130131 // Check if the stack is large enough for anything to potentially become unreachable.
131- if (_ops.sourceSize () < 15 )
132+ if (_ops.sourceSize () < (_ops. reachableStackDepth - 1 ) )
132133 return false ;
133134 // Check whether any deep slot might still be needed later (i.e. we still need to reach it with a DUP or SWAP).
134- for (size_t sourceOffset: ranges::views::iota (0u , _ops.sourceSize () - 15 ))
135+ for (size_t sourceOffset: ranges::views::iota (0u , _ops.sourceSize () - (_ops. reachableStackDepth - 1 ) ))
135136 {
136137 // This slot needs to be moved.
137138 if (!_ops.isCompatible (sourceOffset, sourceOffset))
@@ -256,10 +257,10 @@ class Shuffler
256257 )
257258 {
258259 // We cannot swap that deep.
259- if (ops.sourceSize () - offset - 1 > 16 )
260+ if (ops.sourceSize () - offset - 1 > ops. reachableStackDepth )
260261 {
261262 // If there is a reachable slot to be removed, park the current top there.
262- for (size_t swapDepth: ranges::views::iota (1u , 17u ) | ranges::views::reverse)
263+ for (size_t swapDepth: ranges::views::iota (1u , ops. reachableStackDepth + 1u ) | ranges::views::reverse)
263264 if (ops.sourceMultiplicity (ops.sourceSize () - 1 - swapDepth) < 0 )
264265 {
265266 ops.swap (swapDepth);
@@ -431,7 +432,14 @@ class Multiplicity
431432// / its argument to the stack top.
432433// / @a _pop is a function with signature void() that is called when the top most slot is popped.
433434template <typename Swap, typename PushOrDup, typename Pop>
434- void createStackLayout (Stack& _currentStack, Stack const & _targetStack, Swap _swap, PushOrDup _pushOrDup, Pop _pop)
435+ void createStackLayout (
436+ Stack& _currentStack,
437+ Stack const & _targetStack,
438+ Swap _swap,
439+ PushOrDup _pushOrDup,
440+ Pop _pop,
441+ size_t _reachableStackDepth
442+ )
435443{
436444 struct ShuffleOperations
437445 {
@@ -441,18 +449,21 @@ void createStackLayout(Stack& _currentStack, Stack const& _targetStack, Swap _sw
441449 PushOrDup pushOrDupCallback;
442450 Pop popCallback;
443451 Multiplicity multiplicity;
452+ size_t reachableStackDepth;
444453 ShuffleOperations (
445454 Stack& _currentStack,
446455 Stack const & _targetStack,
447456 Swap _swap,
448457 PushOrDup _pushOrDup,
449- Pop _pop
458+ Pop _pop,
459+ size_t _reachableStackDepth
450460 ):
451461 currentStack (_currentStack),
452462 targetStack (_targetStack),
453463 swapCallback (_swap),
454464 pushOrDupCallback (_pushOrDup),
455- popCallback (_pop)
465+ popCallback (_pop),
466+ reachableStackDepth (_reachableStackDepth)
456467 {
457468 for (auto const & slot: currentStack)
458469 --multiplicity[slot];
@@ -499,7 +510,7 @@ void createStackLayout(Stack& _currentStack, Stack const& _targetStack, Swap _sw
499510 }
500511 };
501512
502- Shuffler<ShuffleOperations>::shuffle (_currentStack, _targetStack, _swap, _pushOrDup, _pop);
513+ Shuffler<ShuffleOperations>::shuffle (_currentStack, _targetStack, _swap, _pushOrDup, _pop, _reachableStackDepth );
503514
504515 yulAssert (_currentStack.size () == _targetStack.size (), " " );
505516 for (auto && [current, target]: ranges::zip_view (_currentStack, _targetStack))
0 commit comments