Skip to content

Commit 61a2229

Browse files
[3.13] gh-120367: fix removal of redundant NOPs and jumps after reordering hot-cold blocks (GH-120425) (#120621)
gh-120367: fix removal of redundant NOPs and jumps after reordering hot-cold blocks (GH-120425) (cherry picked from commit 21866c8) Co-authored-by: Irit Katriel <[email protected]>
1 parent 7c47f93 commit 61a2229

File tree

3 files changed

+47
-12
lines changed

3 files changed

+47
-12
lines changed

Lib/test/test_compile.py

Lines changed: 27 additions & 0 deletions
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'):
Lines changed: 2 additions & 0 deletions
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

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1829,6 +1829,22 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
18291829

18301830
static int resolve_line_numbers(cfg_builder *g, int firstlineno);
18311831

1832+
static int
1833+
remove_redundant_nops_and_jumps(cfg_builder *g)
1834+
{
1835+
int removed_nops, removed_jumps;
1836+
do {
1837+
/* Convergence is guaranteed because the number of
1838+
* redundant jumps and nops only decreases.
1839+
*/
1840+
removed_nops = remove_redundant_nops(g);
1841+
RETURN_IF_ERROR(removed_nops);
1842+
removed_jumps = remove_redundant_jumps(g);
1843+
RETURN_IF_ERROR(removed_jumps);
1844+
} while(removed_nops + removed_jumps > 0);
1845+
return SUCCESS;
1846+
}
1847+
18321848
/* Perform optimizations on a control flow graph.
18331849
The consts object should still be in list form to allow new constants
18341850
to be appended.
@@ -1850,17 +1866,7 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache, int firstl
18501866
}
18511867
RETURN_IF_ERROR(remove_redundant_nops_and_pairs(g->g_entryblock));
18521868
RETURN_IF_ERROR(remove_unreachable(g->g_entryblock));
1853-
1854-
int removed_nops, removed_jumps;
1855-
do {
1856-
/* Convergence is guaranteed because the number of
1857-
* redundant jumps and nops only decreases.
1858-
*/
1859-
removed_nops = remove_redundant_nops(g);
1860-
RETURN_IF_ERROR(removed_nops);
1861-
removed_jumps = remove_redundant_jumps(g);
1862-
RETURN_IF_ERROR(removed_jumps);
1863-
} while(removed_nops + removed_jumps > 0);
1869+
RETURN_IF_ERROR(remove_redundant_nops_and_jumps(g));
18641870
assert(no_redundant_jumps(g));
18651871
return SUCCESS;
18661872
}
@@ -2330,7 +2336,7 @@ push_cold_blocks_to_end(cfg_builder *g) {
23302336
b->b_next = cold_blocks;
23312337

23322338
if (cold_blocks != NULL) {
2333-
RETURN_IF_ERROR(remove_redundant_jumps(g));
2339+
RETURN_IF_ERROR(remove_redundant_nops_and_jumps(g));
23342340
}
23352341
return SUCCESS;
23362342
}

0 commit comments

Comments
 (0)