summaryrefslogtreecommitdiffstats
path: root/Python/compile.c
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2005-02-20 12:41:32 (GMT)
committerRaymond Hettinger <python@rcn.com>2005-02-20 12:41:32 (GMT)
commit80121491e083a3e80d482f73d201590083285d57 (patch)
tree2b4326c876501e6dad7b91dfefeec607c6626bd4 /Python/compile.c
parent57e7447c447249a33a13da853f8c1bfec546842a (diff)
downloadcpython-80121491e083a3e80d482f73d201590083285d57.zip
cpython-80121491e083a3e80d482f73d201590083285d57.tar.gz
cpython-80121491e083a3e80d482f73d201590083285d57.tar.bz2
Teach the peepholer to fold unary operations on constants.
Afterwards, -0.5 loads in a single step and no longer requires a runtime UNARY_NEGATIVE operation.
Diffstat (limited to 'Python/compile.c')
-rw-r--r--Python/compile.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/Python/compile.c b/Python/compile.c
index c1c2fa9..b458f73 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -542,6 +542,54 @@ fold_binops_on_constants(unsigned char *codestr, PyObject *consts)
return 1;
}
+static int
+fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts)
+{
+ PyObject *newconst, *v;
+ int len_consts, opcode;
+
+ /* Pre-conditions */
+ assert(PyList_CheckExact(consts));
+ assert(codestr[0] == LOAD_CONST);
+
+ /* Create new constant */
+ v = PyList_GET_ITEM(consts, GETARG(codestr, 0));
+ opcode = codestr[3];
+ switch (opcode) {
+ case UNARY_NEGATIVE:
+ newconst = PyNumber_Negative(v);
+ break;
+ case UNARY_CONVERT:
+ newconst = PyObject_Repr(v);
+ break;
+ case UNARY_INVERT:
+ newconst = PyNumber_Invert(v);
+ break;
+ default:
+ /* Called with an unknown opcode */
+ assert(0);
+ return 0;
+ }
+ if (newconst == NULL) {
+ PyErr_Clear();
+ return 0;
+ }
+
+ /* Append folded constant into consts table */
+ len_consts = PyList_GET_SIZE(consts);
+ if (PyList_Append(consts, newconst)) {
+ Py_DECREF(newconst);
+ return 0;
+ }
+ Py_DECREF(newconst);
+
+ /* Write NOP LOAD_CONST newconst */
+ codestr[0] = NOP;
+ codestr[1] = LOAD_CONST;
+ SETARG(codestr, 1, len_consts);
+ return 1;
+}
+
static unsigned int *
markblocks(unsigned char *code, int len)
{
@@ -771,6 +819,20 @@ optimize_code(PyObject *code, PyObject* consts, PyObject *names, PyObject *linen
}
break;
+ /* Fold unary ops on constants.
+ LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */
+ case UNARY_NEGATIVE:
+ case UNARY_CONVERT:
+ case UNARY_INVERT:
+ if (lastlc >= 1 &&
+ ISBASICBLOCK(blocks, i-3, 4) &&
+ fold_unaryops_on_constants(&codestr[i-3], consts)) {
+ i -= 2;
+ assert(codestr[i] == LOAD_CONST);
+ cumlc = 1;
+ }
+ break;
+
/* Simplify conditional jump to conditional jump where the
result of the first test implies the success of a similar
test or the failure of the opposite test.