X Tutup
The Wayback Machine - https://web.archive.org/web/20220203172852/https://github.com/python/cpython/pull/30902
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-46528: Simplify the VM's stack manipulations #30902

Merged
merged 10 commits into from Jan 26, 2022
Merged

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

Python/compile.c Outdated Show resolved Hide resolved
Python/compile.c Show resolved Hide resolved
@sweeneyde
Copy link
Member

@sweeneyde sweeneyde commented Jan 26, 2022

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
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
X Tutup