Skip to content

Commit 21866c8

Browse files
authored
gh-120367: fix removal of redundant NOPs and jumps after reordering hot-cold blocks (#120425)
1 parent c2d5df5 commit 21866c8

File tree

3 files changed

+47
-12
lines changed

3 files changed

+47
-12
lines changed

Lib/test/test_compile.py

+27
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,33 @@ def test_compile_invalid_namedexpr(self):
502502
with self.assertRaisesRegex(TypeError, "NamedExpr target must be a Name"):
503503
compile(ast.fix_missing_locations(m), "<file>", "exec")
504504

505+
def test_compile_redundant_jumps_and_nops_after_moving_cold_blocks(self):
506+
# See gh-120367
507+
code=textwrap.dedent("""
508+
try:
509+
pass
510+
except:
511+
pass
512+
else:
513+
match name_2:
514+
case b'':
515+
pass
516+
finally:
517+
something
518+
""")
519+
520+
tree = ast.parse(code)
521+
522+
# make all instructions locations the same to create redundancies
523+
for node in ast.walk(tree):
524+
if hasattr(node,"lineno"):
525+
del node.lineno
526+
del node.end_lineno
527+
del node.col_offset
528+
del node.end_col_offset
529+
530+
compile(ast.fix_missing_locations(tree), "<file>", "exec")
531+
505532
def test_compile_ast(self):
506533
fname = __file__
507534
if fname.lower().endswith('pyc'):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix crash in compiler on code with redundant NOPs and JUMPs which show up
2+
after exception handlers are moved to the end of the code.

Python/flowgraph.c

+18-12
Original file line numberDiff line numberDiff line change
@@ -1857,6 +1857,22 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
18571857

18581858
static int resolve_line_numbers(cfg_builder *g, int firstlineno);
18591859

1860+
static int
1861+
remove_redundant_nops_and_jumps(cfg_builder *g)
1862+
{
1863+
int removed_nops, removed_jumps;
1864+
do {
1865+
/* Convergence is guaranteed because the number of
1866+
* redundant jumps and nops only decreases.
1867+
*/
1868+
removed_nops = remove_redundant_nops(g);
1869+
RETURN_IF_ERROR(removed_nops);
1870+
removed_jumps = remove_redundant_jumps(g);
1871+
RETURN_IF_ERROR(removed_jumps);
1872+
} while(removed_nops + removed_jumps > 0);
1873+
return SUCCESS;
1874+
}
1875+
18601876
/* Perform optimizations on a control flow graph.
18611877
The consts object should still be in list form to allow new constants
18621878
to be appended.
@@ -1878,17 +1894,7 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache, int firstl
18781894
}
18791895
RETURN_IF_ERROR(remove_redundant_nops_and_pairs(g->g_entryblock));
18801896
RETURN_IF_ERROR(remove_unreachable(g->g_entryblock));
1881-
1882-
int removed_nops, removed_jumps;
1883-
do {
1884-
/* Convergence is guaranteed because the number of
1885-
* redundant jumps and nops only decreases.
1886-
*/
1887-
removed_nops = remove_redundant_nops(g);
1888-
RETURN_IF_ERROR(removed_nops);
1889-
removed_jumps = remove_redundant_jumps(g);
1890-
RETURN_IF_ERROR(removed_jumps);
1891-
} while(removed_nops + removed_jumps > 0);
1897+
RETURN_IF_ERROR(remove_redundant_nops_and_jumps(g));
18921898
assert(no_redundant_jumps(g));
18931899
return SUCCESS;
18941900
}
@@ -2358,7 +2364,7 @@ push_cold_blocks_to_end(cfg_builder *g) {
23582364
b->b_next = cold_blocks;
23592365

23602366
if (cold_blocks != NULL) {
2361-
RETURN_IF_ERROR(remove_redundant_jumps(g));
2367+
RETURN_IF_ERROR(remove_redundant_nops_and_jumps(g));
23622368
}
23632369
return SUCCESS;
23642370
}

0 commit comments

Comments
 (0)