[Python-checkins] python/dist/src/Python compile.c,2.337,2.338

rhettinger at users.sourceforge.net rhettinger at users.sourceforge.net
Sun Jan 2 07:17:37 CET 2005


Update of /cvsroot/python/python/dist/src/Python
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7497/Python

Modified Files:
	compile.c 
Log Message:
Teach the peephole optimizer to fold simple constant expressions.

Index: compile.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v
retrieving revision 2.337
retrieving revision 2.338
diff -u -d -r2.337 -r2.338
--- compile.c	7 Nov 2004 14:04:00 -0000	2.337
+++ compile.c	2 Jan 2005 06:17:33 -0000	2.338
@@ -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.



More information about the Python-checkins mailing list