@@ -126,6 +126,12 @@ is_jump(cfg_instr *i)
126
126
_instr__ptr_->i_oparg = 0; \
127
127
} while (0);
128
128
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
+
129
135
/***** Blocks *****/
130
136
131
137
/* 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,
1382
1388
1383
1389
/*
1384
1390
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 .
1386
1392
*/
1387
1393
static void
1388
1394
nop_out (basicblock * bb , int start , int count )
1389
1395
{
1390
1396
assert (start < bb -> b_iused );
1391
1397
for (; count > 0 ; start -- ) {
1392
1398
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 ) {
1394
1401
continue ;
1395
1402
}
1396
- INSTR_SET_OP0 (& bb -> b_instr [start ], NOP );
1403
+ INSTR_SET_OP0 (instr , NOP );
1404
+ INSTR_SET_LOC (instr , NO_LOCATION );
1397
1405
count -- ;
1398
1406
}
1399
1407
}
@@ -1423,7 +1431,7 @@ fold_tuple_of_constants(basicblock *bb, int n, PyObject *consts, PyObject *const
1423
1431
int index = add_const (newconst , consts , const_cache );
1424
1432
RETURN_IF_ERROR (index );
1425
1433
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 );
1427
1435
return SUCCESS ;
1428
1436
}
1429
1437
@@ -1479,40 +1487,16 @@ optimize_lists_and_sets(basicblock *bb, int i, int nextop,
1479
1487
else {
1480
1488
assert (i >= 2 );
1481
1489
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
+
1482
1493
INSTR_SET_OP1 (& bb -> b_instr [i - 2 ], instr -> i_opcode , 0 );
1483
1494
INSTR_SET_OP1 (& bb -> b_instr [i - 1 ], LOAD_CONST , index );
1484
1495
INSTR_SET_OP1 (& bb -> b_instr [i ], instr -> i_opcode == BUILD_LIST ? LIST_EXTEND : SET_UPDATE , 1 );
1485
1496
}
1486
1497
return SUCCESS ;
1487
1498
}
1488
1499
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
-
1516
1500
/* Determine opcode & oparg for freshly folded constant. */
1517
1501
static int
1518
1502
newop_from_folded (PyObject * newconst , PyObject * consts ,
@@ -1534,27 +1518,25 @@ newop_from_folded(PyObject *newconst, PyObject *consts,
1534
1518
}
1535
1519
1536
1520
static 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 )
1538
1522
{
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 ) {
1542
1526
/* TODO: support other binary ops */
1543
1527
return SUCCESS ;
1544
1528
}
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 ) {
1547
1532
return SUCCESS ;
1548
1533
}
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 );
1558
1540
if (newconst == NULL ) {
1559
1541
if (PyErr_ExceptionMatches (PyExc_KeyboardInterrupt )) {
1560
1542
return ERROR ;
@@ -1564,14 +1546,9 @@ optimize_if_const_op(basicblock *bb, int n, PyObject *consts, PyObject *const_ca
1564
1546
}
1565
1547
int newopcode , newoparg ;
1566
1548
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 );
1570
1551
return SUCCESS ;
1571
- error :
1572
- Py_XDECREF (o );
1573
- Py_XDECREF (key );
1574
- return ERROR ;
1575
1552
}
1576
1553
1577
1554
#define VISITED (-1)
@@ -2072,7 +2049,7 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
2072
2049
}
2073
2050
break ;
2074
2051
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 ));
2076
2053
break ;
2077
2054
}
2078
2055
}
0 commit comments