|
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