Skip to content

Commit

Permalink
[3.11] gh-104615: don't make unsafe swaps in apply_static_swaps (GH-1…
Browse files Browse the repository at this point in the history
…04620). (#104636)

(cherry picked from commit 0589c6a)
  • Loading branch information
carljm authored May 19, 2023
1 parent d78c3bc commit 667e4ec
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 0 deletions.
18 changes: 18 additions & 0 deletions Lib/test/test_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -1064,6 +1064,24 @@ def test_compare_positions(self):
with self.subTest(source):
self.assertEqual(actual_positions, expected_positions)

def test_apply_static_swaps(self):
def f(x, y):
a, a = x, y
return a
self.assertEqual(f("x", "y"), "y")

def test_apply_static_swaps_2(self):
def f(x, y, z):
a, b, a = x, y, z
return a
self.assertEqual(f("x", "y", "z"), "z")

def test_apply_static_swaps_3(self):
def f(x, y, z):
a, a, b = x, y, z
return a
self.assertEqual(f("x", "y", "z"), "y")


@requires_debug_ranges()
class TestSourcePositions(unittest.TestCase):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix wrong ordering of assignments in code like ``a, a = x, y``. Contributed by
Carl Meyer.
20 changes: 20 additions & 0 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -8690,6 +8690,9 @@ swaptimize(basicblock *block, int *ix)
#define SWAPPABLE(opcode) \
((opcode) == STORE_FAST || (opcode) == POP_TOP)

#define STORES_TO(instr) \
(((instr).i_opcode == STORE_FAST) ? (instr).i_oparg : -1)

static int
next_swappable_instruction(basicblock *block, int i, int lineno)
{
Expand Down Expand Up @@ -8741,6 +8744,23 @@ apply_static_swaps(basicblock *block, int i)
return;
}
}
// The reordering is not safe if the two instructions to be swapped
// store to the same location, or if any intervening instruction stores
// to the same location as either of them.
int store_j = STORES_TO(block->b_instr[j]);
int store_k = STORES_TO(block->b_instr[k]);
if (store_j >= 0 || store_k >= 0) {
if (store_j == store_k) {
return;
}
for (int idx = j + 1; idx < k; idx++) {
int store_idx = STORES_TO(block->b_instr[idx]);
if (store_idx >= 0 && (store_idx == store_j || store_idx == store_k)) {
return;
}
}
}

// Success!
swap->i_opcode = NOP;
struct instr temp = block->b_instr[j];
Expand Down

0 comments on commit 667e4ec

Please sign in to comment.