|
85 | 85 | (opcode) == SETUP_WITH || \ |
86 | 86 | (opcode) == SETUP_CLEANUP) |
87 | 87 |
|
| 88 | +/* opcodes that must be last in the basicblock */ |
| 89 | +#define IS_TERMINATOR_OPCODE(opcode) \ |
| 90 | + (IS_JUMP_OPCODE(opcode) || IS_SCOPE_EXIT_OPCODE(opcode)) |
| 91 | + |
88 | 92 | /* opcodes which are not emitted in codegen stage, only by the assembler */ |
89 | 93 | #define IS_ASSEMBLER_OPCODE(opcode) \ |
90 | 94 | ((opcode) == JUMP_FORWARD || \ |
@@ -262,27 +266,27 @@ typedef struct basicblock_ { |
262 | 266 |
|
263 | 267 |
|
264 | 268 | static struct instr * |
265 | | -basicblock_last_instr(basicblock *b) { |
| 269 | +basicblock_last_instr(const basicblock *b) { |
266 | 270 | if (b->b_iused) { |
267 | 271 | return &b->b_instr[b->b_iused - 1]; |
268 | 272 | } |
269 | 273 | return NULL; |
270 | 274 | } |
271 | 275 |
|
272 | 276 | static inline int |
273 | | -basicblock_returns(basicblock *b) { |
| 277 | +basicblock_returns(const basicblock *b) { |
274 | 278 | struct instr *last = basicblock_last_instr(b); |
275 | 279 | return last && last->i_opcode == RETURN_VALUE; |
276 | 280 | } |
277 | 281 |
|
278 | 282 | static inline int |
279 | | -basicblock_exits_scope(basicblock *b) { |
| 283 | +basicblock_exits_scope(const basicblock *b) { |
280 | 284 | struct instr *last = basicblock_last_instr(b); |
281 | 285 | return last && IS_SCOPE_EXIT_OPCODE(last->i_opcode); |
282 | 286 | } |
283 | 287 |
|
284 | 288 | static inline int |
285 | | -basicblock_nofallthrough(basicblock *b) { |
| 289 | +basicblock_nofallthrough(const basicblock *b) { |
286 | 290 | struct instr *last = basicblock_last_instr(b); |
287 | 291 | return (last && |
288 | 292 | (IS_SCOPE_EXIT_OPCODE(last->i_opcode) || |
@@ -1243,18 +1247,12 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg) |
1243 | 1247 | return stack_effect(opcode, oparg, -1); |
1244 | 1248 | } |
1245 | 1249 |
|
1246 | | -static int |
1247 | | -is_end_of_basic_block(struct instr *instr) |
1248 | | -{ |
1249 | | - int opcode = instr->i_opcode; |
1250 | | - return IS_JUMP_OPCODE(opcode) || IS_SCOPE_EXIT_OPCODE(opcode); |
1251 | | -} |
1252 | | - |
1253 | 1250 | static int |
1254 | 1251 | compiler_use_new_implicit_block_if_needed(struct compiler *c) |
1255 | 1252 | { |
1256 | 1253 | basicblock *b = c->u->u_curblock; |
1257 | | - if (b->b_iused && is_end_of_basic_block(basicblock_last_instr(b))) { |
| 1254 | + struct instr *last = basicblock_last_instr(b); |
| 1255 | + if (last && IS_TERMINATOR_OPCODE(last->i_opcode)) { |
1258 | 1256 | basicblock *b = compiler_new_block(c); |
1259 | 1257 | if (b == NULL) { |
1260 | 1258 | return -1; |
@@ -8553,18 +8551,6 @@ assemble(struct compiler *c, int addNone) |
8553 | 8551 | ADDOP(c, RETURN_VALUE); |
8554 | 8552 | } |
8555 | 8553 |
|
8556 | | - for (basicblock *b = c->u->u_blocks; b != NULL; b = b->b_list) { |
8557 | | - if (normalize_basic_block(b)) { |
8558 | | - return NULL; |
8559 | | - } |
8560 | | - } |
8561 | | - |
8562 | | - for (basicblock *b = c->u->u_blocks; b != NULL; b = b->b_list) { |
8563 | | - if (extend_block(b)) { |
8564 | | - return NULL; |
8565 | | - } |
8566 | | - } |
8567 | | - |
8568 | 8554 | assert(PyDict_GET_SIZE(c->u->u_varnames) < INT_MAX); |
8569 | 8555 | assert(PyDict_GET_SIZE(c->u->u_cellvars) < INT_MAX); |
8570 | 8556 | assert(PyDict_GET_SIZE(c->u->u_freevars) < INT_MAX); |
@@ -8622,12 +8608,12 @@ assemble(struct compiler *c, int addNone) |
8622 | 8608 | if (optimize_cfg(entryblock, consts, c->c_const_cache)) { |
8623 | 8609 | goto error; |
8624 | 8610 | } |
8625 | | - if (duplicate_exits_without_lineno(entryblock)) { |
8626 | | - return NULL; |
8627 | | - } |
8628 | 8611 | if (trim_unused_consts(entryblock, consts)) { |
8629 | 8612 | goto error; |
8630 | 8613 | } |
| 8614 | + if (duplicate_exits_without_lineno(entryblock)) { |
| 8615 | + return NULL; |
| 8616 | + } |
8631 | 8617 | propagate_line_numbers(entryblock); |
8632 | 8618 | guarantee_lineno_for_exits(entryblock, c->u->u_firstlineno); |
8633 | 8619 |
|
@@ -9323,8 +9309,8 @@ clean_basic_block(basicblock *bb) { |
9323 | 9309 |
|
9324 | 9310 | static int |
9325 | 9311 | normalize_basic_block(basicblock *bb) { |
9326 | | - /* Mark blocks as exit and/or nofallthrough. |
9327 | | - Raise SystemError if CFG is malformed. */ |
| 9312 | + /* Skip over empty blocks. |
| 9313 | + * Raise SystemError if jump or exit is not last instruction in the block. */ |
9328 | 9314 | for (int i = 0; i < bb->b_iused; i++) { |
9329 | 9315 | int opcode = bb->b_instr[i].i_opcode; |
9330 | 9316 | assert(!IS_ASSEMBLER_OPCODE(opcode)); |
@@ -9461,15 +9447,24 @@ propagate_line_numbers(basicblock *entryblock) { |
9461 | 9447 | The consts object should still be in list form to allow new constants |
9462 | 9448 | to be appended. |
9463 | 9449 |
|
9464 | | - All transformations keep the code size the same or smaller. |
9465 | | - For those that reduce size, the gaps are initially filled with |
| 9450 | + Code trasnformations that reduce code size initially fill the gaps with |
9466 | 9451 | NOPs. Later those NOPs are removed. |
9467 | 9452 | */ |
9468 | 9453 |
|
9469 | 9454 | static int |
9470 | 9455 | optimize_cfg(basicblock *entryblock, PyObject *consts, PyObject *const_cache) |
9471 | 9456 | { |
9472 | 9457 | assert(PyDict_CheckExact(const_cache)); |
| 9458 | + for (basicblock *b = entryblock; b != NULL; b = b->b_next) { |
| 9459 | + if (normalize_basic_block(b)) { |
| 9460 | + return -1; |
| 9461 | + } |
| 9462 | + } |
| 9463 | + for (basicblock *b = entryblock; b != NULL; b = b->b_next) { |
| 9464 | + if (extend_block(b)) { |
| 9465 | + return -1; |
| 9466 | + } |
| 9467 | + } |
9473 | 9468 | for (basicblock *b = entryblock; b != NULL; b = b->b_next) { |
9474 | 9469 | if (optimize_basic_block(const_cache, b, consts)) { |
9475 | 9470 | return -1; |
|
0 commit comments