Kaydet (Commit) 9c18e81f authored tarafından Raymond Hettinger's avatar Raymond Hettinger

Install two code generation optimizations that depend on NOP.

Reduces the cost of "not" to almost zero.
üst 2c9f8891
...@@ -13,6 +13,7 @@ extern "C" { ...@@ -13,6 +13,7 @@ extern "C" {
#define ROT_THREE 3 #define ROT_THREE 3
#define DUP_TOP 4 #define DUP_TOP 4
#define ROT_FOUR 5 #define ROT_FOUR 5
#define NOP 9
#define UNARY_POSITIVE 10 #define UNARY_POSITIVE 10
#define UNARY_NEGATIVE 11 #define UNARY_NEGATIVE 11
......
...@@ -49,6 +49,7 @@ def_op('ROT_THREE', 3) ...@@ -49,6 +49,7 @@ def_op('ROT_THREE', 3)
def_op('DUP_TOP', 4) def_op('DUP_TOP', 4)
def_op('ROT_FOUR', 5) def_op('ROT_FOUR', 5)
def_op('NOP', 9)
def_op('UNARY_POSITIVE', 10) def_op('UNARY_POSITIVE', 10)
def_op('UNARY_NEGATIVE', 11) def_op('UNARY_NEGATIVE', 11)
def_op('UNARY_NOT', 12) def_op('UNARY_NOT', 12)
......
...@@ -849,6 +849,9 @@ eval_frame(PyFrameObject *f) ...@@ -849,6 +849,9 @@ eval_frame(PyFrameObject *f)
/* case STOP_CODE: this is an error! */ /* case STOP_CODE: this is an error! */
case NOP:
goto fast_next_opcode;
case LOAD_FAST: case LOAD_FAST:
x = GETLOCAL(oparg); x = GETLOCAL(oparg);
if (x != NULL) { if (x != NULL) {
......
...@@ -392,6 +392,33 @@ optimize_code(PyObject *code, PyObject* consts) ...@@ -392,6 +392,33 @@ optimize_code(PyObject *code, PyObject* consts)
opcode = codestr[i]; opcode = codestr[i];
switch (opcode) { 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. /* Skip over LOAD_CONST trueconst JUMP_IF_FALSE xx POP_TOP.
Note, only the first opcode is changed, the others still Note, only the first opcode is changed, the others still
perform normally if they happen to be jump targets. */ perform normally if they happen to be jump targets. */
...@@ -418,8 +445,8 @@ optimize_code(PyObject *code, PyObject* consts) ...@@ -418,8 +445,8 @@ optimize_code(PyObject *code, PyObject* consts)
codestr[i] = ROT_TWO; codestr[i] = ROT_TWO;
codestr[i+1] = JUMP_FORWARD; codestr[i+1] = JUMP_FORWARD;
SETARG(codestr, i+1, 2); SETARG(codestr, i+1, 2);
codestr[i+4] = DUP_TOP; /* Filler codes used as NOPs */ codestr[i+4] = NOP;
codestr[i+5] = POP_TOP; codestr[i+5] = NOP;
continue; continue;
} }
if (GETARG(codestr, i) == 3 && \ if (GETARG(codestr, i) == 3 && \
...@@ -428,7 +455,7 @@ optimize_code(PyObject *code, PyObject* consts) ...@@ -428,7 +455,7 @@ optimize_code(PyObject *code, PyObject* consts)
codestr[i+1] = ROT_TWO; codestr[i+1] = ROT_TWO;
codestr[i+2] = JUMP_FORWARD; codestr[i+2] = JUMP_FORWARD;
SETARG(codestr, i+2, 1); SETARG(codestr, i+2, 1);
codestr[i+5] = DUP_TOP; codestr[i+5] = NOP;
} }
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment