diff options
author | Raymond Hettinger <python@rcn.com> | 2004-06-21 16:31:15 (GMT) |
---|---|---|
committer | Raymond Hettinger <python@rcn.com> | 2004-06-21 16:31:15 (GMT) |
commit | 9c18e81fb23d60ea77bdf4f3c2649296f26e4a95 (patch) | |
tree | b0a494cfa23bf97cbbd52019328a22c32db9e524 | |
parent | 2c9f889122b48395c1997b08dd328f33f64f1ecd (diff) | |
download | cpython-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.h | 1 | ||||
-rw-r--r-- | Lib/opcode.py | 1 | ||||
-rw-r--r-- | Python/ceval.c | 3 | ||||
-rw-r--r-- | Python/compile.c | 33 |
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; |