@@ -1452,6 +1452,93 @@ fold_tuple_of_constants(basicblock *bb, int i, PyObject *consts, PyObject *const
14521452 return SUCCESS ;
14531453}
14541454
1455+ /* Replace:
1456+ BUILD_LIST 0
1457+ LOAD_CONST c1
1458+ LIST_APPEND
1459+ LOAD_CONST c2
1460+ LIST_APPEND
1461+ ...
1462+ LOAD_CONST cN
1463+ LIST_APPEND
1464+ CALL_INTRINSIC_1 INTRINSIC_LIST_TO_TUPLE
1465+ with:
1466+ LOAD_CONST (c1, c2, ... cN)
1467+ */
1468+ static int
1469+ fold_constant_intrinsic_list_to_tuple (basicblock * bb , int i ,
1470+ PyObject * consts , PyObject * const_cache )
1471+ {
1472+ assert (PyDict_CheckExact (const_cache ));
1473+ assert (PyList_CheckExact (consts ));
1474+ assert (i >= 0 && i < bb -> b_iused );
1475+ cfg_instr * intrinsic = & bb -> b_instr [i ];
1476+ assert (
1477+ intrinsic -> i_opcode == CALL_INTRINSIC_1 &&
1478+ intrinsic -> i_oparg == INTRINSIC_LIST_TO_TUPLE
1479+ );
1480+
1481+ PyObject * list = PyList_New (0 );
1482+ if (list == NULL ) {
1483+ return ERROR ;
1484+ }
1485+
1486+ bool expect_append = true;
1487+
1488+ for (int pos = i - 1 ; pos >= 0 ; pos -- ) {
1489+ cfg_instr * instr = & bb -> b_instr [pos ];
1490+
1491+ if (instr -> i_opcode == NOP ) {
1492+ continue ;
1493+ }
1494+
1495+ if (instr -> i_opcode == BUILD_LIST && instr -> i_oparg == 0 ) {
1496+ if (!expect_append ) {
1497+ /* Not a sequence start */
1498+ goto exit ;
1499+ }
1500+ /* Sequence start, we are done. */
1501+ if (PyList_Reverse (list ) < 0 ) {
1502+ goto error ;
1503+ }
1504+ PyObject * newconst = PyList_AsTuple (list );
1505+ if (newconst == NULL ) {
1506+ goto error ;
1507+ }
1508+ Py_DECREF (list );
1509+ int nops = (int )PyTuple_Size (newconst ) * 2 + 1 ;
1510+ nop_out (bb , i - 1 , nops );
1511+ return instr_make_load_const (intrinsic , newconst , consts , const_cache );
1512+ }
1513+
1514+ if (expect_append ) {
1515+ if (!(instr -> i_opcode == LIST_APPEND && instr -> i_oparg == 1 )) {
1516+ goto exit ;
1517+ }
1518+ }
1519+ else {
1520+ if (!loads_const (instr -> i_opcode )) {
1521+ goto exit ;
1522+ }
1523+ PyObject * constant = get_const_value (instr -> i_opcode , instr -> i_oparg , consts );
1524+ int r = PyList_Append (list , constant );
1525+ Py_DECREF (constant );
1526+ if (r < 0 ) {
1527+ goto error ;
1528+ }
1529+ }
1530+
1531+ expect_append = !expect_append ;
1532+ }
1533+
1534+ exit :
1535+ Py_DECREF (list );
1536+ return SUCCESS ;
1537+ error :
1538+ Py_DECREF (list );
1539+ return ERROR ;
1540+ }
1541+
14551542#define MIN_CONST_SEQUENCE_SIZE 3
14561543/*
14571544Optimize lists and sets for:
@@ -2295,8 +2382,12 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
22952382 break ;
22962383 case CALL_INTRINSIC_1 :
22972384 // for _ in (*foo, *bar) -> for _ in [*foo, *bar]
2298- if (oparg == INTRINSIC_LIST_TO_TUPLE && nextop == GET_ITER ) {
2299- INSTR_SET_OP0 (inst , NOP );
2385+ if (oparg == INTRINSIC_LIST_TO_TUPLE ) {
2386+ if (nextop == GET_ITER ) {
2387+ INSTR_SET_OP0 (inst , NOP );
2388+ } else {
2389+ fold_constant_intrinsic_list_to_tuple (bb , i , consts , const_cache );
2390+ }
23002391 }
23012392 else if (oparg == INTRINSIC_UNARY_POSITIVE ) {
23022393 RETURN_IF_ERROR (fold_const_unaryop (bb , i , consts , const_cache ));
0 commit comments