@@ -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,22 @@ 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 i_loc info to "location" if provided .
13861392*/
13871393static void
1388- nop_out (basicblock * bb , int start , int count )
1394+ nop_out (basicblock * bb , int start , int count , _Py_SourceLocation * location )
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+ if (location != NULL ) {
1405+ INSTR_SET_LOC (instr , * location );
1406+ }
13971407 count -- ;
13981408 }
13991409}
@@ -1422,8 +1432,8 @@ fold_tuple_of_constants(basicblock *bb, int n, PyObject *consts, PyObject *const
14221432 assert (PyTuple_CheckExact (newconst ) && PyTuple_GET_SIZE (newconst ) == seq_size );
14231433 int index = add_const (newconst , consts , const_cache );
14241434 RETURN_IF_ERROR (index );
1425- nop_out (bb , n - 1 , seq_size );
1426- INSTR_SET_OP1 (& bb -> b_instr [ n ] , LOAD_CONST , index );
1435+ nop_out (bb , n - 1 , seq_size , & instr -> i_loc );
1436+ INSTR_SET_OP1 (instr , LOAD_CONST , index );
14271437 return SUCCESS ;
14281438}
14291439
@@ -1472,7 +1482,7 @@ optimize_lists_and_sets(basicblock *bb, int i, int nextop,
14721482 }
14731483 int index = add_const (newconst , consts , const_cache );
14741484 RETURN_IF_ERROR (index );
1475- nop_out (bb , i - 1 , seq_size );
1485+ nop_out (bb , i - 1 , seq_size , & instr -> i_loc );
14761486 if (contains_or_iter ) {
14771487 INSTR_SET_OP1 (instr , LOAD_CONST , index );
14781488 }
@@ -1486,33 +1496,6 @@ optimize_lists_and_sets(basicblock *bb, int i, int nextop,
14861496 return SUCCESS ;
14871497}
14881498
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-
15161499/* Determine opcode & oparg for freshly folded constant. */
15171500static int
15181501newop_from_folded (PyObject * newconst , PyObject * consts ,
@@ -1534,27 +1517,25 @@ newop_from_folded(PyObject *newconst, PyObject *consts,
15341517}
15351518
15361519static int
1537- optimize_if_const_op (basicblock * bb , int n , PyObject * consts , PyObject * const_cache )
1520+ optimize_if_const_binop (basicblock * bb , int i , PyObject * consts , PyObject * const_cache )
15381521{
1539- cfg_instr * subscr = & bb -> b_instr [n ];
1540- assert (subscr -> i_opcode == BINARY_OP );
1541- if (subscr -> i_oparg != NB_SUBSCR ) {
1522+ cfg_instr * binop = & bb -> b_instr [i ];
1523+ assert (binop -> i_opcode == BINARY_OP );
1524+ if (binop -> i_oparg != NB_SUBSCR ) {
15421525 /* TODO: support other binary ops */
15431526 return SUCCESS ;
15441527 }
1545- cfg_instr * arg , * idx ;
1546- if (!find_load_const_pair (bb , n - 1 , & arg , & idx )) {
1528+ PyObject * pair ;
1529+ RETURN_IF_ERROR (get_constant_sequence (bb , i - 1 , 2 , consts , & pair ));
1530+ if (pair == NULL ) {
15471531 return SUCCESS ;
15481532 }
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 );
1533+ assert (PyTuple_CheckExact (pair ) && PyTuple_Size (pair ) == 2 );
1534+ PyObject * left = PyTuple_GET_ITEM (pair , 0 );
1535+ PyObject * right = PyTuple_GET_ITEM (pair , 1 );
1536+ assert (left != NULL && right != NULL );
1537+ PyObject * newconst = PyObject_GetItem (left , right );
1538+ Py_DECREF (pair );
15581539 if (newconst == NULL ) {
15591540 if (PyErr_ExceptionMatches (PyExc_KeyboardInterrupt )) {
15601541 return ERROR ;
@@ -1564,14 +1545,9 @@ optimize_if_const_op(basicblock *bb, int n, PyObject *consts, PyObject *const_ca
15641545 }
15651546 int newopcode , newoparg ;
15661547 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 );
1548+ nop_out (bb , i - 1 , 2 , & binop -> i_loc );
1549+ INSTR_SET_OP1 (binop , newopcode , newoparg );
15701550 return SUCCESS ;
1571- error :
1572- Py_XDECREF (o );
1573- Py_XDECREF (key );
1574- return ERROR ;
15751551}
15761552
15771553#define VISITED (-1)
@@ -2072,7 +2048,7 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
20722048 }
20732049 break ;
20742050 case BINARY_OP :
2075- RETURN_IF_ERROR (optimize_if_const_op (bb , i , consts , const_cache ));
2051+ RETURN_IF_ERROR (optimize_if_const_binop (bb , i , consts , const_cache ));
20762052 break ;
20772053 }
20782054 }
0 commit comments