]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Install two code generation optimizations that depend on NOP.
authorRaymond Hettinger <python@rcn.com>
Mon, 21 Jun 2004 16:31:15 +0000 (16:31 +0000)
committerRaymond Hettinger <python@rcn.com>
Mon, 21 Jun 2004 16:31:15 +0000 (16:31 +0000)
Reduces the cost of "not" to almost zero.

Include/opcode.h
Lib/opcode.py
Python/ceval.c
Python/compile.c

index 8df96b4f224fb2c3b27d4ac225def38df65e44c9..868512fe8de13d1f6122cb8a903d3edffd3a5427 100644 (file)
@@ -13,6 +13,7 @@ extern "C" {
 #define ROT_THREE      3
 #define DUP_TOP                4
 #define ROT_FOUR       5
+#define NOP            9
 
 #define UNARY_POSITIVE 10
 #define UNARY_NEGATIVE 11
index ae9f6ccf13f8219e16a7973f7b3e0356b70080ff..9517c4314a3bb4b14d1412c16f783b02a0192bb7 100644 (file)
@@ -49,6 +49,7 @@ def_op('ROT_THREE', 3)
 def_op('DUP_TOP', 4)
 def_op('ROT_FOUR', 5)
 
+def_op('NOP', 9)
 def_op('UNARY_POSITIVE', 10)
 def_op('UNARY_NEGATIVE', 11)
 def_op('UNARY_NOT', 12)
index f66e318f5819c79b83fbeeffe2831e55e84edb59..088c8814ed8423d0b2797c59334efde4f6a86ff5 100644 (file)
@@ -849,6 +849,9 @@ eval_frame(PyFrameObject *f)
 
                /* case STOP_CODE: this is an error! */
 
+               case NOP:
+                       goto fast_next_opcode;
+
                case LOAD_FAST:
                        x = GETLOCAL(oparg);
                        if (x != NULL) {
index dd80ae4e715d028f813eee84abceb66ae6c141be..ab4b533b6baecde150b8aa61ad937c282e4f8d82 100644 (file)
@@ -392,6 +392,33 @@ optimize_code(PyObject *code, PyObject* consts)
                opcode = codestr[i];
                switch (opcode) {
 
+               /* Replace UNARY_NOT JUMP_IF_FALSE with NOP JUMP_IF_TRUE */
+               case UNARY_NOT:
+                       if (codestr[i+1] != JUMP_IF_FALSE  ||
+                           codestr[i+4] != POP_TOP  ||
+                           !ISBASICBLOCK(blocks,i,5))
+                               continue;
+                       tgt = GETJUMPTGT(codestr, (i+1));
+                       if (codestr[tgt] != POP_TOP)
+                               continue;
+                       codestr[i] = NOP;
+                       codestr[i+1] = JUMP_IF_TRUE;
+                       break;
+
+               /* not a is b -->  a is not b
+                  not a in b -->  a not in b
+                  not a is not b -->  a is b
+                  not a not in b -->  a in b */
+               case COMPARE_OP:
+                       j = GETARG(codestr, i);
+                       if (j < 6  ||  j > 9  ||
+                           codestr[i+3] != UNARY_NOT  || 
+                           !ISBASICBLOCK(blocks,i,4))
+                        continue;
+                       SETARG(codestr, i, (j^1));
+                       codestr[i+3] = NOP;
+                       break;
+
                /* Skip over LOAD_CONST trueconst  JUMP_IF_FALSE xx  POP_TOP. 
                   Note, only the first opcode is changed, the others still
                   perform normally if they happen to be jump targets. */
@@ -418,8 +445,8 @@ optimize_code(PyObject *code, PyObject* consts)
                                codestr[i] = ROT_TWO;
                                codestr[i+1] = JUMP_FORWARD;
                                SETARG(codestr, i+1, 2);
-                               codestr[i+4] = DUP_TOP;  /* Filler codes used as NOPs */
-                               codestr[i+5] = POP_TOP;
+                               codestr[i+4] = NOP;
+                               codestr[i+5] = NOP;
                                continue;
                        } 
                        if (GETARG(codestr, i) == 3 && \
@@ -428,7 +455,7 @@ optimize_code(PyObject *code, PyObject* consts)
                                codestr[i+1] = ROT_TWO;
                                codestr[i+2] = JUMP_FORWARD;
                                SETARG(codestr, i+2, 1);
-                               codestr[i+5] = DUP_TOP;
+                               codestr[i+5] = NOP;
                        }
                        break;