]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-104635: Eliminate redundant STORE_FAST instructions in the compiler (gh-105320)
authorDong-hee Na <donghee.na@python.org>
Wed, 7 Jun 2023 23:39:56 +0000 (08:39 +0900)
committerGitHub <noreply@github.com>
Wed, 7 Jun 2023 23:39:56 +0000 (08:39 +0900)
Lib/test/test_dis.py
Lib/test/test_peepholer.py
Misc/NEWS.d/next/Core and Builtins/2023-06-05-23-38-43.gh-issue-104635.VYZhVh.rst [new file with mode: 0644]
Python/flowgraph.c

index 28da3fd8cf5e222a19dd251b420e665f0ba6a01b..cb35175d2069026e598041b7176386744e8aa903 100644 (file)
@@ -808,8 +808,9 @@ dis_extended_arg_quick_code = """\
 %3d           2 LOAD_CONST               1 (Ellipsis)
               4 EXTENDED_ARG             1
               6 UNPACK_EX              256
-              8 STORE_FAST_STORE_FAST     0 (_, _)
-             10 RETURN_CONST             0 (None)
+              8 POP_TOP
+             10 STORE_FAST               0 (_)
+             12 RETURN_CONST             0 (None)
 """% (extended_arg_quick.__code__.co_firstlineno,
       extended_arg_quick.__code__.co_firstlineno + 1,)
 
index c57016bb108f0a5f8c5174add2c78ee21f5bb5ec..82b0b50d0ea4374b331600a7a7df72f8a47f838b 100644 (file)
@@ -1075,15 +1075,47 @@ class DirectCfgOptimizerTests(CfgOptimizationTestCase):
             ('RETURN_VALUE', 5)
         ]
         expected_insts = [
+            ('LOAD_CONST', 0, 1),
+            ('LOAD_CONST', 1, 2),
+            ('NOP', 0, 3),
+            ('STORE_FAST', 1, 4),
+            ('POP_TOP', 0, 4),
+            ('RETURN_VALUE', 5)
+        ]
+        self.cfg_optimization_test(insts, expected_insts, consts=list(range(3)), nlocals=1)
+
+    def test_dead_store_elimination_in_same_lineno(self):
+        insts = [
             ('LOAD_CONST', 0, 1),
             ('LOAD_CONST', 1, 2),
             ('LOAD_CONST', 2, 3),
-            ('SWAP', 3, 4),
-            ('STORE_FAST_STORE_FAST', 17, 4),
+            ('STORE_FAST', 1, 4),
+            ('STORE_FAST', 1, 4),
+            ('STORE_FAST', 1, 4),
+            ('RETURN_VALUE', 5)
+        ]
+        expected_insts = [
+            ('LOAD_CONST', 0, 1),
+            ('LOAD_CONST', 1, 2),
+            ('NOP', 0, 3),
             ('POP_TOP', 0, 4),
+            ('STORE_FAST', 1, 4),
             ('RETURN_VALUE', 5)
         ]
         self.cfg_optimization_test(insts, expected_insts, consts=list(range(3)), nlocals=1)
 
+    def test_no_dead_store_elimination_in_different_lineno(self):
+        insts = [
+            ('LOAD_CONST', 0, 1),
+            ('LOAD_CONST', 1, 2),
+            ('LOAD_CONST', 2, 3),
+            ('STORE_FAST', 1, 4),
+            ('STORE_FAST', 1, 5),
+            ('STORE_FAST', 1, 6),
+            ('RETURN_VALUE', 5)
+        ]
+        self.cfg_optimization_test(insts, insts, consts=list(range(3)), nlocals=1)
+
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-06-05-23-38-43.gh-issue-104635.VYZhVh.rst b/Misc/NEWS.d/next/Core and Builtins/2023-06-05-23-38-43.gh-issue-104635.VYZhVh.rst
new file mode 100644 (file)
index 0000000..f20ddb5
--- /dev/null
@@ -0,0 +1,2 @@
+Eliminate redundant :opcode:`STORE_FAST` instructions in the compiler. Patch
+by Dong-hee Na and Carl Meyer.
index 2fd9a85b6d9570fc3402fed5eaa676f0c9e5b016..b16b508fe76f758a7d2b042f53b5b337266fa548 100644 (file)
@@ -1515,15 +1515,18 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
                     */
                 }
                 break;
+            case STORE_FAST:
+                if (opcode == nextop &&
+                    oparg == bb->b_instr[i+1].i_oparg &&
+                    bb->b_instr[i].i_loc.lineno == bb->b_instr[i+1].i_loc.lineno) {
+                    bb->b_instr[i].i_opcode = POP_TOP;
+                    bb->b_instr[i].i_oparg = 0;
+                }
+                break;
             case SWAP:
                 if (oparg == 1) {
                     INSTR_SET_OP0(inst, NOP);
-                    break;
-                }
-                if (swaptimize(bb, &i) < 0) {
-                    goto error;
                 }
-                apply_static_swaps(bb, i);
                 break;
             case KW_NAMES:
                 break;
@@ -1538,6 +1541,16 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
                 assert (!HAS_CONST(inst->i_opcode));
         }
     }
+
+    for (int i = 0; i < bb->b_iused; i++) {
+        cfg_instr *inst = &bb->b_instr[i];
+        if (inst->i_opcode == SWAP) {
+            if (swaptimize(bb, &i) < 0) {
+                goto error;
+            }
+            apply_static_swaps(bb, i);
+        }
+    }
     return SUCCESS;
 error:
     return ERROR;