]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-106529: Generate uops for POP_JUMP_IF_[NOT_]NONE (#106796)
authorGuido van Rossum <guido@python.org>
Mon, 17 Jul 2023 17:06:05 +0000 (10:06 -0700)
committerGitHub <noreply@github.com>
Mon, 17 Jul 2023 17:06:05 +0000 (10:06 -0700)
These aren't automatically translated because (ironically)
they are macros deferring to POP_JUMP_IF_{TRUE,FALSE},
which are not viable uops (being manually translated).

The hack is that we emit IS_NONE and then set opcode and
jump to the POP_JUMP_IF_{TRUE,FALSE} translation code.

Lib/test/test_capi/test_misc.py
Python/optimizer.c

index 6df918997b2b19118cf9a7bece3f9d5602b3427f..c0dcff825758ad7a0778465c600e7a0090646514 100644 (file)
@@ -2532,6 +2532,36 @@ class TestUops(unittest.TestCase):
         uops = {opname for opname, _ in ex}
         self.assertIn("_POP_JUMP_IF_FALSE", uops)
 
+    def test_pop_jump_if_none(self):
+        def testfunc(a):
+            for x in a:
+                if x is None:
+                    x = 0
+
+        opt = _testinternalcapi.get_uop_optimizer()
+        with temporary_optimizer(opt):
+            testfunc([1, 2, 3])
+
+        ex = get_first_executor(testfunc)
+        self.assertIsNotNone(ex)
+        uops = {opname for opname, _ in ex}
+        self.assertIn("_POP_JUMP_IF_TRUE", uops)
+
+    def test_pop_jump_if_not_none(self):
+        def testfunc(a):
+            for x in a:
+                if x is not None:
+                    x = 0
+
+        opt = _testinternalcapi.get_uop_optimizer()
+        with temporary_optimizer(opt):
+            testfunc([1, 2, 3])
+
+        ex = get_first_executor(testfunc)
+        self.assertIsNotNone(ex)
+        uops = {opname for opname, _ in ex}
+        self.assertIn("_POP_JUMP_IF_FALSE", uops)
+
     def test_pop_jump_if_true(self):
         def testfunc(n):
             i = 0
index 289b202f806ae1f8f7e2d244862f0773df23a943..693ba375971ae76c09167dc978f33911fb2ac3f1 100644 (file)
@@ -464,9 +464,26 @@ translate_bytecode_to_trace(
 
         switch (opcode) {
 
+            case POP_JUMP_IF_NONE:
+            {
+                RESERVE(2, 2);
+                ADD_TO_TRACE(IS_NONE, 0);
+                opcode = POP_JUMP_IF_TRUE;
+                goto pop_jump_if_bool;
+            }
+
+            case POP_JUMP_IF_NOT_NONE:
+            {
+                RESERVE(2, 2);
+                ADD_TO_TRACE(IS_NONE, 0);
+                opcode = POP_JUMP_IF_FALSE;
+                goto pop_jump_if_bool;
+            }
+
             case POP_JUMP_IF_FALSE:
             case POP_JUMP_IF_TRUE:
             {
+pop_jump_if_bool:
                 // Assume jump unlikely (TODO: handle jump likely case)
                 RESERVE(1, 2);
                 _Py_CODEUNIT *target_instr =