diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index 28748009f731bc..34bc3e19c9cb85 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -2525,8 +2525,8 @@ def test_unoptimized_if_unconsumed(self): ] expected = [ ("LOAD_FAST", 0, 1), - ("LOAD_FAST_BORROW", 1, 2), - ("POP_TOP", None, 3), + ("NOP", None, 2), + ("NOP", None, 3), ] self.check(insts, expected) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-07-25-18-05-19.gh-issue-152600._TEXv2.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-07-25-18-05-19.gh-issue-152600._TEXv2.rst new file mode 100644 index 00000000000000..c8a7fd0cdadfba --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-07-25-18-05-19.gh-issue-152600._TEXv2.rst @@ -0,0 +1,2 @@ +Now, :opcode:`LOAD_FAST`; :opcode:`POP_TOP`, and :opcode:`LOAD_FAST_BORROW`; +:opcode:`POP_TOP` pairs become :opcode:`NOPs `. diff --git a/Python/flowgraph.c b/Python/flowgraph.c index f135f243c74e2f..72ba500464ede1 100644 --- a/Python/flowgraph.c +++ b/Python/flowgraph.c @@ -1157,6 +1157,9 @@ remove_redundant_nops_and_pairs(basicblock *entryblock) else if (prev_opcode == COPY && prev_oparg == 1) { is_redundant_pair = true; } + else if (prev_opcode == LOAD_FAST) { + is_redundant_pair = true; + } } if (is_redundant_pair) { INSTR_SET_OP0(prev_instr, NOP); @@ -2635,9 +2638,14 @@ remove_redundant_nops_and_jumps(cfg_builder *g) Code trasnformations that reduce code size initially fill the gaps with NOPs. Later those NOPs are removed. */ + +static int +add_checks_for_loads_of_uninitialized_variables(basicblock *entryblock, + int nlocals, int nparams); + static int optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache, - _Py_hashtable_t *consts_index, int firstlineno) + _Py_hashtable_t *consts_index, int firstlineno, int nlocals, int nparams) { assert(PyDict_CheckExact(const_cache)); RETURN_IF_ERROR(check_cfg(g)); @@ -2648,6 +2656,9 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache, for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { RETURN_IF_ERROR(optimize_basic_block(const_cache, b, consts, consts_index)); } + RETURN_IF_ERROR( + add_checks_for_loads_of_uninitialized_variables( + g->g_entryblock, nlocals, nparams)); RETURN_IF_ERROR(remove_redundant_nops_and_pairs(g->g_entryblock)); RETURN_IF_ERROR(remove_unreachable(g->g_entryblock)); RETURN_IF_ERROR(remove_redundant_nops_and_jumps(g)); @@ -3790,16 +3801,13 @@ _PyCfg_OptimizeCodeUnit(cfg_builder *g, PyObject *consts, PyObject *const_cache, } } - int ret = optimize_cfg(g, consts, const_cache, consts_index, firstlineno); + int ret = optimize_cfg(g, consts, const_cache, consts_index, firstlineno, nlocals, nparams); _Py_hashtable_destroy(consts_index); RETURN_IF_ERROR(ret); RETURN_IF_ERROR(remove_unused_consts(g->g_entryblock, consts)); - RETURN_IF_ERROR( - add_checks_for_loads_of_uninitialized_variables( - g->g_entryblock, nlocals, nparams)); RETURN_IF_ERROR(insert_superinstructions(g)); RETURN_IF_ERROR(push_cold_blocks_to_end(g));