Skip to content

Commit 356a88c

Browse files
committed
Move line number propagation before optimization
1 parent f56d132 commit 356a88c

File tree

2 files changed

+39
-35
lines changed

2 files changed

+39
-35
lines changed

Lib/test/test_dis.py

+4-10
Original file line numberDiff line numberDiff line change
@@ -577,14 +577,10 @@ async def _asyncwith(c):
577577
RETURN_CONST 0 (None)
578578
579579
%4d L12: CLEANUP_THROW
580-
581-
-- L13: JUMP_BACKWARD_NO_INTERRUPT 25 (to L5)
582-
583-
%4d L14: CLEANUP_THROW
584-
585-
-- L15: JUMP_BACKWARD_NO_INTERRUPT 9 (to L11)
586-
587-
%4d L16: PUSH_EXC_INFO
580+
L13: JUMP_BACKWARD_NO_INTERRUPT 25 (to L5)
581+
L14: CLEANUP_THROW
582+
L15: JUMP_BACKWARD_NO_INTERRUPT 9 (to L11)
583+
L16: PUSH_EXC_INFO
588584
WITH_EXCEPT_START
589585
GET_AWAITABLE 2
590586
LOAD_CONST 0 (None)
@@ -630,8 +626,6 @@ async def _asyncwith(c):
630626
_asyncwith.__code__.co_firstlineno + 1,
631627
_asyncwith.__code__.co_firstlineno + 3,
632628
_asyncwith.__code__.co_firstlineno + 1,
633-
_asyncwith.__code__.co_firstlineno + 1,
634-
_asyncwith.__code__.co_firstlineno + 1,
635629
_asyncwith.__code__.co_firstlineno + 3,
636630
)
637631

Python/flowgraph.c

+35-25
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ typedef struct _PyCfgInstruction {
2929
int i_opcode;
3030
int i_oparg;
3131
_PyCompilerSrcLocation i_loc;
32+
unsigned i_loc_propagated : 1; /* location was set by propagate_line_numbers */
3233
struct _PyCfgBasicblock *i_target; /* target block (if jump instruction) */
3334
struct _PyCfgBasicblock *i_except; /* target block when exception is raised */
3435
} cfg_instr;
@@ -940,7 +941,10 @@ label_exception_targets(basicblock *entryblock) {
940941
/***** CFG optimizations *****/
941942

942943
static int
943-
mark_reachable(basicblock *entryblock) {
944+
remove_unreachable(basicblock *entryblock) {
945+
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
946+
b->b_predecessors = 0;
947+
}
944948
basicblock **stack = make_cfg_traversal_stack(entryblock);
945949
if (stack == NULL) {
946950
return ERROR;
@@ -972,6 +976,14 @@ mark_reachable(basicblock *entryblock) {
972976
}
973977
}
974978
PyMem_Free(stack);
979+
980+
/* Delete unreachable instructions */
981+
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
982+
if (b->b_predecessors == 0) {
983+
b->b_iused = 0;
984+
b->b_except_handler = 0;
985+
}
986+
}
975987
return SUCCESS;
976988
}
977989

@@ -1149,13 +1161,15 @@ jump_thread(cfg_instr *inst, cfg_instr *target, int opcode)
11491161
assert(is_jump(target));
11501162
// bpo-45773: If inst->i_target == target->i_target, then nothing actually
11511163
// changes (and we fall into an infinite loop):
1164+
if (inst->i_loc.lineno == -1) assert(inst->i_loc_propagated);
1165+
if (target->i_loc.lineno == -1) assert(target->i_loc_propagated);
11521166
if ((inst->i_loc.lineno == target->i_loc.lineno ||
1153-
inst->i_loc.lineno == -1 || target->i_loc.lineno == -1) &&
1167+
inst->i_loc_propagated || target->i_loc_propagated) &&
11541168
inst->i_target != target->i_target)
11551169
{
11561170
inst->i_target = target->i_target;
11571171
inst->i_opcode = opcode;
1158-
if (inst->i_loc.lineno == -1) {
1172+
if (inst->i_loc_propagated && !target->i_loc_propagated) {
11591173
inst->i_loc = target->i_loc;
11601174
}
11611175
return true;
@@ -1714,6 +1728,7 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
17141728
return ERROR;
17151729
}
17161730

1731+
static int resolve_line_numbers(cfg_builder *g, int firstlineno);
17171732

17181733
/* Perform optimizations on a control flow graph.
17191734
The consts object should still be in list form to allow new constants
@@ -1723,41 +1738,31 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
17231738
NOPs. Later those NOPs are removed.
17241739
*/
17251740
static int
1726-
optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache)
1741+
optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache, int firstlineno)
17271742
{
17281743
assert(PyDict_CheckExact(const_cache));
17291744
RETURN_IF_ERROR(check_cfg(g));
17301745
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
17311746
RETURN_IF_ERROR(inline_small_exit_blocks(b));
17321747
}
1748+
RETURN_IF_ERROR(remove_unreachable(g->g_entryblock));
1749+
RETURN_IF_ERROR(resolve_line_numbers(g, firstlineno));
17331750
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
17341751
RETURN_IF_ERROR(optimize_basic_block(const_cache, b, consts));
1735-
assert(b->b_predecessors == 0);
17361752
}
17371753
RETURN_IF_ERROR(remove_redundant_nops_and_pairs(g->g_entryblock));
17381754
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
17391755
RETURN_IF_ERROR(inline_small_exit_blocks(b));
17401756
}
1741-
RETURN_IF_ERROR(mark_reachable(g->g_entryblock));
1742-
1743-
/* Delete unreachable instructions */
1744-
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
1745-
if (b->b_predecessors == 0) {
1746-
b->b_iused = 0;
1747-
b->b_except_handler = 0;
1748-
}
1749-
}
1750-
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
1751-
remove_redundant_nops(b);
1752-
}
1753-
RETURN_IF_ERROR(remove_redundant_jumps(g));
1757+
RETURN_IF_ERROR(remove_unreachable(g->g_entryblock));
17541758

1755-
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
1756-
remove_redundant_nops(b);
1759+
for (int n = 0; n < 2; n++) {
1760+
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
1761+
remove_redundant_nops(b);
1762+
}
1763+
RETURN_IF_ERROR(remove_redundant_jumps(g));
17571764
}
17581765

1759-
RETURN_IF_ERROR(remove_redundant_jumps(g));
1760-
17611766
assert(no_redundant_jumps(g));
17621767
return SUCCESS;
17631768
}
@@ -2174,7 +2179,9 @@ push_cold_blocks_to_end(cfg_builder *g) {
21742179
if (!IS_LABEL(b->b_next->b_label)) {
21752180
b->b_next->b_label.id = next_lbl++;
21762181
}
2177-
basicblock_addop(explicit_jump, JUMP_NO_INTERRUPT, b->b_next->b_label.id, NO_LOCATION);
2182+
cfg_instr *prev_instr = basicblock_last_instr(b);
2183+
basicblock_addop(explicit_jump, JUMP_NO_INTERRUPT, b->b_next->b_label.id,
2184+
prev_instr->i_loc);
21782185
explicit_jump->b_cold = 1;
21792186
explicit_jump->b_next = b->b_next;
21802187
b->b_next = explicit_jump;
@@ -2345,6 +2352,7 @@ propagate_line_numbers(basicblock *entryblock) {
23452352
for (int i = 0; i < b->b_iused; i++) {
23462353
if (b->b_instr[i].i_loc.lineno < 0) {
23472354
b->b_instr[i].i_loc = prev_location;
2355+
b->b_instr[i].i_loc_propagated = 1;
23482356
}
23492357
else {
23502358
prev_location = b->b_instr[i].i_loc;
@@ -2354,6 +2362,7 @@ propagate_line_numbers(basicblock *entryblock) {
23542362
if (b->b_next->b_iused > 0) {
23552363
if (b->b_next->b_instr[0].i_loc.lineno < 0) {
23562364
b->b_next->b_instr[0].i_loc = prev_location;
2365+
b->b_next->b_instr[0].i_loc_propagated = 1;
23572366
}
23582367
}
23592368
}
@@ -2362,6 +2371,7 @@ propagate_line_numbers(basicblock *entryblock) {
23622371
if (target->b_predecessors == 1) {
23632372
if (target->b_instr[0].i_loc.lineno < 0) {
23642373
target->b_instr[0].i_loc = prev_location;
2374+
target->b_instr[0].i_loc_propagated = 1;
23652375
}
23662376
}
23672377
}
@@ -2401,7 +2411,6 @@ resolve_line_numbers(cfg_builder *g, int firstlineno)
24012411
{
24022412
RETURN_IF_ERROR(duplicate_exits_without_lineno(g));
24032413
propagate_line_numbers(g->g_entryblock);
2404-
guarantee_lineno_for_exits(g->g_entryblock, firstlineno);
24052414
return SUCCESS;
24062415
}
24072416

@@ -2417,14 +2426,15 @@ _PyCfg_OptimizeCodeUnit(cfg_builder *g, PyObject *consts, PyObject *const_cache,
24172426
RETURN_IF_ERROR(label_exception_targets(g->g_entryblock));
24182427

24192428
/** Optimization **/
2420-
RETURN_IF_ERROR(optimize_cfg(g, consts, const_cache));
2429+
RETURN_IF_ERROR(optimize_cfg(g, consts, const_cache, firstlineno));
24212430
RETURN_IF_ERROR(remove_unused_consts(g->g_entryblock, consts));
24222431
RETURN_IF_ERROR(
24232432
add_checks_for_loads_of_uninitialized_variables(
24242433
g->g_entryblock, nlocals, nparams));
24252434
insert_superinstructions(g);
24262435

24272436
RETURN_IF_ERROR(push_cold_blocks_to_end(g));
2437+
guarantee_lineno_for_exits(g->g_entryblock, firstlineno);
24282438
RETURN_IF_ERROR(resolve_line_numbers(g, firstlineno));
24292439
return SUCCESS;
24302440
}

0 commit comments

Comments
 (0)