[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

AltStyle によって変換されたページ (->オリジナル) /