@@ -1428,31 +1428,42 @@ fold_tuple_of_constants(basicblock *bb, int n, PyObject *consts, PyObject *const
1428
1428
}
1429
1429
1430
1430
#define MIN_CONST_SEQUENCE_SIZE 3
1431
- /* Replace LOAD_CONST c1, LOAD_CONST c2 ... LOAD_CONST cN, BUILD_LIST N
1432
- with BUILD_LIST 0, LOAD_CONST (c1, c2, ... cN), LIST_EXTEND 1,
1433
- or BUILD_SET & SET_UPDATE respectively.
1431
+ /*
1432
+ Optimize literal list/set for:
1433
+ 1. "for" loop, comprehension or "in"/"not in" tests:
1434
+ Change literal list or set of constants into constant
1435
+ tuple or frozenset respectively. Change literal list of
1436
+ non-constants into tuple.
1437
+ 2. Constant literal lists/set with length >= MIN_CONST_SEQUENCE_SIZE:
1438
+ Replace LOAD_CONST c1, LOAD_CONST c2 ... LOAD_CONST cN, BUILD_LIST N
1439
+ with BUILD_LIST 0, LOAD_CONST (c1, c2, ... cN), LIST_EXTEND 1,
1440
+ or BUILD_SET & SET_UPDATE respectively.
1434
1441
*/
1435
1442
static int
1436
- optimize_if_const_list_or_set (basicblock * bb , int n , PyObject * consts , PyObject * const_cache )
1443
+ optimize_list_or_set_literal (basicblock * bb , int i , int nextop ,
1444
+ PyObject * consts , PyObject * const_cache )
1437
1445
{
1438
1446
assert (PyDict_CheckExact (const_cache ));
1439
1447
assert (PyList_CheckExact (consts ));
1440
- cfg_instr * instr = & bb -> b_instr [n ];
1448
+ cfg_instr * instr = & bb -> b_instr [i ];
1441
1449
assert (instr -> i_opcode == BUILD_LIST || instr -> i_opcode == BUILD_SET );
1450
+ bool contains_or_iter_literal = nextop == GET_ITER || nextop == CONTAINS_OP ;
1442
1451
int seq_size = instr -> i_oparg ;
1443
- if (seq_size < MIN_CONST_SEQUENCE_SIZE ) {
1452
+ if (seq_size < MIN_CONST_SEQUENCE_SIZE && ! contains_or_iter_literal ) {
1444
1453
return SUCCESS ;
1445
1454
}
1446
1455
PyObject * newconst ;
1447
- RETURN_IF_ERROR (get_constant_sequence (bb , n - 1 , seq_size , consts , & newconst ));
1456
+ RETURN_IF_ERROR (get_constant_sequence (bb , i - 1 , seq_size , consts , & newconst ));
1448
1457
if (newconst == NULL ) {
1449
1458
/* not a const sequence */
1459
+ if (contains_or_iter_literal && instr -> i_opcode == BUILD_LIST ) {
1460
+ /* convert list iterable to tuple */
1461
+ INSTR_SET_OP1 (instr , BUILD_TUPLE , instr -> i_oparg );
1462
+ }
1450
1463
return SUCCESS ;
1451
1464
}
1452
1465
assert (PyTuple_CheckExact (newconst ) && PyTuple_GET_SIZE (newconst ) == seq_size );
1453
- int build = instr -> i_opcode ;
1454
- int extend = build == BUILD_LIST ? LIST_EXTEND : SET_UPDATE ;
1455
- if (build == BUILD_SET ) {
1466
+ if (instr -> i_opcode == BUILD_SET ) {
1456
1467
PyObject * frozenset = PyFrozenSet_New (newconst );
1457
1468
if (frozenset == NULL ) {
1458
1469
Py_DECREF (newconst );
@@ -1462,11 +1473,16 @@ optimize_if_const_list_or_set(basicblock *bb, int n, PyObject *consts, PyObject
1462
1473
}
1463
1474
int index = add_const (newconst , consts , const_cache );
1464
1475
RETURN_IF_ERROR (index );
1465
- nop_out (bb , n - 1 , seq_size );
1466
- assert (n >= 2 );
1467
- INSTR_SET_OP1 (& bb -> b_instr [n - 2 ], build , 0 );
1468
- INSTR_SET_OP1 (& bb -> b_instr [n - 1 ], LOAD_CONST , index );
1469
- INSTR_SET_OP1 (& bb -> b_instr [n ], extend , 1 );
1476
+ nop_out (bb , i - 1 , seq_size );
1477
+ if (contains_or_iter_literal ) {
1478
+ INSTR_SET_OP1 (instr , LOAD_CONST , index );
1479
+ }
1480
+ else {
1481
+ assert (i >= 2 );
1482
+ INSTR_SET_OP1 (& bb -> b_instr [i - 2 ], instr -> i_opcode , 0 );
1483
+ INSTR_SET_OP1 (& bb -> b_instr [i - 1 ], LOAD_CONST , index );
1484
+ INSTR_SET_OP1 (& bb -> b_instr [i ], instr -> i_opcode == BUILD_LIST ? LIST_EXTEND : SET_UPDATE , 1 );
1485
+ }
1470
1486
return SUCCESS ;
1471
1487
}
1472
1488
@@ -1558,41 +1574,6 @@ optimize_if_const_op(basicblock *bb, int n, PyObject *consts, PyObject *const_ca
1558
1574
return ERROR ;
1559
1575
}
1560
1576
1561
- static int
1562
- optimize_if_const_list_or_set_iter (basicblock * bb , int n ,
1563
- PyObject * consts , PyObject * const_cache )
1564
- {
1565
- cfg_instr * instr = & bb -> b_instr [n ];
1566
- assert (instr -> i_opcode == BUILD_LIST || instr -> i_opcode == BUILD_SET );
1567
- assert (n + 1 < bb -> b_iused );
1568
- cfg_instr * next = & bb -> b_instr [n + 1 ];
1569
- assert (next -> i_opcode == GET_ITER || next -> i_opcode == CONTAINS_OP );
1570
- int seq_size = instr -> i_oparg ;
1571
- PyObject * newconst ;
1572
- RETURN_IF_ERROR (get_constant_sequence (bb , n - 1 , seq_size , consts , & newconst ));
1573
- if (newconst == NULL ) {
1574
- /* not a const sequence */
1575
- if (instr -> i_opcode == BUILD_LIST ) {
1576
- /* even if not const list, it is still changed to build tuple */
1577
- INSTR_SET_OP1 (instr , BUILD_TUPLE , instr -> i_oparg );
1578
- }
1579
- return SUCCESS ;
1580
- }
1581
- if (instr -> i_opcode == BUILD_SET ) {
1582
- PyObject * frozenset = PyFrozenSet_New (newconst );
1583
- if (frozenset == NULL ) {
1584
- Py_DECREF (newconst );
1585
- return ERROR ;
1586
- }
1587
- Py_SETREF (newconst , frozenset );
1588
- }
1589
- int index = add_const (newconst , consts , const_cache );
1590
- RETURN_IF_ERROR (index );
1591
- nop_out (bb , n - 1 , seq_size );
1592
- INSTR_SET_OP1 (instr , LOAD_CONST , index );
1593
- return SUCCESS ;
1594
- }
1595
-
1596
1577
#define VISITED (-1)
1597
1578
1598
1579
// Replace an arbitrary run of SWAPs and NOPs with an optimal one that has the
@@ -1958,12 +1939,7 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
1958
1939
break ;
1959
1940
case BUILD_LIST :
1960
1941
case BUILD_SET :
1961
- if (nextop == GET_ITER || nextop == CONTAINS_OP ) {
1962
- RETURN_IF_ERROR (optimize_if_const_list_or_set_iter (bb , i , consts , const_cache ));
1963
- }
1964
- else {
1965
- RETURN_IF_ERROR (optimize_if_const_list_or_set (bb , i , consts , const_cache ));
1966
- }
1942
+ RETURN_IF_ERROR (optimize_list_or_set_literal (bb , i , nextop , consts , const_cache ));
1967
1943
break ;
1968
1944
case POP_JUMP_IF_NOT_NONE :
1969
1945
case POP_JUMP_IF_NONE :
0 commit comments