Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9c18e81

Browse files
committed
Install two code generation optimizations that depend on NOP.
Reduces the cost of "not" to almost zero.
1 parent 2c9f889 commit 9c18e81

4 files changed

Lines changed: 35 additions & 3 deletions

File tree

Include/opcode.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ extern "C" {
1313
#define ROT_THREE 3
1414
#define DUP_TOP 4
1515
#define ROT_FOUR 5
16+
#define NOP 9
1617

1718
#define UNARY_POSITIVE 10
1819
#define UNARY_NEGATIVE 11

Lib/opcode.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ def jabs_op(name, op):
4949
def_op('DUP_TOP', 4)
5050
def_op('ROT_FOUR', 5)
5151

52+
def_op('NOP', 9)
5253
def_op('UNARY_POSITIVE', 10)
5354
def_op('UNARY_NEGATIVE', 11)
5455
def_op('UNARY_NOT', 12)

Python/ceval.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,9 @@ eval_frame(PyFrameObject *f)
849849

850850
/* case STOP_CODE: this is an error! */
851851

852+
case NOP:
853+
goto fast_next_opcode;
854+
852855
case LOAD_FAST:
853856
x = GETLOCAL(oparg);
854857
if (x != NULL) {

Python/compile.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,33 @@ optimize_code(PyObject *code, PyObject* consts)
392392
opcode = codestr[i];
393393
switch (opcode) {
394394

395+
/* Replace UNARY_NOT JUMP_IF_FALSE with NOP JUMP_IF_TRUE */
396+
case UNARY_NOT:
397+
if (codestr[i+1] != JUMP_IF_FALSE ||
398+
codestr[i+4] != POP_TOP ||
399+
!ISBASICBLOCK(blocks,i,5))
400+
continue;
401+
tgt = GETJUMPTGT(codestr, (i+1));
402+
if (codestr[tgt] != POP_TOP)
403+
continue;
404+
codestr[i] = NOP;
405+
codestr[i+1] = JUMP_IF_TRUE;
406+
break;
407+
408+
/* not a is b --> a is not b
409+
not a in b --> a not in b
410+
not a is not b --> a is b
411+
not a not in b --> a in b */
412+
case COMPARE_OP:
413+
j = GETARG(codestr, i);
414+
if (j < 6 || j > 9 ||
415+
codestr[i+3] != UNARY_NOT ||
416+
!ISBASICBLOCK(blocks,i,4))
417+
continue;
418+
SETARG(codestr, i, (j^1));
419+
codestr[i+3] = NOP;
420+
break;
421+
395422
/* Skip over LOAD_CONST trueconst JUMP_IF_FALSE xx POP_TOP.
396423
Note, only the first opcode is changed, the others still
397424
perform normally if they happen to be jump targets. */
@@ -418,8 +445,8 @@ optimize_code(PyObject *code, PyObject* consts)
418445
codestr[i] = ROT_TWO;
419446
codestr[i+1] = JUMP_FORWARD;
420447
SETARG(codestr, i+1, 2);
421-
codestr[i+4] = DUP_TOP; /* Filler codes used as NOPs */
422-
codestr[i+5] = POP_TOP;
448+
codestr[i+4] = NOP;
449+
codestr[i+5] = NOP;
423450
continue;
424451
}
425452
if (GETARG(codestr, i) == 3 && \
@@ -428,7 +455,7 @@ optimize_code(PyObject *code, PyObject* consts)
428455
codestr[i+1] = ROT_TWO;
429456
codestr[i+2] = JUMP_FORWARD;
430457
SETARG(codestr, i+2, 1);
431-
codestr[i+5] = DUP_TOP;
458+
codestr[i+5] = NOP;
432459
}
433460
break;
434461

0 commit comments

Comments
 (0)