mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 19:34:08 +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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 *
 | 
			
		||||
markblocks(unsigned char *code, int len)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -771,6 +819,20 @@ optimize_code(PyObject *code, PyObject* consts, PyObject *names, PyObject *linen
 | 
			
		|||
			}
 | 
			
		||||
			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
 | 
			
		||||
		   result of the first test implies the success of a similar
 | 
			
		||||
		   test or the failure of the opposite test.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue