Skip to content

Commit

Permalink
Remove unnecessary LIST_TO_TUPLE conversions (GH-126558)
Browse files Browse the repository at this point in the history
  • Loading branch information
brandtbucher authored Jan 8, 2025
1 parent 845d924 commit 004f9fd
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 0 deletions.
51 changes: 51 additions & 0 deletions Lib/test/test_peepholer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1193,5 +1193,56 @@ def get_insts(lno1, lno2, op1, op2):
]
self.cfg_optimization_test(insts, expected_insts, consts=list(range(5)))

def test_list_to_tuple_get_iter(self):
# for _ in (*foo, *bar) -> for _ in [*foo, *bar]
INTRINSIC_LIST_TO_TUPLE = 6
insts = [
("BUILD_LIST", 0, 1),
("LOAD_FAST", 0, 2),
("LIST_EXTEND", 1, 3),
("LOAD_FAST", 1, 4),
("LIST_EXTEND", 1, 5),
("CALL_INTRINSIC_1", INTRINSIC_LIST_TO_TUPLE, 6),
("GET_ITER", None, 7),
top := self.Label(),
("FOR_ITER", end := self.Label(), 8),
("STORE_FAST", 2, 9),
("JUMP", top, 10),
end,
("END_FOR", None, 11),
("POP_TOP", None, 12),
("LOAD_CONST", 0, 13),
("RETURN_VALUE", None, 14),
]
expected_insts = [
("BUILD_LIST", 0, 1),
("LOAD_FAST", 0, 2),
("LIST_EXTEND", 1, 3),
("LOAD_FAST", 1, 4),
("LIST_EXTEND", 1, 5),
("NOP", None, 6), # ("CALL_INTRINSIC_1", INTRINSIC_LIST_TO_TUPLE, 6),
("GET_ITER", None, 7),
top := self.Label(),
("FOR_ITER", end := self.Label(), 8),
("STORE_FAST", 2, 9),
("JUMP", top, 10),
end,
("END_FOR", None, 11),
("POP_TOP", None, 12),
("LOAD_CONST", 0, 13),
("RETURN_VALUE", None, 14),
]
self.cfg_optimization_test(insts, expected_insts, consts=[None])

def test_list_to_tuple_get_iter_is_safe(self):
a, b = [], []
for item in (*(items := [0, 1, 2, 3]),):
a.append(item)
b.append(items.pop())
self.assertEqual(a, [0, 1, 2, 3])
self.assertEqual(b, [3, 2, 1, 0])
self.assertEqual(items, [])


if __name__ == "__main__":
unittest.main()
7 changes: 7 additions & 0 deletions Python/flowgraph.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "Python.h"
#include "pycore_flowgraph.h"
#include "pycore_compile.h"
#include "pycore_intrinsics.h"
#include "pycore_pymem.h" // _PyMem_IsPtrFreed()

#include "pycore_opcode_utils.h"
Expand Down Expand Up @@ -1874,6 +1875,12 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
continue;
}
break;
case CALL_INTRINSIC_1:
// for _ in (*foo, *bar) -> for _ in [*foo, *bar]
if (oparg == INTRINSIC_LIST_TO_TUPLE && nextop == GET_ITER) {
INSTR_SET_OP0(inst, NOP);
}
break;
}
}

Expand Down

0 comments on commit 004f9fd

Please sign in to comment.