From a059e85866adb8ccd98d216b78428eb37fa70509 Mon Sep 17 00:00:00 2001 From: Wulian233 <1055917385@qq.com> Date: Sat, 11 Apr 2026 23:02:46 +0800 Subject: [PATCH] gh-131798: Add `_IS_NONE` to the JIT optimizer (GH-148369) --- Lib/test/test_capi/test_opt.py | 18 ++++++++++++++++++ Python/optimizer_bytecodes.c | 10 ++++++++++ Python/optimizer_cases.c.h | 10 +++++++++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 6d8ad8798de5..f11413cc6254 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -4662,6 +4662,24 @@ class TestUopsOptimization(unittest.TestCase): # v + 1 should be constant folded self.assertNotIn("_BINARY_OP", uops) + def test_is_none_narrows_to_constant(self): + def testfunc(n): + value = None + hits = 0 + for _ in range(n): + if value is None: + hits += 1 + return hits + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + + self.assertNotIn("_IS_NONE", uops) + self.assertIn("_GUARD_IS_NONE_POP", uops) + self.assertIn("_POP_TOP_NOP", uops) + def test_is_false_narrows_to_constant(self): def f(n): def return_false(): diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 9b1a69649978..c7fe34bf785c 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -724,6 +724,16 @@ dummy_func(void) { r = right; } + op(_IS_NONE, (value -- b)) { + if (sym_is_const(ctx, value)) { + PyObject *value_o = sym_get_const(ctx, value); + b = sym_new_const(ctx, Py_IsNone(value_o) ? Py_True : Py_False); + } + else { + b = sym_new_type(ctx, &PyBool_Type); + } + } + op(_CONTAINS_OP, (left, right -- b, l, r)) { b = sym_new_type(ctx, &PyBool_Type); l = left; diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index e5c67b6cf0e3..98287e7f8417 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -3193,8 +3193,16 @@ /* _POP_JUMP_IF_TRUE is not a viable micro-op for tier 2 */ case _IS_NONE: { + JitOptRef value; JitOptRef b; - b = sym_new_not_null(ctx); + value = stack_pointer[-1]; + if (sym_is_const(ctx, value)) { + PyObject *value_o = sym_get_const(ctx, value); + b = sym_new_const(ctx, Py_IsNone(value_o) ? Py_True : Py_False); + } + else { + b = sym_new_type(ctx, &PyBool_Type); + } stack_pointer[-1] = b; break; } -- 2.47.3