mirror of
https://github.com/python/cpython.git
synced 2025-07-24 11:44:31 +00:00
gh-93678: move normalize_basic_block and extend_block call into optimize_cfg (GH-95002)
This commit is contained in:
parent
f36589510b
commit
ea11c17742
1 changed files with 26 additions and 31 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue