mirror of
https://github.com/python/cpython.git
synced 2025-11-01 18:51:43 +00:00
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.
This commit is contained in:
parent
57e7447c44
commit
80121491e0
1 changed files with 62 additions and 0 deletions
|
|
@ -542,6 +542,54 @@ fold_binops_on_constants(unsigned char *codestr, PyObject *consts)
|
||||||
return 1;
|
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 *
|
static unsigned int *
|
||||||
markblocks(unsigned char *code, int len)
|
markblocks(unsigned char *code, int len)
|
||||||
{
|
{
|
||||||
|
|
@ -771,6 +819,20 @@ optimize_code(PyObject *code, PyObject* consts, PyObject *names, PyObject *linen
|
||||||
}
|
}
|
||||||
break;
|
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
|
/* Simplify conditional jump to conditional jump where the
|
||||||
result of the first test implies the success of a similar
|
result of the first test implies the success of a similar
|
||||||
test or the failure of the opposite test.
|
test or the failure of the opposite test.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue