From: Sacul <183588943+Sacul0457@users.noreply.github.com> Date: Tue, 17 Mar 2026 14:07:17 +0000 (+0800) Subject: gh-131798: Optimize `_ITER_CHECK_RANGE` and `_ITER_CHECK_LIST` in the JIT (GH-144583) X-Git-Tag: v3.15.0a8~276 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1efd9939c8742a251f232f09ccd0c1def7fda66e;p=thirdparty%2FPython%2Fcpython.git gh-131798: Optimize `_ITER_CHECK_RANGE` and `_ITER_CHECK_LIST` in the JIT (GH-144583) --- diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 1385a7f840d7..2a126a7b29cc 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -3981,6 +3981,22 @@ class TestUopsOptimization(unittest.TestCase): self.assertIn("_POP_TOP_NOP", uops) self.assertLessEqual(count_ops(ex, "_POP_TOP"), 2) + def test_iter_check_list(self): + def testfunc(n): + x = 0 + for _ in range(n): + l = [1] + for num in l: # unguarded + x += num + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + uops = get_opnames(ex) + + self.assertIn("_BUILD_LIST", uops) + self.assertNotIn("_ITER_CHECK_LIST", uops) + def test_match_class(self): def testfunc(n): class A: diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-08-01-19-50.gh-issue-131798.PaWDNH.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-08-01-19-50.gh-issue-131798.PaWDNH.rst new file mode 100644 index 000000000000..fe80c2d911b6 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-08-01-19-50.gh-issue-131798.PaWDNH.rst @@ -0,0 +1 @@ +Optimize ``_ITER_CHECK_RANGE`` and ``_ITER_CHECK_LIST`` in the JIT diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index f3a391b2e37e..9b77fd0c32d9 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -1091,6 +1091,24 @@ dummy_func(void) { sym_set_type(iter, &PyTuple_Type); } + op(_ITER_CHECK_LIST, (iter, null_or_index -- iter, null_or_index)) { + if (sym_matches_type(iter, &PyList_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(iter, &PyList_Type); + } + } + + op(_ITER_CHECK_RANGE, (iter, null_or_index -- iter, null_or_index)) { + if (sym_matches_type(iter, &PyRange_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(iter, &PyRange_Type); + } + } + op(_ITER_NEXT_RANGE, (iter, null_or_index -- iter, null_or_index, next)) { next = sym_new_type(ctx, &PyLong_Type); } diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 52a0c08ac677..eef07cedaf38 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -2752,6 +2752,14 @@ /* _INSTRUMENTED_FOR_ITER is not a viable micro-op for tier 2 */ case _ITER_CHECK_LIST: { + JitOptRef iter; + iter = stack_pointer[-2]; + if (sym_matches_type(iter, &PyList_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(iter, &PyList_Type); + } break; } @@ -2800,6 +2808,14 @@ } case _ITER_CHECK_RANGE: { + JitOptRef iter; + iter = stack_pointer[-2]; + if (sym_matches_type(iter, &PyRange_Type)) { + ADD_OP(_NOP, 0, 0); + } + else { + sym_set_type(iter, &PyRange_Type); + } break; }