gh-93678: move normalize_basic_block and extend_block call into optimize_cfg (GH-95002)

This commit is contained in:
Irit Katriel 2022-07-19 17:48:56 +01:00 committed by GitHub
parent f36589510b
commit ea11c17742
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -85,6 +85,10 @@
(opcode) == SETUP_WITH || \ (opcode) == SETUP_WITH || \
(opcode) == SETUP_CLEANUP) (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 */ /* opcodes which are not emitted in codegen stage, only by the assembler */
#define IS_ASSEMBLER_OPCODE(opcode) \ #define IS_ASSEMBLER_OPCODE(opcode) \
((opcode) == JUMP_FORWARD || \ ((opcode) == JUMP_FORWARD || \
@ -262,7 +266,7 @@ typedef struct basicblock_ {
static struct instr * static struct instr *
basicblock_last_instr(basicblock *b) { basicblock_last_instr(const basicblock *b) {
if (b->b_iused) { if (b->b_iused) {
return &b->b_instr[b->b_iused - 1]; return &b->b_instr[b->b_iused - 1];
} }
@ -270,19 +274,19 @@ basicblock_last_instr(basicblock *b) {
} }
static inline int static inline int
basicblock_returns(basicblock *b) { basicblock_returns(const basicblock *b) {
struct instr *last = basicblock_last_instr(b); struct instr *last = basicblock_last_instr(b);
return last && last->i_opcode == RETURN_VALUE; return last && last->i_opcode == RETURN_VALUE;
} }
static inline int static inline int
basicblock_exits_scope(basicblock *b) { basicblock_exits_scope(const basicblock *b) {
struct instr *last = basicblock_last_instr(b); struct instr *last = basicblock_last_instr(b);
return last && IS_SCOPE_EXIT_OPCODE(last->i_opcode); return last && IS_SCOPE_EXIT_OPCODE(last->i_opcode);
} }
static inline int static inline int
basicblock_nofallthrough(basicblock *b) { basicblock_nofallthrough(const basicblock *b) {
struct instr *last = basicblock_last_instr(b); struct instr *last = basicblock_last_instr(b);
return (last && return (last &&
(IS_SCOPE_EXIT_OPCODE(last->i_opcode) || (IS_SCOPE_EXIT_OPCODE(last->i_opcode) ||
@ -1243,18 +1247,12 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
return stack_effect(opcode, oparg, -1); return stack_effect(opcode, oparg, -1);
} }
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 static int
compiler_use_new_implicit_block_if_needed(struct compiler *c) compiler_use_new_implicit_block_if_needed(struct compiler *c)
{ {
basicblock *b = c->u->u_curblock; 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); basicblock *b = compiler_new_block(c);
if (b == NULL) { if (b == NULL) {
return -1; return -1;
@ -8553,18 +8551,6 @@ assemble(struct compiler *c, int addNone)
ADDOP(c, RETURN_VALUE); 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_varnames) < INT_MAX);
assert(PyDict_GET_SIZE(c->u->u_cellvars) < INT_MAX); assert(PyDict_GET_SIZE(c->u->u_cellvars) < INT_MAX);
assert(PyDict_GET_SIZE(c->u->u_freevars) < 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)) { if (optimize_cfg(entryblock, consts, c->c_const_cache)) {
goto error; goto error;
} }
if (duplicate_exits_without_lineno(entryblock)) {
return NULL;
}
if (trim_unused_consts(entryblock, consts)) { if (trim_unused_consts(entryblock, consts)) {
goto error; goto error;
} }
if (duplicate_exits_without_lineno(entryblock)) {
return NULL;
}
propagate_line_numbers(entryblock); propagate_line_numbers(entryblock);
guarantee_lineno_for_exits(entryblock, c->u->u_firstlineno); guarantee_lineno_for_exits(entryblock, c->u->u_firstlineno);
@ -9323,8 +9309,8 @@ clean_basic_block(basicblock *bb) {
static int static int
normalize_basic_block(basicblock *bb) { normalize_basic_block(basicblock *bb) {
/* Mark blocks as exit and/or nofallthrough. /* Skip over empty blocks.
Raise SystemError if CFG is malformed. */ * Raise SystemError if jump or exit is not last instruction in the block. */
for (int i = 0; i < bb->b_iused; i++) { for (int i = 0; i < bb->b_iused; i++) {
int opcode = bb->b_instr[i].i_opcode; int opcode = bb->b_instr[i].i_opcode;
assert(!IS_ASSEMBLER_OPCODE(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 The consts object should still be in list form to allow new constants
to be appended. to be appended.
All transformations keep the code size the same or smaller. Code trasnformations that reduce code size initially fill the gaps with
For those that reduce size, the gaps are initially filled with
NOPs. Later those NOPs are removed. NOPs. Later those NOPs are removed.
*/ */
@ -9470,6 +9455,16 @@ static int
optimize_cfg(basicblock *entryblock, PyObject *consts, PyObject *const_cache) optimize_cfg(basicblock *entryblock, PyObject *consts, PyObject *const_cache)
{ {
assert(PyDict_CheckExact(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) { for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
if (optimize_basic_block(const_cache, b, consts)) { if (optimize_basic_block(const_cache, b, consts)) {
return -1; return -1;