summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2004-06-21 16:31:15 (GMT)
committerRaymond Hettinger <python@rcn.com>2004-06-21 16:31:15 (GMT)
commit9c18e81fb23d60ea77bdf4f3c2649296f26e4a95 (patch)
treeb0a494cfa23bf97cbbd52019328a22c32db9e524
parent2c9f889122b48395c1997b08dd328f33f64f1ecd (diff)
downloadcpython-9c18e81fb23d60ea77bdf4f3c2649296f26e4a95.zip
cpython-9c18e81fb23d60ea77bdf4f3c2649296f26e4a95.tar.gz
cpython-9c18e81fb23d60ea77bdf4f3c2649296f26e4a95.tar.bz2
Install two code generation optimizations that depend on NOP.
Reduces the cost of "not" to almost zero.
-rw-r--r--Include/opcode.h1
-rw-r--r--Lib/opcode.py1
-rw-r--r--Python/ceval.c3
-rw-r--r--Python/compile.c33
4 files changed, 35 insertions, 3 deletions
diff --git a/Include/opcode.h b/Include/opcode.h
index 8df96b4..868512f 100644
--- a/Include/opcode.h
+++ b/Include/opcode.h
@@ -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
diff --git a/Lib/opcode.py b/Lib/opcode.py
index ae9f6cc..9517c43 100644
--- a/Lib/opcode.py
+++ b/Lib/opcode.py
@@ -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)
diff --git a/Python/ceval.c b/Python/ceval.c
index f66e318..088c881 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -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) {
diff --git a/Python/compile.c b/Python/compile.c
index dd80ae4..ab4b533 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -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;