Mercurial > cpython-lru_cache-weakref
diff Python/compile.c @ 34305:0c326327e722 legacy-trunk
Teach the peephole optimizer to fold simple constant expressions.
| author | Raymond Hettinger <python@rcn.com> |
|---|---|
| date | Sun, 02 Jan 2005 06:17:33 +0000 |
| parents | e4404046e552 |
| children | d81b6173f050 |
line wrap: on
line diff
--- a/Python/compile.c Sat Jan 01 22:33:36 2005 +0000 +++ b/Python/compile.c Sun Jan 02 06:17:33 2005 +0000 @@ -439,6 +439,99 @@ return 1; } +/* Replace LOAD_CONST c1. LOAD_CONST c2 BINOP + with LOAD_CONST binop(c1,c2) + The consts table must still be in list form so that the + new constant can be appended. + Called with codestr pointing to the first LOAD_CONST. + Abandons the transformation if the folding fails (i.e. 1+'a'). */ +static int +fold_binops_on_constants(unsigned char *codestr, PyObject *consts) +{ + PyObject *newconst, *v, *w; + int len_consts, opcode; + + /* Pre-conditions */ + assert(PyList_CheckExact(consts)); + assert(codestr[0] == LOAD_CONST); + assert(codestr[3] == LOAD_CONST); + + /* Create new constant */ + v = PyList_GET_ITEM(consts, GETARG(codestr, 0)); + w = PyList_GET_ITEM(consts, GETARG(codestr, 3)); + opcode = codestr[6]; + switch (opcode) { + case BINARY_POWER: + newconst = PyNumber_Power(v, w, Py_None); + break; + case BINARY_MULTIPLY: + newconst = PyNumber_Multiply(v, w); + break; + case BINARY_DIVIDE: + if (!_Py_QnewFlag) { + newconst = PyNumber_Divide(v, w); + break; + } + /* -Qnew is in effect: fall through to + BINARY_TRUE_DIVIDE */ + case BINARY_TRUE_DIVIDE: + newconst = PyNumber_TrueDivide(v, w); + break; + case BINARY_FLOOR_DIVIDE: + newconst = PyNumber_FloorDivide(v, w); + break; + case BINARY_MODULO: + newconst = PyNumber_Remainder(v, w); + break; + case BINARY_ADD: + newconst = PyNumber_Add(v, w); + break; + case BINARY_SUBTRACT: + newconst = PyNumber_Subtract(v, w); + break; + case BINARY_SUBSCR: + newconst = PyObject_GetItem(v, w); + break; + case BINARY_LSHIFT: + newconst = PyNumber_Lshift(v, w); + break; + case BINARY_RSHIFT: + newconst = PyNumber_Rshift(v, w); + break; + case BINARY_AND: + newconst = PyNumber_And(v, w); + break; + case BINARY_XOR: + newconst = PyNumber_Xor(v, w); + break; + case BINARY_OR: + newconst = PyNumber_Or(v, w); + 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 NOP NOP NOP LOAD_CONST newconst */ + memset(codestr, NOP, 4); + codestr[4] = LOAD_CONST; + SETARG(codestr, 4, len_consts); + return 1; +} + static unsigned int * markblocks(unsigned char *code, int len) { @@ -614,7 +707,6 @@ h = i - 3 * j; if (h >= 0 && j <= lastlc && - codestr[h] == LOAD_CONST && ISBASICBLOCK(blocks, h, 3*(j+1)) && tuple_of_constants(&codestr[h], j, consts)) { assert(codestr[i] == LOAD_CONST); @@ -640,6 +732,31 @@ } break; + /* Fold binary ops on constants. + LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */ + case BINARY_POWER: + case BINARY_MULTIPLY: + case BINARY_DIVIDE: + case BINARY_TRUE_DIVIDE: + case BINARY_FLOOR_DIVIDE: + case BINARY_MODULO: + case BINARY_ADD: + case BINARY_SUBTRACT: + case BINARY_SUBSCR: + case BINARY_LSHIFT: + case BINARY_RSHIFT: + case BINARY_AND: + case BINARY_XOR: + case BINARY_OR: + if (lastlc >= 2 && + ISBASICBLOCK(blocks, i-6, 7) && + fold_binops_on_constants(&codestr[i-6], 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.
