diff options
author | Irit Katriel <1055913+iritkatriel@users.noreply.github.com> | 2022-07-19 16:48:56 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-19 16:48:56 (GMT) |
commit | ea11c1774274aa9f4d6eee863d37632aa79a0ace (patch) | |
tree | a6710589610af4721e6c9d5967defb9e1902da6d /Python/compile.c | |
parent | f36589510b8708fa224d799d5b328deab558aa4e (diff) | |
download | cpython-ea11c1774274aa9f4d6eee863d37632aa79a0ace.zip cpython-ea11c1774274aa9f4d6eee863d37632aa79a0ace.tar.gz cpython-ea11c1774274aa9f4d6eee863d37632aa79a0ace.tar.bz2 |
gh-93678: move normalize_basic_block and extend_block call into optimize_cfg (GH-95002)
Diffstat (limited to 'Python/compile.c')
-rw-r--r-- | Python/compile.c | 57 |
1 files changed, 26 insertions, 31 deletions
diff --git a/Python/compile.c b/Python/compile.c index 427fb2a..30d8fdb 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -85,6 +85,10 @@ (opcode) == SETUP_WITH || \ (opcode) == SETUP_CLEANUP) +/* opcodes that must be last in the basicblock */ +#define IS_TERMINATOR_OPCODE(opcode) \ + (IS_JUMP_OPCODE(opcode) || IS_SCOPE_EXIT_OPCODE(opcode)) + /* opcodes which are not emitted in codegen stage, only by the assembler */ #define IS_ASSEMBLER_OPCODE(opcode) \ ((opcode) == JUMP_FORWARD || \ @@ -262,7 +266,7 @@ typedef struct basicblock_ { static struct instr * -basicblock_last_instr(basicblock *b) { +basicblock_last_instr(const basicblock *b) { if (b->b_iused) { return &b->b_instr[b->b_iused - 1]; } @@ -270,19 +274,19 @@ basicblock_last_instr(basicblock *b) { } static inline int -basicblock_returns(basicblock *b) { +basicblock_returns(const basicblock *b) { struct instr *last = basicblock_last_instr(b); return last && last->i_opcode == RETURN_VALUE; } static inline int -basicblock_exits_scope(basicblock *b) { +basicblock_exits_scope(const basicblock *b) { struct instr *last = basicblock_last_instr(b); return last && IS_SCOPE_EXIT_OPCODE(last->i_opcode); } static inline int -basicblock_nofallthrough(basicblock *b) { +basicblock_nofallthrough(const basicblock *b) { struct instr *last = basicblock_last_instr(b); return (last && (IS_SCOPE_EXIT_OPCODE(last->i_opcode) || @@ -1244,17 +1248,11 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg) } static int -is_end_of_basic_block(struct instr *instr) -{ - int opcode = instr->i_opcode; - return IS_JUMP_OPCODE(opcode) || IS_SCOPE_EXIT_OPCODE(opcode); -} - -static int compiler_use_new_implicit_block_if_needed(struct compiler *c) { basicblock *b = c->u->u_curblock; - if (b->b_iused && is_end_of_basic_block(basicblock_last_instr(b))) { + struct instr *last = basicblock_last_instr(b); + if (last && IS_TERMINATOR_OPCODE(last->i_opcode)) { basicblock *b = compiler_new_block(c); if (b == NULL) { return -1; @@ -8553,18 +8551,6 @@ assemble(struct compiler *c, int addNone) ADDOP(c, RETURN_VALUE); } - for (basicblock *b = c->u->u_blocks; b != NULL; b = b->b_list) { - if (normalize_basic_block(b)) { - return NULL; - } - } - - for (basicblock *b = c->u->u_blocks; b != NULL; b = b->b_list) { - if (extend_block(b)) { - return NULL; - } - } - assert(PyDict_GET_SIZE(c->u->u_varnames) < INT_MAX); assert(PyDict_GET_SIZE(c->u->u_cellvars) < INT_MAX); assert(PyDict_GET_SIZE(c->u->u_freevars) < INT_MAX); @@ -8622,12 +8608,12 @@ assemble(struct compiler *c, int addNone) if (optimize_cfg(entryblock, consts, c->c_const_cache)) { goto error; } - if (duplicate_exits_without_lineno(entryblock)) { - return NULL; - } if (trim_unused_consts(entryblock, consts)) { goto error; } + if (duplicate_exits_without_lineno(entryblock)) { + return NULL; + } propagate_line_numbers(entryblock); guarantee_lineno_for_exits(entryblock, c->u->u_firstlineno); @@ -9323,8 +9309,8 @@ clean_basic_block(basicblock *bb) { static int normalize_basic_block(basicblock *bb) { - /* Mark blocks as exit and/or nofallthrough. - Raise SystemError if CFG is malformed. */ + /* Skip over empty blocks. + * Raise SystemError if jump or exit is not last instruction in the block. */ for (int i = 0; i < bb->b_iused; i++) { int opcode = bb->b_instr[i].i_opcode; assert(!IS_ASSEMBLER_OPCODE(opcode)); @@ -9461,8 +9447,7 @@ propagate_line_numbers(basicblock *entryblock) { The consts object should still be in list form to allow new constants to be appended. - All transformations keep the code size the same or smaller. - For those that reduce size, the gaps are initially filled with + Code trasnformations that reduce code size initially fill the gaps with NOPs. Later those NOPs are removed. */ @@ -9471,6 +9456,16 @@ optimize_cfg(basicblock *entryblock, PyObject *consts, PyObject *const_cache) { assert(PyDict_CheckExact(const_cache)); for (basicblock *b = entryblock; b != NULL; b = b->b_next) { + if (normalize_basic_block(b)) { + return -1; + } + } + for (basicblock *b = entryblock; b != NULL; b = b->b_next) { + if (extend_block(b)) { + return -1; + } + } + for (basicblock *b = entryblock; b != NULL; b = b->b_next) { if (optimize_basic_block(const_cache, b, consts)) { return -1; } |