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

Skip to content

Commit 8012149

Browse files
committed
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.
1 parent 57e7447 commit 8012149

1 file changed

Lines changed: 62 additions & 0 deletions

File tree

Python/compile.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,54 @@ fold_binops_on_constants(unsigned char *codestr, PyObject *consts)
542542
return 1;
543543
}
544544

545+
static int
546+
fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts)
547+
{
548+
PyObject *newconst, *v;
549+
int len_consts, opcode;
550+
551+
/* Pre-conditions */
552+
assert(PyList_CheckExact(consts));
553+
assert(codestr[0] == LOAD_CONST);
554+
555+
/* Create new constant */
556+
v = PyList_GET_ITEM(consts, GETARG(codestr, 0));
557+
opcode = codestr[3];
558+
switch (opcode) {
559+
case UNARY_NEGATIVE:
560+
newconst = PyNumber_Negative(v);
561+
break;
562+
case UNARY_CONVERT:
563+
newconst = PyObject_Repr(v);
564+
break;
565+
case UNARY_INVERT:
566+
newconst = PyNumber_Invert(v);
567+
break;
568+
default:
569+
/* Called with an unknown opcode */
570+
assert(0);
571+
return 0;
572+
}
573+
if (newconst == NULL) {
574+
PyErr_Clear();
575+
return 0;
576+
}
577+
578+
/* Append folded constant into consts table */
579+
len_consts = PyList_GET_SIZE(consts);
580+
if (PyList_Append(consts, newconst)) {
581+
Py_DECREF(newconst);
582+
return 0;
583+
}
584+
Py_DECREF(newconst);
585+
586+
/* Write NOP LOAD_CONST newconst */
587+
codestr[0] = NOP;
588+
codestr[1] = LOAD_CONST;
589+
SETARG(codestr, 1, len_consts);
590+
return 1;
591+
}
592+
545593
static unsigned int *
546594
markblocks(unsigned char *code, int len)
547595
{
@@ -771,6 +819,20 @@ optimize_code(PyObject *code, PyObject* consts, PyObject *names, PyObject *linen
771819
}
772820
break;
773821

822+
/* Fold unary ops on constants.
823+
LOAD_CONST c1 UNARY_OP --> LOAD_CONST unary_op(c) */
824+
case UNARY_NEGATIVE:
825+
case UNARY_CONVERT:
826+
case UNARY_INVERT:
827+
if (lastlc >= 1 &&
828+
ISBASICBLOCK(blocks, i-3, 4) &&
829+
fold_unaryops_on_constants(&codestr[i-3], consts)) {
830+
i -= 2;
831+
assert(codestr[i] == LOAD_CONST);
832+
cumlc = 1;
833+
}
834+
break;
835+
774836
/* Simplify conditional jump to conditional jump where the
775837
result of the first test implies the success of a similar
776838
test or the failure of the opposite test.

0 commit comments

Comments
 (0)