]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-131798: JIT: Propagate the result in `_BINARY_OP_SUBSCR_TUPLE_INT` (GH-133003)
authorTomas R. <tomas.roun8@gmail.com>
Sat, 26 Apr 2025 18:47:55 +0000 (20:47 +0200)
committerGitHub <noreply@github.com>
Sat, 26 Apr 2025 18:47:55 +0000 (02:47 +0800)
Lib/test/test_capi/test_opt.py
Misc/NEWS.d/next/Core_and_Builtins/2025-04-26-13-57-13.gh-issue-131798.Gt8CGE.rst [new file with mode: 0644]
Python/optimizer_bytecodes.c
Python/optimizer_cases.c.h

index 0047306ae422dbc2d4cb68bb9b2417913fe4fe41..7e0c60d55224021017f281bfa330122bfa9a0eb3 100644 (file)
@@ -1923,6 +1923,23 @@ class TestUopsOptimization(unittest.TestCase):
         self.assertNotIn("_GUARD_TOS_INT", uops)
         self.assertIn("_CALL_LEN", uops)
 
+    def test_binary_op_subscr_tuple_int(self):
+        def testfunc(n):
+            x = 0
+            for _ in range(n):
+                y = (1, 2)
+                if y[0] == 1:  # _COMPARE_OP_INT + _GUARD_IS_TRUE_POP are removed
+                    x += 1
+            return x
+
+        res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
+        self.assertEqual(res, TIER2_THRESHOLD)
+        self.assertIsNotNone(ex)
+        uops = get_opnames(ex)
+        self.assertIn("_BINARY_OP_SUBSCR_TUPLE_INT", uops)
+        self.assertNotIn("_COMPARE_OP_INT", uops)
+        self.assertNotIn("_GUARD_IS_TRUE_POP", uops)
+
 
 def global_identity(x):
     return x
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-04-26-13-57-13.gh-issue-131798.Gt8CGE.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-26-13-57-13.gh-issue-131798.Gt8CGE.rst
new file mode 100644 (file)
index 0000000..f404924
--- /dev/null
@@ -0,0 +1,2 @@
+Propagate the return type of ``_BINARY_OP_SUBSCR_TUPLE_INT`` in JIT. Patch
+by Tomas Roun
index 040e54479b722a90d71715d24e8cd4b555d4563c..f862c9c8c6a840a30c9b76da6d7db7a925f15dfd 100644 (file)
@@ -370,6 +370,27 @@ dummy_func(void) {
         res = sym_new_type(ctx, &PyUnicode_Type);
     }
 
+    op(_BINARY_OP_SUBSCR_TUPLE_INT, (tuple_st, sub_st -- res)) {
+        assert(sym_matches_type(tuple_st, &PyTuple_Type));
+        if (sym_is_const(ctx, sub_st)) {
+            assert(PyLong_CheckExact(sym_get_const(ctx, sub_st)));
+            long index = PyLong_AsLong(sym_get_const(ctx, sub_st));
+            assert(index >= 0);
+            int tuple_length = sym_tuple_length(tuple_st);
+            if (tuple_length == -1) {
+                // Unknown length
+                res = sym_new_not_null(ctx);
+            }
+            else {
+                assert(index < tuple_length);
+                res = sym_tuple_getitem(ctx, tuple_st, index);
+            }
+        }
+        else {
+            res = sym_new_not_null(ctx);
+        }
+    }
+
     op(_TO_BOOL, (value -- res)) {
         int already_bool = optimize_to_bool(this_instr, ctx, value, &res);
         if (!already_bool) {
index 9a5a362ec199a992dc47edd47594d3ec4ba984e2..c92b036eb56463569ba8bdb2ea7610c5dd7ca29d 100644 (file)
         }
 
         case _BINARY_OP_SUBSCR_TUPLE_INT: {
+            JitOptSymbol *sub_st;
+            JitOptSymbol *tuple_st;
             JitOptSymbol *res;
-            res = sym_new_not_null(ctx);
+            sub_st = stack_pointer[-1];
+            tuple_st = stack_pointer[-2];
+            assert(sym_matches_type(tuple_st, &PyTuple_Type));
+            if (sym_is_const(ctx, sub_st)) {
+                assert(PyLong_CheckExact(sym_get_const(ctx, sub_st)));
+                long index = PyLong_AsLong(sym_get_const(ctx, sub_st));
+                assert(index >= 0);
+                int tuple_length = sym_tuple_length(tuple_st);
+                if (tuple_length == -1) {
+                    res = sym_new_not_null(ctx);
+                }
+                else {
+                    assert(index < tuple_length);
+                    res = sym_tuple_getitem(ctx, tuple_st, index);
+                }
+            }
+            else {
+                res = sym_new_not_null(ctx);
+            }
             stack_pointer[-2] = res;
             stack_pointer += -1;
             assert(WITHIN_STACK_BOUNDS());