Skip to content

Commit 8781a04

Browse files
authored
gh-92782: unify the style of CFG traversal algorithms in the compiler (GH-92784)
1 parent 93fc149 commit 8781a04

File tree

1 file changed

+45
-38
lines changed

1 file changed

+45
-38
lines changed

Python/compile.c

+45-38
Original file line numberDiff line numberDiff line change
@@ -7061,7 +7061,6 @@ struct assembler {
70617061
PyObject *a_except_table; /* bytes containing exception table */
70627062
basicblock *a_entry;
70637063
int a_offset; /* offset into bytecode */
7064-
int a_nblocks; /* number of reachable blocks */
70657064
int a_except_table_off; /* offset into exception table */
70667065
int a_prevlineno; /* lineno of last emitted line in line table */
70677066
int a_prev_end_lineno; /* end_lineno of last emitted line in line table */
@@ -7074,6 +7073,20 @@ struct assembler {
70747073
int a_location_off; /* offset of last written location info frame */
70757074
};
70767075

7076+
static basicblock**
7077+
make_cfg_traversal_stack(basicblock *entry) {
7078+
int nblocks = 0;
7079+
for (basicblock *b = entry; b != NULL; b = b->b_next) {
7080+
b->b_visited = 0;
7081+
nblocks++;
7082+
}
7083+
basicblock **stack = (basicblock **)PyMem_Malloc(sizeof(basicblock *) * nblocks);
7084+
if (!stack) {
7085+
PyErr_NoMemory();
7086+
}
7087+
return stack;
7088+
}
7089+
70777090
Py_LOCAL_INLINE(void)
70787091
stackdepth_push(basicblock ***sp, basicblock *b, int depth)
70797092
{
@@ -7089,31 +7102,26 @@ stackdepth_push(basicblock ***sp, basicblock *b, int depth)
70897102
* cycles in the flow graph have no net effect on the stack depth.
70907103
*/
70917104
static int
7092-
stackdepth(struct compiler *c)
7105+
stackdepth(struct compiler *c, basicblock *entry)
70937106
{
7094-
basicblock *b, *entryblock = NULL;
7095-
basicblock **stack, **sp;
7096-
int nblocks = 0, maxdepth = 0;
7097-
for (b = c->u->u_blocks; b != NULL; b = b->b_list) {
7107+
for (basicblock *b = entry; b != NULL; b = b->b_next) {
70987108
b->b_startdepth = INT_MIN;
7099-
entryblock = b;
7100-
nblocks++;
71017109
}
7102-
assert(entryblock!= NULL);
7103-
stack = (basicblock **)PyObject_Malloc(sizeof(basicblock *) * nblocks);
7110+
basicblock **stack = make_cfg_traversal_stack(entry);
71047111
if (!stack) {
7105-
PyErr_NoMemory();
71067112
return -1;
71077113
}
71087114

7109-
sp = stack;
7115+
int maxdepth = 0;
7116+
basicblock **sp = stack;
71107117
if (c->u->u_ste->ste_generator || c->u->u_ste->ste_coroutine) {
7111-
stackdepth_push(&sp, entryblock, 1);
7118+
stackdepth_push(&sp, entry, 1);
71127119
} else {
7113-
stackdepth_push(&sp, entryblock, 0);
7120+
stackdepth_push(&sp, entry, 0);
71147121
}
7122+
71157123
while (sp != stack) {
7116-
b = *--sp;
7124+
basicblock *b = *--sp;
71177125
int depth = b->b_startdepth;
71187126
assert(depth >= 0);
71197127
basicblock *next = b->b_next;
@@ -7159,7 +7167,7 @@ stackdepth(struct compiler *c)
71597167
stackdepth_push(&sp, next, depth);
71607168
}
71617169
}
7162-
PyObject_Free(stack);
7170+
PyMem_Free(stack);
71637171
return maxdepth;
71647172
}
71657173

@@ -7264,14 +7272,8 @@ copy_except_stack(ExceptStack *stack) {
72647272

72657273
static int
72667274
label_exception_targets(basicblock *entry) {
7267-
int nblocks = 0;
7268-
for (basicblock *b = entry; b != NULL; b = b->b_next) {
7269-
b->b_visited = 0;
7270-
nblocks++;
7271-
}
7272-
basicblock **todo_stack = PyMem_Malloc(sizeof(basicblock *)*nblocks);
7275+
basicblock **todo_stack = make_cfg_traversal_stack(entry);
72737276
if (todo_stack == NULL) {
7274-
PyErr_NoMemory();
72757277
return -1;
72767278
}
72777279
ExceptStack *except_stack = make_except_stack();
@@ -8051,7 +8053,7 @@ static int
80518053
optimize_cfg(struct compiler *c, struct assembler *a, PyObject *consts);
80528054

80538055
static int
8054-
trim_unused_consts(struct compiler *c, struct assembler *a, PyObject *consts);
8056+
trim_unused_consts(struct assembler *a, PyObject *consts);
80558057

80568058
/* Duplicates exit BBs, so that line numbers can be propagated to them */
80578059
static int
@@ -8347,7 +8349,6 @@ assemble(struct compiler *c, int addNone)
83478349
if (!assemble_init(&a, nblocks, c->u->u_firstlineno))
83488350
goto error;
83498351
a.a_entry = entryblock;
8350-
a.a_nblocks = nblocks;
83518352

83528353
int numdropped = fix_cell_offsets(c, entryblock, cellfixedoffsets);
83538354
PyMem_Free(cellfixedoffsets); // At this point we're done with it.
@@ -8368,12 +8369,12 @@ assemble(struct compiler *c, int addNone)
83688369
if (duplicate_exits_without_lineno(c)) {
83698370
return NULL;
83708371
}
8371-
if (trim_unused_consts(c, &a, consts)) {
8372+
if (trim_unused_consts(&a, consts)) {
83728373
goto error;
83738374
}
83748375
propagate_line_numbers(&a);
83758376
guarantee_lineno_for_exits(&a, c->u->u_firstlineno);
8376-
int maxdepth = stackdepth(c);
8377+
int maxdepth = stackdepth(c, entryblock);
83778378
if (maxdepth < 0) {
83788379
goto error;
83798380
}
@@ -9081,17 +9082,19 @@ normalize_basic_block(basicblock *bb) {
90819082

90829083
static int
90839084
mark_reachable(struct assembler *a) {
9084-
basicblock **stack, **sp;
9085-
sp = stack = (basicblock **)PyObject_Malloc(sizeof(basicblock *) * a->a_nblocks);
9085+
basicblock **stack = make_cfg_traversal_stack(a->a_entry);
90869086
if (stack == NULL) {
90879087
return -1;
90889088
}
9089+
basicblock **sp = stack;
90899090
a->a_entry->b_predecessors = 1;
90909091
*sp++ = a->a_entry;
90919092
while (sp > stack) {
90929093
basicblock *b = *(--sp);
9094+
b->b_visited = 1;
90939095
if (b->b_next && !b->b_nofallthrough) {
9094-
if (b->b_next->b_predecessors == 0) {
9096+
if (!b->b_next->b_visited) {
9097+
assert(b->b_next->b_predecessors == 0);
90959098
*sp++ = b->b_next;
90969099
}
90979100
b->b_next->b_predecessors++;
@@ -9101,14 +9104,15 @@ mark_reachable(struct assembler *a) {
91019104
struct instr *instr = &b->b_instr[i];
91029105
if (is_jump(instr) || is_block_push(instr)) {
91039106
target = instr->i_target;
9104-
if (target->b_predecessors == 0) {
9107+
if (!target->b_visited) {
9108+
assert(target->b_predecessors == 0 || target == b->b_next);
91059109
*sp++ = target;
91069110
}
91079111
target->b_predecessors++;
91089112
}
91099113
}
91109114
}
9111-
PyObject_Free(stack);
9115+
PyMem_Free(stack);
91129116
return 0;
91139117
}
91149118

@@ -9128,12 +9132,15 @@ eliminate_empty_basic_blocks(basicblock *entry) {
91289132
if (b->b_iused == 0) {
91299133
continue;
91309134
}
9131-
if (is_jump(&b->b_instr[b->b_iused-1])) {
9132-
basicblock *target = b->b_instr[b->b_iused-1].i_target;
9133-
while (target->b_iused == 0) {
9134-
target = target->b_next;
9135+
for (int i = 0; i < b->b_iused; i++) {
9136+
struct instr *instr = &b->b_instr[i];
9137+
if (is_jump(instr) || is_block_push(instr)) {
9138+
basicblock *target = instr->i_target;
9139+
while (target->b_iused == 0) {
9140+
target = target->b_next;
9141+
}
9142+
instr->i_target = target;
91359143
}
9136-
b->b_instr[b->b_iused-1].i_target = target;
91379144
}
91389145
}
91399146
}
@@ -9253,7 +9260,7 @@ optimize_cfg(struct compiler *c, struct assembler *a, PyObject *consts)
92539260

92549261
// Remove trailing unused constants.
92559262
static int
9256-
trim_unused_consts(struct compiler *c, struct assembler *a, PyObject *consts)
9263+
trim_unused_consts(struct assembler *a, PyObject *consts)
92579264
{
92589265
assert(PyList_CheckExact(consts));
92599266

0 commit comments

Comments
 (0)