]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] gh-112356: LOAD_GLOBAL can only include one PUSH_NULL (#112566)
authorDennis Sweeney <36520290+sweeneyde@users.noreply.github.com>
Fri, 1 Dec 2023 00:35:49 +0000 (19:35 -0500)
committerGitHub <noreply@github.com>
Fri, 1 Dec 2023 00:35:49 +0000 (00:35 +0000)
Lib/test/test_peepholer.py
Misc/NEWS.d/next/Core and Builtins/2023-11-30-23-47-56.gh-issue-112356.g2BqyK.rst [new file with mode: 0644]
Python/flowgraph.c

index 0aabce880053d6ded29f6a507ea9fa69372e1edb..02e43d1579a1a91ce5eb0591ee0d9e2fc780c08b 100644 (file)
@@ -1075,5 +1075,26 @@ class DirectCfgOptimizerTests(CfgOptimizationTestCase):
         ]
         self.cfg_optimization_test(insts, insts, consts=list(range(3)), nlocals=1)
 
+    def test_only_one_push_null_per_load_global(self):
+        # When optimizing func()(), a second pass shouldn't
+        # let the LOAD_GLOBAL absorb another PUSH_NULL.
+        before = [
+            ('PUSH_NULL', 0, 1),
+            ('PUSH_NULL', 0, 1),
+            ('LOAD_GLOBAL', 0, 1),
+            ('CALL', 0, 1),
+            ('CALL', 0, 1),
+            ('RETURN_VALUE', 0, 1),
+        ]
+        after = [
+            ('PUSH_NULL', 0, 1),
+            ('LOAD_GLOBAL', 1, 1),
+            ('CALL', 0, 1),
+            ('CALL', 0, 1),
+            ('RETURN_VALUE', 0, 1),
+        ]
+        self.cfg_optimization_test(before, expected_insts=after, consts=[])
+        self.cfg_optimization_test(after, expected_insts=after, consts=[])
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-11-30-23-47-56.gh-issue-112356.g2BqyK.rst b/Misc/NEWS.d/next/Core and Builtins/2023-11-30-23-47-56.gh-issue-112356.g2BqyK.rst
new file mode 100644 (file)
index 0000000..0bb8eaf
--- /dev/null
@@ -0,0 +1 @@
+Stopped erroneously deleting a ``LOAD_NULL`` bytecode instruction when optimized twice.
index afcae317403ef270c5c58465397bc0aef10f4031..b53e771bb7bb1e40675bcf8291b14d5335a4568f 100644 (file)
@@ -1554,9 +1554,9 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
             case KW_NAMES:
                 break;
             case PUSH_NULL:
-                if (nextop == LOAD_GLOBAL && (inst[1].i_opcode & 1) == 0) {
+                if (nextop == LOAD_GLOBAL && (bb->b_instr[i+1].i_oparg & 1) == 0) {
                     INSTR_SET_OP0(inst, NOP);
-                    inst[1].i_oparg |= 1;
+                    bb->b_instr[i+1].i_oparg |= 1;
                 }
                 break;
             default: