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):
#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)
{
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];