@@ -8052,29 +8052,24 @@ fold_rotations(struct instr *inst, int n)
8052
8052
}
8053
8053
}
8054
8054
8055
-
8056
- static int
8057
- eliminate_jump_to_jump (basicblock * bb , int opcode ) {
8058
- assert (bb -> b_iused > 0 );
8059
- struct instr * inst = & bb -> b_instr [bb -> b_iused - 1 ];
8060
- assert (is_jump (inst ));
8061
- assert (inst -> i_target -> b_iused > 0 );
8062
- struct instr * target = & inst -> i_target -> b_instr [0 ];
8063
- if (inst -> i_target == target -> i_target ) {
8064
- /* Nothing to do */
8065
- return 0 ;
8066
- }
8067
- int lineno = target -> i_lineno ;
8068
- int end_lineno = target -> i_end_lineno ;
8069
- int col_offset = target -> i_col_offset ;
8070
- int end_col_offset = target -> i_end_col_offset ;
8071
- if (add_jump_to_block (bb , opcode , lineno , end_lineno , col_offset ,
8072
- end_col_offset , target -> i_target ) == 0 ) {
8073
- return -1 ;
8055
+ // Attempt to eliminate jumps to jumps by updating inst to jump to
8056
+ // target->i_target using the provided opcode. Return whether or not the
8057
+ // optimization was successful.
8058
+ static bool
8059
+ jump_thread (struct instr * inst , struct instr * target , int opcode )
8060
+ {
8061
+ assert (is_jump (inst ));
8062
+ assert (is_jump (target ));
8063
+ // bpo-45773: If inst->i_target == target->i_target, then nothing actually
8064
+ // changes (and we fall into an infinite loop):
8065
+ if (inst -> i_lineno == target -> i_lineno &&
8066
+ inst -> i_target != target -> i_target )
8067
+ {
8068
+ inst -> i_target = target -> i_target ;
8069
+ inst -> i_opcode = opcode ;
8070
+ return true;
8074
8071
}
8075
- assert (bb -> b_iused >= 2 );
8076
- bb -> b_instr [bb -> b_iused - 2 ].i_opcode = NOP ;
8077
- return 0 ;
8072
+ return false;
8078
8073
}
8079
8074
8080
8075
/* Maximum size of basic block that should be copied in optimizer */
@@ -8199,108 +8194,78 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
8199
8194
where y+1 is the instruction following the second test.
8200
8195
*/
8201
8196
case JUMP_IF_FALSE_OR_POP :
8202
- switch (target -> i_opcode ) {
8197
+ switch (target -> i_opcode ) {
8203
8198
case POP_JUMP_IF_FALSE :
8204
- if (inst -> i_lineno == target -> i_lineno ) {
8205
- * inst = * target ;
8206
- i -- ;
8207
- }
8199
+ i -= jump_thread (inst , target , POP_JUMP_IF_FALSE );
8208
8200
break ;
8209
8201
case JUMP_ABSOLUTE :
8210
8202
case JUMP_FORWARD :
8211
8203
case JUMP_IF_FALSE_OR_POP :
8212
- if (inst -> i_lineno == target -> i_lineno &&
8213
- inst -> i_target != target -> i_target ) {
8214
- inst -> i_target = target -> i_target ;
8215
- i -- ;
8216
- }
8204
+ i -= jump_thread (inst , target , JUMP_IF_FALSE_OR_POP );
8217
8205
break ;
8218
8206
case JUMP_IF_TRUE_OR_POP :
8219
- assert ( inst -> i_target -> b_iused == 1 );
8207
+ case POP_JUMP_IF_TRUE :
8220
8208
if (inst -> i_lineno == target -> i_lineno ) {
8209
+ // We don't need to bother checking for loops here,
8210
+ // since a block's b_next cannot point to itself:
8211
+ assert (inst -> i_target != inst -> i_target -> b_next );
8221
8212
inst -> i_opcode = POP_JUMP_IF_FALSE ;
8222
8213
inst -> i_target = inst -> i_target -> b_next ;
8223
8214
-- i ;
8224
8215
}
8225
8216
break ;
8226
8217
}
8227
8218
break ;
8228
-
8229
8219
case JUMP_IF_TRUE_OR_POP :
8230
- switch (target -> i_opcode ) {
8220
+ switch (target -> i_opcode ) {
8231
8221
case POP_JUMP_IF_TRUE :
8232
- if (inst -> i_lineno == target -> i_lineno ) {
8233
- * inst = * target ;
8234
- i -- ;
8235
- }
8222
+ i -= jump_thread (inst , target , POP_JUMP_IF_TRUE );
8236
8223
break ;
8237
8224
case JUMP_ABSOLUTE :
8238
8225
case JUMP_FORWARD :
8239
8226
case JUMP_IF_TRUE_OR_POP :
8240
- if (inst -> i_lineno == target -> i_lineno &&
8241
- inst -> i_target != target -> i_target ) {
8242
- inst -> i_target = target -> i_target ;
8243
- i -- ;
8244
- }
8227
+ i -= jump_thread (inst , target , JUMP_IF_TRUE_OR_POP );
8245
8228
break ;
8246
8229
case JUMP_IF_FALSE_OR_POP :
8247
- assert ( inst -> i_target -> b_iused == 1 );
8230
+ case POP_JUMP_IF_FALSE :
8248
8231
if (inst -> i_lineno == target -> i_lineno ) {
8232
+ // We don't need to bother checking for loops here,
8233
+ // since a block's b_next cannot point to itself:
8234
+ assert (inst -> i_target != inst -> i_target -> b_next );
8249
8235
inst -> i_opcode = POP_JUMP_IF_TRUE ;
8250
8236
inst -> i_target = inst -> i_target -> b_next ;
8251
8237
-- i ;
8252
8238
}
8253
8239
break ;
8254
8240
}
8255
8241
break ;
8256
-
8257
8242
case POP_JUMP_IF_FALSE :
8258
- switch (target -> i_opcode ) {
8243
+ switch (target -> i_opcode ) {
8259
8244
case JUMP_ABSOLUTE :
8260
8245
case JUMP_FORWARD :
8261
- if (inst -> i_lineno == target -> i_lineno ) {
8262
- inst -> i_target = target -> i_target ;
8263
- i -- ;
8264
- }
8265
- break ;
8246
+ case JUMP_IF_FALSE_OR_POP :
8247
+ i -= jump_thread (inst , target , POP_JUMP_IF_FALSE );
8266
8248
}
8267
8249
break ;
8268
-
8269
8250
case POP_JUMP_IF_TRUE :
8270
- switch (target -> i_opcode ) {
8251
+ switch (target -> i_opcode ) {
8271
8252
case JUMP_ABSOLUTE :
8272
8253
case JUMP_FORWARD :
8273
- if (inst -> i_lineno == target -> i_lineno ) {
8274
- inst -> i_target = target -> i_target ;
8275
- i -- ;
8276
- }
8277
- break ;
8254
+ case JUMP_IF_TRUE_OR_POP :
8255
+ i -= jump_thread (inst , target , POP_JUMP_IF_TRUE );
8278
8256
}
8279
8257
break ;
8280
-
8281
8258
case JUMP_ABSOLUTE :
8282
8259
case JUMP_FORWARD :
8283
- assert (i == bb -> b_iused - 1 );
8284
- switch (target -> i_opcode ) {
8285
- case JUMP_FORWARD :
8286
- if (eliminate_jump_to_jump (bb , inst -> i_opcode )) {
8287
- goto error ;
8288
- }
8289
- break ;
8290
-
8260
+ switch (target -> i_opcode ) {
8291
8261
case JUMP_ABSOLUTE :
8292
- if (eliminate_jump_to_jump (bb , JUMP_ABSOLUTE )) {
8293
- goto error ;
8294
- }
8295
- break ;
8262
+ case JUMP_FORWARD :
8263
+ i -= jump_thread (inst , target , JUMP_ABSOLUTE );
8296
8264
}
8297
8265
break ;
8298
8266
case FOR_ITER :
8299
- assert (i == bb -> b_iused - 1 );
8300
8267
if (target -> i_opcode == JUMP_FORWARD ) {
8301
- if (eliminate_jump_to_jump (bb , inst -> i_opcode )) {
8302
- goto error ;
8303
- }
8268
+ i -= jump_thread (inst , target , FOR_ITER );
8304
8269
}
8305
8270
break ;
8306
8271
case ROT_N :
0 commit comments