gh-120367: fix removal of redundant NOPs and jumps after reordering hot-cold blocks (#120425)

This commit is contained in:
Irit Katriel 2024-06-17 11:10:06 +01:00 committed by GitHub
parent c2d5df5787
commit 21866c8ed2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 47 additions and 12 deletions

View file

@ -502,6 +502,33 @@ def test_compile_invalid_namedexpr(self):
with self.assertRaisesRegex(TypeError, "NamedExpr target must be a Name"):
compile(ast.fix_missing_locations(m), "<file>", "exec")
def test_compile_redundant_jumps_and_nops_after_moving_cold_blocks(self):
# See gh-120367
code=textwrap.dedent("""
try:
pass
except:
pass
else:
match name_2:
case b'':
pass
finally:
something
""")
tree = ast.parse(code)
# make all instructions locations the same to create redundancies
for node in ast.walk(tree):
if hasattr(node,"lineno"):
del node.lineno
del node.end_lineno
del node.col_offset
del node.end_col_offset
compile(ast.fix_missing_locations(tree), "<file>", "exec")
def test_compile_ast(self):
fname = __file__
if fname.lower().endswith('pyc'):

View file

@ -0,0 +1,2 @@
Fix crash in compiler on code with redundant NOPs and JUMPs which show up
after exception handlers are moved to the end of the code.

View file

@ -1857,6 +1857,22 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
static int resolve_line_numbers(cfg_builder *g, int firstlineno);
static int
remove_redundant_nops_and_jumps(cfg_builder *g)
{
int removed_nops, removed_jumps;
do {
/* Convergence is guaranteed because the number of
* redundant jumps and nops only decreases.
*/
removed_nops = remove_redundant_nops(g);
RETURN_IF_ERROR(removed_nops);
removed_jumps = remove_redundant_jumps(g);
RETURN_IF_ERROR(removed_jumps);
} while(removed_nops + removed_jumps > 0);
return SUCCESS;
}
/* Perform optimizations on a control flow graph.
The consts object should still be in list form to allow new constants
to be appended.
@ -1878,17 +1894,7 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache, int firstl
}
RETURN_IF_ERROR(remove_redundant_nops_and_pairs(g->g_entryblock));
RETURN_IF_ERROR(remove_unreachable(g->g_entryblock));
int removed_nops, removed_jumps;
do {
/* Convergence is guaranteed because the number of
* redundant jumps and nops only decreases.
*/
removed_nops = remove_redundant_nops(g);
RETURN_IF_ERROR(removed_nops);
removed_jumps = remove_redundant_jumps(g);
RETURN_IF_ERROR(removed_jumps);
} while(removed_nops + removed_jumps > 0);
RETURN_IF_ERROR(remove_redundant_nops_and_jumps(g));
assert(no_redundant_jumps(g));
return SUCCESS;
}
@ -2358,7 +2364,7 @@ push_cold_blocks_to_end(cfg_builder *g) {
b->b_next = cold_blocks;
if (cold_blocks != NULL) {
RETURN_IF_ERROR(remove_redundant_jumps(g));
RETURN_IF_ERROR(remove_redundant_nops_and_jumps(g));
}
return SUCCESS;
}