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_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) ||
@ -1243,18 +1247,12 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
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
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.
*/
@ -9470,6 +9455,16 @@ static int
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;