Skip to content

Commit ea11c17

Browse files
authored
gh-93678: move normalize_basic_block and extend_block call into optimize_cfg (GH-95002)
1 parent f365895 commit ea11c17

File tree

1 file changed

+26
-31
lines changed

1 file changed

+26
-31
lines changed

Python/compile.c

+26-31
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@
8585
(opcode) == SETUP_WITH || \
8686
(opcode) == SETUP_CLEANUP)
8787

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+
8892
/* opcodes which are not emitted in codegen stage, only by the assembler */
8993
#define IS_ASSEMBLER_OPCODE(opcode) \
9094
((opcode) == JUMP_FORWARD || \
@@ -262,27 +266,27 @@ typedef struct basicblock_ {
262266

263267

264268
static struct instr *
265-
basicblock_last_instr(basicblock *b) {
269+
basicblock_last_instr(const basicblock *b) {
266270
if (b->b_iused) {
267271
return &b->b_instr[b->b_iused - 1];
268272
}
269273
return NULL;
270274
}
271275

272276
static inline int
273-
basicblock_returns(basicblock *b) {
277+
basicblock_returns(const basicblock *b) {
274278
struct instr *last = basicblock_last_instr(b);
275279
return last && last->i_opcode == RETURN_VALUE;
276280
}
277281

278282
static inline int
279-
basicblock_exits_scope(basicblock *b) {
283+
basicblock_exits_scope(const basicblock *b) {
280284
struct instr *last = basicblock_last_instr(b);
281285
return last && IS_SCOPE_EXIT_OPCODE(last->i_opcode);
282286
}
283287

284288
static inline int
285-
basicblock_nofallthrough(basicblock *b) {
289+
basicblock_nofallthrough(const basicblock *b) {
286290
struct instr *last = basicblock_last_instr(b);
287291
return (last &&
288292
(IS_SCOPE_EXIT_OPCODE(last->i_opcode) ||
@@ -1243,18 +1247,12 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
12431247
return stack_effect(opcode, oparg, -1);
12441248
}
12451249

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-
12531250
static int
12541251
compiler_use_new_implicit_block_if_needed(struct compiler *c)
12551252
{
12561253
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)) {
12581256
basicblock *b = compiler_new_block(c);
12591257
if (b == NULL) {
12601258
return -1;
@@ -8553,18 +8551,6 @@ assemble(struct compiler *c, int addNone)
85538551
ADDOP(c, RETURN_VALUE);
85548552
}
85558553

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-
85688554
assert(PyDict_GET_SIZE(c->u->u_varnames) < INT_MAX);
85698555
assert(PyDict_GET_SIZE(c->u->u_cellvars) < INT_MAX);
85708556
assert(PyDict_GET_SIZE(c->u->u_freevars) < INT_MAX);
@@ -8622,12 +8608,12 @@ assemble(struct compiler *c, int addNone)
86228608
if (optimize_cfg(entryblock, consts, c->c_const_cache)) {
86238609
goto error;
86248610
}
8625-
if (duplicate_exits_without_lineno(entryblock)) {
8626-
return NULL;
8627-
}
86288611
if (trim_unused_consts(entryblock, consts)) {
86298612
goto error;
86308613
}
8614+
if (duplicate_exits_without_lineno(entryblock)) {
8615+
return NULL;
8616+
}
86318617
propagate_line_numbers(entryblock);
86328618
guarantee_lineno_for_exits(entryblock, c->u->u_firstlineno);
86338619

@@ -9323,8 +9309,8 @@ clean_basic_block(basicblock *bb) {
93239309

93249310
static int
93259311
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. */
93289314
for (int i = 0; i < bb->b_iused; i++) {
93299315
int opcode = bb->b_instr[i].i_opcode;
93309316
assert(!IS_ASSEMBLER_OPCODE(opcode));
@@ -9461,15 +9447,24 @@ propagate_line_numbers(basicblock *entryblock) {
94619447
The consts object should still be in list form to allow new constants
94629448
to be appended.
94639449
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
94669451
NOPs. Later those NOPs are removed.
94679452
*/
94689453

94699454
static int
94709455
optimize_cfg(basicblock *entryblock, PyObject *consts, PyObject *const_cache)
94719456
{
94729457
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+
}
94739468
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
94749469
if (optimize_basic_block(const_cache, b, consts)) {
94759470
return -1;

0 commit comments

Comments
 (0)