@@ -29,7 +29,6 @@ typedef struct _PyCfgInstruction {
29
29
int i_opcode ;
30
30
int i_oparg ;
31
31
_PyCompilerSrcLocation i_loc ;
32
- unsigned i_loc_propagated : 1 ; /* location was set by propagate_line_numbers */
33
32
struct _PyCfgBasicblock * i_target ; /* target block (if jump instruction) */
34
33
struct _PyCfgBasicblock * i_except ; /* target block when exception is raised */
35
34
} cfg_instr ;
@@ -146,6 +145,16 @@ basicblock_next_instr(basicblock *b)
146
145
return b -> b_iused ++ ;
147
146
}
148
147
148
+ static cfg_instr *
149
+ basicblock_last_instr (const basicblock * b ) {
150
+ assert (b -> b_iused >= 0 );
151
+ if (b -> b_iused > 0 ) {
152
+ assert (b -> b_instr != NULL );
153
+ return & b -> b_instr [b -> b_iused - 1 ];
154
+ }
155
+ return NULL ;
156
+ }
157
+
149
158
/* Allocate a new block and return a pointer to it.
150
159
Returns NULL on error.
151
160
*/
@@ -186,6 +195,22 @@ basicblock_addop(basicblock *b, int opcode, int oparg, location loc)
186
195
return SUCCESS ;
187
196
}
188
197
198
+ static int
199
+ basicblock_add_jump (basicblock * b , int opcode , basicblock * target , location loc )
200
+ {
201
+ cfg_instr * last = basicblock_last_instr (b );
202
+ if (last && is_jump (last )) {
203
+ return ERROR ;
204
+ }
205
+
206
+ RETURN_IF_ERROR (
207
+ basicblock_addop (b , opcode , target -> b_label .id , loc ));
208
+ last = basicblock_last_instr (b );
209
+ assert (last && last -> i_opcode == opcode );
210
+ last -> i_target = target ;
211
+ return SUCCESS ;
212
+ }
213
+
189
214
static inline int
190
215
basicblock_append_instructions (basicblock * target , basicblock * source )
191
216
{
@@ -199,16 +224,6 @@ basicblock_append_instructions(basicblock *target, basicblock *source)
199
224
return SUCCESS ;
200
225
}
201
226
202
- static cfg_instr *
203
- basicblock_last_instr (const basicblock * b ) {
204
- assert (b -> b_iused >= 0 );
205
- if (b -> b_iused > 0 ) {
206
- assert (b -> b_instr != NULL );
207
- return & b -> b_instr [b -> b_iused - 1 ];
208
- }
209
- return NULL ;
210
- }
211
-
212
227
static inline int
213
228
basicblock_nofallthrough (const basicblock * b ) {
214
229
cfg_instr * last = basicblock_last_instr (b );
@@ -560,8 +575,8 @@ normalize_jumps_in_block(cfg_builder *g, basicblock *b) {
560
575
if (backwards_jump == NULL ) {
561
576
return ERROR ;
562
577
}
563
- basicblock_addop ( backwards_jump , JUMP , target -> b_label . id , last -> i_loc );
564
- backwards_jump -> b_instr [ 0 ]. i_target = target ;
578
+ RETURN_IF_ERROR (
579
+ basicblock_add_jump ( backwards_jump , JUMP , target , last -> i_loc )) ;
565
580
last -> i_opcode = reversed_opcode ;
566
581
last -> i_target = b -> b_next ;
567
582
@@ -1141,13 +1156,7 @@ remove_redundant_jumps(cfg_builder *g) {
1141
1156
basicblock * next = next_nonempty_block (b -> b_next );
1142
1157
if (jump_target == next ) {
1143
1158
changes ++ ;
1144
- if (last -> i_loc_propagated ) {
1145
- b -> b_iused -- ;
1146
- }
1147
- else {
1148
- assert (last -> i_loc .lineno != -1 );
1149
- INSTR_SET_OP0 (last , NOP );
1150
- }
1159
+ INSTR_SET_OP0 (last , NOP );
1151
1160
}
1152
1161
}
1153
1162
}
@@ -1184,23 +1193,23 @@ inline_small_exit_blocks(basicblock *bb) {
1184
1193
// target->i_target using the provided opcode. Return whether or not the
1185
1194
// optimization was successful.
1186
1195
static bool
1187
- jump_thread (cfg_instr * inst , cfg_instr * target , int opcode )
1196
+ jump_thread (basicblock * bb , cfg_instr * inst , cfg_instr * target , int opcode )
1188
1197
{
1189
1198
assert (is_jump (inst ));
1190
1199
assert (is_jump (target ));
1200
+ assert (inst == basicblock_last_instr (bb ));
1191
1201
// bpo-45773: If inst->i_target == target->i_target, then nothing actually
1192
1202
// changes (and we fall into an infinite loop):
1193
- if (inst -> i_loc .lineno == -1 ) assert (inst -> i_loc_propagated );
1194
- if (target -> i_loc .lineno == -1 ) assert (target -> i_loc_propagated );
1195
- if ((inst -> i_loc .lineno == target -> i_loc .lineno ||
1196
- inst -> i_loc_propagated || target -> i_loc_propagated ) &&
1197
- inst -> i_target != target -> i_target )
1198
- {
1199
- inst -> i_target = target -> i_target ;
1200
- inst -> i_opcode = opcode ;
1201
- if (inst -> i_loc_propagated && !target -> i_loc_propagated ) {
1202
- inst -> i_loc = target -> i_loc ;
1203
- }
1203
+ if (inst -> i_target != target -> i_target ) {
1204
+ /* Change inst to NOP and append a jump to target->i_target. The
1205
+ * NOP will be removed later if it's not needed for the lineno.
1206
+ */
1207
+ INSTR_SET_OP0 (inst , NOP );
1208
+
1209
+ RETURN_IF_ERROR (
1210
+ basicblock_add_jump (
1211
+ bb , opcode , target -> i_target , target -> i_loc ));
1212
+
1204
1213
return true;
1205
1214
}
1206
1215
return false;
@@ -1673,29 +1682,29 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
1673
1682
case POP_JUMP_IF_NONE :
1674
1683
switch (target -> i_opcode ) {
1675
1684
case JUMP :
1676
- i -= jump_thread (inst , target , inst -> i_opcode );
1685
+ i -= jump_thread (bb , inst , target , inst -> i_opcode );
1677
1686
}
1678
1687
break ;
1679
1688
case POP_JUMP_IF_FALSE :
1680
1689
switch (target -> i_opcode ) {
1681
1690
case JUMP :
1682
- i -= jump_thread (inst , target , POP_JUMP_IF_FALSE );
1691
+ i -= jump_thread (bb , inst , target , POP_JUMP_IF_FALSE );
1683
1692
}
1684
1693
break ;
1685
1694
case POP_JUMP_IF_TRUE :
1686
1695
switch (target -> i_opcode ) {
1687
1696
case JUMP :
1688
- i -= jump_thread (inst , target , POP_JUMP_IF_TRUE );
1697
+ i -= jump_thread (bb , inst , target , POP_JUMP_IF_TRUE );
1689
1698
}
1690
1699
break ;
1691
1700
case JUMP :
1692
1701
case JUMP_NO_INTERRUPT :
1693
1702
switch (target -> i_opcode ) {
1694
1703
case JUMP :
1695
- i -= jump_thread (inst , target , JUMP );
1704
+ i -= jump_thread (bb , inst , target , JUMP );
1696
1705
continue ;
1697
1706
case JUMP_NO_INTERRUPT :
1698
- i -= jump_thread (inst , target , opcode );
1707
+ i -= jump_thread (bb , inst , target , opcode );
1699
1708
continue ;
1700
1709
}
1701
1710
break ;
@@ -1707,7 +1716,7 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
1707
1716
* of FOR_ITER.
1708
1717
*/
1709
1718
/*
1710
- i -= jump_thread(inst, target, FOR_ITER);
1719
+ i -= jump_thread(bb, inst, target, FOR_ITER);
1711
1720
*/
1712
1721
}
1713
1722
break ;
@@ -2410,7 +2419,6 @@ propagate_line_numbers(basicblock *entryblock) {
2410
2419
for (int i = 0 ; i < b -> b_iused ; i ++ ) {
2411
2420
if (b -> b_instr [i ].i_loc .lineno < 0 ) {
2412
2421
b -> b_instr [i ].i_loc = prev_location ;
2413
- b -> b_instr [i ].i_loc_propagated = 1 ;
2414
2422
}
2415
2423
else {
2416
2424
prev_location = b -> b_instr [i ].i_loc ;
@@ -2420,7 +2428,6 @@ propagate_line_numbers(basicblock *entryblock) {
2420
2428
if (b -> b_next -> b_iused > 0 ) {
2421
2429
if (b -> b_next -> b_instr [0 ].i_loc .lineno < 0 ) {
2422
2430
b -> b_next -> b_instr [0 ].i_loc = prev_location ;
2423
- b -> b_next -> b_instr [0 ].i_loc_propagated = 1 ;
2424
2431
}
2425
2432
}
2426
2433
}
@@ -2429,7 +2436,6 @@ propagate_line_numbers(basicblock *entryblock) {
2429
2436
if (target -> b_predecessors == 1 ) {
2430
2437
if (target -> b_instr [0 ].i_loc .lineno < 0 ) {
2431
2438
target -> b_instr [0 ].i_loc = prev_location ;
2432
- target -> b_instr [0 ].i_loc_propagated = 1 ;
2433
2439
}
2434
2440
}
2435
2441
}
0 commit comments