Skip to content

Commit 004f9fd

Browse files
authored
Remove unnecessary LIST_TO_TUPLE conversions (GH-126558)
1 parent 845d924 commit 004f9fd

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

Lib/test/test_peepholer.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,5 +1193,56 @@ def get_insts(lno1, lno2, op1, op2):
11931193
]
11941194
self.cfg_optimization_test(insts, expected_insts, consts=list(range(5)))
11951195

1196+
def test_list_to_tuple_get_iter(self):
1197+
# for _ in (*foo, *bar) -> for _ in [*foo, *bar]
1198+
INTRINSIC_LIST_TO_TUPLE = 6
1199+
insts = [
1200+
("BUILD_LIST", 0, 1),
1201+
("LOAD_FAST", 0, 2),
1202+
("LIST_EXTEND", 1, 3),
1203+
("LOAD_FAST", 1, 4),
1204+
("LIST_EXTEND", 1, 5),
1205+
("CALL_INTRINSIC_1", INTRINSIC_LIST_TO_TUPLE, 6),
1206+
("GET_ITER", None, 7),
1207+
top := self.Label(),
1208+
("FOR_ITER", end := self.Label(), 8),
1209+
("STORE_FAST", 2, 9),
1210+
("JUMP", top, 10),
1211+
end,
1212+
("END_FOR", None, 11),
1213+
("POP_TOP", None, 12),
1214+
("LOAD_CONST", 0, 13),
1215+
("RETURN_VALUE", None, 14),
1216+
]
1217+
expected_insts = [
1218+
("BUILD_LIST", 0, 1),
1219+
("LOAD_FAST", 0, 2),
1220+
("LIST_EXTEND", 1, 3),
1221+
("LOAD_FAST", 1, 4),
1222+
("LIST_EXTEND", 1, 5),
1223+
("NOP", None, 6), # ("CALL_INTRINSIC_1", INTRINSIC_LIST_TO_TUPLE, 6),
1224+
("GET_ITER", None, 7),
1225+
top := self.Label(),
1226+
("FOR_ITER", end := self.Label(), 8),
1227+
("STORE_FAST", 2, 9),
1228+
("JUMP", top, 10),
1229+
end,
1230+
("END_FOR", None, 11),
1231+
("POP_TOP", None, 12),
1232+
("LOAD_CONST", 0, 13),
1233+
("RETURN_VALUE", None, 14),
1234+
]
1235+
self.cfg_optimization_test(insts, expected_insts, consts=[None])
1236+
1237+
def test_list_to_tuple_get_iter_is_safe(self):
1238+
a, b = [], []
1239+
for item in (*(items := [0, 1, 2, 3]),):
1240+
a.append(item)
1241+
b.append(items.pop())
1242+
self.assertEqual(a, [0, 1, 2, 3])
1243+
self.assertEqual(b, [3, 2, 1, 0])
1244+
self.assertEqual(items, [])
1245+
1246+
11961247
if __name__ == "__main__":
11971248
unittest.main()

Python/flowgraph.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "Python.h"
55
#include "pycore_flowgraph.h"
66
#include "pycore_compile.h"
7+
#include "pycore_intrinsics.h"
78
#include "pycore_pymem.h" // _PyMem_IsPtrFreed()
89

910
#include "pycore_opcode_utils.h"
@@ -1874,6 +1875,12 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
18741875
continue;
18751876
}
18761877
break;
1878+
case CALL_INTRINSIC_1:
1879+
// for _ in (*foo, *bar) -> for _ in [*foo, *bar]
1880+
if (oparg == INTRINSIC_LIST_TO_TUPLE && nextop == GET_ITER) {
1881+
INSTR_SET_OP0(inst, NOP);
1882+
}
1883+
break;
18771884
}
18781885
}
18791886

0 commit comments

Comments
 (0)