Skip to content

Conversation

brandtbucher
Copy link
Member

@brandtbucher brandtbucher commented Jan 26, 2022

...as discussed in faster-cpython/ideas#228:

  • Replace DUP_TOP with COPY(1).
  • Replace DUP_TOP_TWO with COPY(2), COPY(2).
  • Introduce a new SWAP instruction.
    • Replace ROT_TWO with SWAP(2).
    • Replace ROT_THREE with SWAP(3), SWAP(2).
    • Remove ROT_FOUR.
    • Replace ROT_N(n) with SWAP(n), SWAP(n - 1), ..., SWAP(2).
    • Optimize runs of SWAP instructions.

https://bugs.python.org/issue46528

@sweeneyde
Copy link
Member

I threw together a test for the basic swaptimize algorithm and it passes some test cases, so that's nice:

def permutation(swaps, N=None):
    if N is None:
        N = max(swaps)
    perm = list(range(N))
    for s in swaps:
        perm[0], perm[s-1] = perm[s-1], perm[0]
    return perm


def swaptimize(*old_swaps):
    assert old_swaps
    if len(old_swaps) == 1:
        return tuple(old_swaps)

    perm = permutation(old_swaps)

    swaps = []
    for i, x in enumerate(perm):
        # March forward, searching for an un-traversed cycle.
        if x is None or x == i:
            continue
        # Traverse this cycle.
        j = i
        while True:
            if j != 0:
                swaps.append(j + 1)
            if perm[j] is None:
                # Back to the start of the cycle.
                assert j == i
                break
            next_j = perm[j]
            perm[j] = None
            j = next_j

    swaps = tuple(reversed(swaps))

    assert permutation(old_swaps, len(perm)) == permutation(swaps, len(perm))
    assert len(swaps) <= len(old_swaps)

    return swaps

assert swaptimize(1) == (1,) # This should be ()?
assert swaptimize(2) == (2,)
assert swaptimize(3) == (3,)
assert swaptimize(10) == (10,)

assert swaptimize(2, 2, 5, 5) == ()
assert swaptimize(10, 20, 20, 10) == ()
assert swaptimize(2, 3, 4, 3) == (3, 4, 3, 2)

from random import randint

for i in range(100_000):
    for n in range(1, 20):
        swaptimize(*[randint(2, 20) for _ in range(n)])

@brandtbucher brandtbucher merged commit 8548366 into python:main Jan 26, 2022
@brandtbucher brandtbucher deleted the swap branch July 21, 2022 20:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants