Created
June 27, 2017 20:56
Add COMPARE_IS_NONE opcode to CPython for performance
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
b66bbc41ce52efe667af0ba47a6098216b758236 | |
diff --git a/Include/opcode.h b/Include/opcode.h | |
index 99c3b0ef81..dceedc662a 100644 | |
--- a/Include/opcode.h | |
+++ b/Include/opcode.h | |
@@ -12,6 +12,8 @@ extern "C" { | |
#define ROT_THREE 3 | |
#define DUP_TOP 4 | |
#define DUP_TOP_TWO 5 | |
+#define COMPARE_IS_NONE 6 | |
+#define COMPARE_IS_NOT_NONE 7 | |
#define NOP 9 | |
#define UNARY_POSITIVE 10 | |
#define UNARY_NEGATIVE 11 | |
diff --git a/Lib/opcode.py b/Lib/opcode.py | |
index dffb38c314..53fac107c1 100644 | |
--- a/Lib/opcode.py | |
+++ b/Lib/opcode.py | |
@@ -60,6 +60,8 @@ def_op('ROT_TWO', 2) | |
def_op('ROT_THREE', 3) | |
def_op('DUP_TOP', 4) | |
def_op('DUP_TOP_TWO', 5) | |
+def_op('COMPARE_IS_NONE', 6) | |
+def_op('COMPARE_IS_NOT_NONE', 7) | |
def_op('NOP', 9) | |
def_op('UNARY_POSITIVE', 10) | |
diff --git a/Python/ceval.c b/Python/ceval.c | |
index 3243a4f8a0..40d697c193 100644 | |
--- a/Python/ceval.c | |
+++ b/Python/ceval.c | |
@@ -1235,6 +1235,28 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) | |
FAST_DISPATCH(); | |
} | |
+ TARGET(COMPARE_IS_NONE) { | |
+ PyObject *top = TOP(); | |
+ PyObject *res = (top == Py_None) ? Py_True : Py_False; | |
+ Py_INCREF(res); | |
+ Py_DECREF(top); | |
+ SET_TOP(res); | |
+ PREDICT(POP_JUMP_IF_FALSE); | |
+ PREDICT(POP_JUMP_IF_TRUE); | |
+ DISPATCH(); | |
+ } | |
+ | |
+ TARGET(COMPARE_IS_NOT_NONE) { | |
+ PyObject *top = TOP(); | |
+ PyObject *res = (top != Py_None) ? Py_True : Py_False; | |
+ Py_INCREF(res); | |
+ Py_DECREF(top); | |
+ SET_TOP(res); | |
+ PREDICT(POP_JUMP_IF_FALSE); | |
+ PREDICT(POP_JUMP_IF_TRUE); | |
+ DISPATCH(); | |
+ } | |
+ | |
TARGET(UNARY_POSITIVE) { | |
PyObject *value = TOP(); | |
PyObject *res = PyNumber_Positive(value); | |
diff --git a/Python/compile.c b/Python/compile.c | |
index 280ddc39e3..8fc39d092e 100644 | |
--- a/Python/compile.c | |
+++ b/Python/compile.c | |
@@ -867,6 +867,10 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg) | |
case DUP_TOP_TWO: | |
return 2; | |
+ case COMPARE_IS_NONE: | |
+ case COMPARE_IS_NOT_NONE: | |
+ return 0; | |
+ | |
case UNARY_POSITIVE: | |
case UNARY_NEGATIVE: | |
case UNARY_NOT: | |
@@ -3419,6 +3423,24 @@ compiler_compare(struct compiler *c, expr_ty e) | |
VISIT(c, expr, e->v.Compare.left); | |
n = asdl_seq_LEN(e->v.Compare.ops); | |
assert(n > 0); | |
+ | |
+ if (n == 1) { | |
+ cmpop_ty cmp = (cmpop_ty)asdl_seq_GET(e->v.Compare.ops, 0); | |
+ expr_ty exp = (expr_ty)asdl_seq_GET(e->v.Compare.comparators, 0); | |
+ if (exp->kind == NameConstant_kind && exp->v.NameConstant.value == Py_None) { | |
+ if (cmp == Is) { | |
+ ADDOP(c, COMPARE_IS_NONE); | |
+ return 1; | |
+ } else if (cmp == IsNot) { | |
+ ADDOP(c, COMPARE_IS_NOT_NONE); | |
+ return 1; | |
+ } | |
+ } | |
+ VISIT(c, expr, exp); | |
+ ADDOP_I(c, COMPARE_OP, cmpop(cmp)); | |
+ return 1; | |
+ } | |
+ | |
if (n > 1) { | |
cleanup = compiler_new_block(c); | |
if (cleanup == NULL) | |
diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h | |
index 567f8723a6..d2156ca154 100644 | |
--- a/Python/opcode_targets.h | |
+++ b/Python/opcode_targets.h | |
@@ -5,8 +5,8 @@ static void *opcode_targets[256] = { | |
&&TARGET_ROT_THREE, | |
&&TARGET_DUP_TOP, | |
&&TARGET_DUP_TOP_TWO, | |
- &&_unknown_opcode, | |
- &&_unknown_opcode, | |
+ &&TARGET_COMPARE_IS_NONE, | |
+ &&TARGET_COMPARE_IS_NOT_NONE, | |
&&_unknown_opcode, | |
&&TARGET_NOP, | |
&&TARGET_UNARY_POSITIVE, |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment