@@ -126,6 +126,12 @@ is_jump(cfg_instr *i)
126126 _instr__ptr_->i_oparg = 0; \
127127 } while (0);
128128
129+ #define INSTR_SET_LOC (I , LOC ) \
130+ do { \
131+ cfg_instr *_instr__ptr_ = (I); \
132+ _instr__ptr_->i_loc = (LOC); \
133+ } while (0);
134+
129135/***** Blocks *****/
130136
131137/* Returns the offset of the next instruction in the current block's
@@ -1382,18 +1388,20 @@ get_constant_sequence(basicblock *bb, int start, int size,
13821388
13831389/*
13841390 Walk basic block backwards starting from "start" and change "count" number of
1385- non-NOP instructions to NOP's.
1391+ non-NOP instructions to NOP's and set their location to NO_LOCATION .
13861392*/
13871393static void
13881394nop_out (basicblock * bb , int start , int count )
13891395{
13901396 assert (start < bb -> b_iused );
13911397 for (; count > 0 ; start -- ) {
13921398 assert (start >= 0 );
1393- if (bb -> b_instr [start ].i_opcode == NOP ) {
1399+ cfg_instr * instr = & bb -> b_instr [start ];
1400+ if (instr -> i_opcode == NOP ) {
13941401 continue ;
13951402 }
1396- INSTR_SET_OP0 (& bb -> b_instr [start ], NOP );
1403+ INSTR_SET_OP0 (instr , NOP );
1404+ INSTR_SET_LOC (instr , NO_LOCATION );
13971405 count -- ;
13981406 }
13991407}
@@ -1423,7 +1431,7 @@ fold_tuple_of_constants(basicblock *bb, int n, PyObject *consts, PyObject *const
14231431 int index = add_const (newconst , consts , const_cache );
14241432 RETURN_IF_ERROR (index );
14251433 nop_out (bb , n - 1 , seq_size );
1426- INSTR_SET_OP1 (& bb -> b_instr [ n ] , LOAD_CONST , index );
1434+ INSTR_SET_OP1 (instr , LOAD_CONST , index );
14271435 return SUCCESS ;
14281436}
14291437
@@ -1479,40 +1487,16 @@ optimize_lists_and_sets(basicblock *bb, int i, int nextop,
14791487 else {
14801488 assert (i >= 2 );
14811489 assert (instr -> i_opcode == BUILD_LIST || instr -> i_opcode == BUILD_SET );
1490+
1491+ INSTR_SET_LOC (& bb -> b_instr [i - 2 ], instr -> i_loc );
1492+
14821493 INSTR_SET_OP1 (& bb -> b_instr [i - 2 ], instr -> i_opcode , 0 );
14831494 INSTR_SET_OP1 (& bb -> b_instr [i - 1 ], LOAD_CONST , index );
14841495 INSTR_SET_OP1 (& bb -> b_instr [i ], instr -> i_opcode == BUILD_LIST ? LIST_EXTEND : SET_UPDATE , 1 );
14851496 }
14861497 return SUCCESS ;
14871498}
14881499
1489- /*
1490- Walk basic block backwards starting from "start" to collect instruction pair
1491- that loads consts skipping NOP's in between.
1492- */
1493- static bool
1494- find_load_const_pair (basicblock * bb , int start , cfg_instr * * first , cfg_instr * * second )
1495- {
1496- cfg_instr * second_load_const = NULL ;
1497- while (start >= 0 ) {
1498- cfg_instr * inst = & bb -> b_instr [start -- ];
1499- if (inst -> i_opcode == NOP ) {
1500- continue ;
1501- }
1502- if (!loads_const (inst -> i_opcode )) {
1503- return false;
1504- }
1505- if (second_load_const == NULL ) {
1506- second_load_const = inst ;
1507- continue ;
1508- }
1509- * first = inst ;
1510- * second = second_load_const ;
1511- return true;
1512- }
1513- return false;
1514- }
1515-
15161500/* Determine opcode & oparg for freshly folded constant. */
15171501static int
15181502newop_from_folded (PyObject * newconst , PyObject * consts ,
@@ -1534,27 +1518,25 @@ newop_from_folded(PyObject *newconst, PyObject *consts,
15341518}
15351519
15361520static int
1537- optimize_if_const_op (basicblock * bb , int n , PyObject * consts , PyObject * const_cache )
1521+ optimize_if_const_binop (basicblock * bb , int i , PyObject * consts , PyObject * const_cache )
15381522{
1539- cfg_instr * subscr = & bb -> b_instr [n ];
1540- assert (subscr -> i_opcode == BINARY_OP );
1541- if (subscr -> i_oparg != NB_SUBSCR ) {
1523+ cfg_instr * binop = & bb -> b_instr [i ];
1524+ assert (binop -> i_opcode == BINARY_OP );
1525+ if (binop -> i_oparg != NB_SUBSCR ) {
15421526 /* TODO: support other binary ops */
15431527 return SUCCESS ;
15441528 }
1545- cfg_instr * arg , * idx ;
1546- if (!find_load_const_pair (bb , n - 1 , & arg , & idx )) {
1529+ PyObject * pair ;
1530+ RETURN_IF_ERROR (get_constant_sequence (bb , i - 1 , 2 , consts , & pair ));
1531+ if (pair == NULL ) {
15471532 return SUCCESS ;
15481533 }
1549- PyObject * o = NULL , * key = NULL ;
1550- if ((o = get_const_value (arg -> i_opcode , arg -> i_oparg , consts )) == NULL
1551- || (key = get_const_value (idx -> i_opcode , idx -> i_oparg , consts )) == NULL )
1552- {
1553- goto error ;
1554- }
1555- PyObject * newconst = PyObject_GetItem (o , key );
1556- Py_DECREF (o );
1557- Py_DECREF (key );
1534+ assert (PyTuple_CheckExact (pair ) && PyTuple_Size (pair ) == 2 );
1535+ PyObject * left = PyTuple_GET_ITEM (pair , 0 );
1536+ PyObject * right = PyTuple_GET_ITEM (pair , 1 );
1537+ assert (left != NULL && right != NULL );
1538+ PyObject * newconst = PyObject_GetItem (left , right );
1539+ Py_DECREF (pair );
15581540 if (newconst == NULL ) {
15591541 if (PyErr_ExceptionMatches (PyExc_KeyboardInterrupt )) {
15601542 return ERROR ;
@@ -1564,14 +1546,9 @@ optimize_if_const_op(basicblock *bb, int n, PyObject *consts, PyObject *const_ca
15641546 }
15651547 int newopcode , newoparg ;
15661548 RETURN_IF_ERROR (newop_from_folded (newconst , consts , const_cache , & newopcode , & newoparg ));
1567- INSTR_SET_OP1 (subscr , newopcode , newoparg );
1568- INSTR_SET_OP0 (arg , NOP );
1569- INSTR_SET_OP0 (idx , NOP );
1549+ nop_out (bb , i - 1 , 2 );
1550+ INSTR_SET_OP1 (binop , newopcode , newoparg );
15701551 return SUCCESS ;
1571- error :
1572- Py_XDECREF (o );
1573- Py_XDECREF (key );
1574- return ERROR ;
15751552}
15761553
15771554#define VISITED (-1)
@@ -2072,7 +2049,7 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
20722049 }
20732050 break ;
20742051 case BINARY_OP :
2075- RETURN_IF_ERROR (optimize_if_const_op (bb , i , consts , const_cache ));
2052+ RETURN_IF_ERROR (optimize_if_const_binop (bb , i , consts , const_cache ));
20762053 break ;
20772054 }
20782055 }
0 commit comments