Example #1
0
/*
 *	calculate addressability as follows
 *		REGISTER ==> 12		register
 *		NAME ==> 11		name+value(SB/SP)
 *			note that 10 is no longer generated
 *		CONST ==> 20		$value
 *		*(20) ==> 21		value
 *		&(10) ==> 12		$name+value(SB)
 *		&(11) ==> 1		$name+value(SP)
 *		(12) + (20) ==> 12	fold constants
 *		(1) + (20) ==> 1	fold constants
 *		*(12) ==> 10		back to name
 *		*(1) ==> 11		back to name
 *
 *		(2,10,11) + (20) ==> 2	indirect w offset
 *		(2) ==> &13
 *		*(10,11) ==> 13		indirect, no index
 *
 *		(20) * (X) ==> 7	multiplier in indexing
 *		(X,7) + (12,1) ==> 8	adder in indexing (addresses)
 *		(X,7) + (10,11,2) ==> 8	adder in indexing (names)
 *		(8) ==> &9		index, almost addressable
 *
 *		(X)++ ==> X		fake addressability
 *
 *	calculate complexity (number of registers)
 */
void
xcom(Node *n)
{
	Node *l, *r;
	int g;

	if(n == Z)
		return;
	l = n->left;
	r = n->right;
	n->complex = 0;
	n->addable = 0;
	switch(n->op) {
	case OCONST:
		n->addable = 20;
		break;

	case ONAME:
		n->addable = 11;	/* difference to make relocatable */
		break;

	case OREGISTER:
		n->addable = 12;
		break;

	case OADDR:
		xcom(l);
		if(l->addable == 10)
			n->addable = 12;
		else
		if(l->addable == 11)
			n->addable = 1;
		break;

	case OADD:
		xcom(l);
		xcom(r);
		if(n->type->etype != TIND)
			break;

		if(l->addable == 20)
		switch(r->addable) {
		case 12:
		case 1:
			n->addable = r->addable;
			goto brk;
		}
		if(r->addable == 20)
		switch(l->addable) {
		case 12:
		case 1:
			n->addable = l->addable;
			goto brk;
		}
		break;

	case OIND:
		xcom(l);
		if(l->op == OADDR) {
			l = l->left;
			l->type = n->type;
			*n = *l;
			return;
		}
		switch(l->addable) {
		case 20:
			n->addable = 21;
			break;
		case 1:
			n->addable = 11;
			break;
		case 12:
			n->addable = 10;
			break;
		}
		break;

	case OASHL:
		xcom(l);
		xcom(r);
		if(typev[n->type->etype])
			break;
		g = vconst(r);
		if(g >= 0 && g < 4)
			n->addable = 7;
		break;

	case OMUL:
	case OLMUL:
		xcom(l);
		xcom(r);
		if(typev[n->type->etype])
			break;
		g = vlog(r);
		if(g >= 0) {
			n->op = OASHL;
			r->vconst = g;
			if(g < 4)
				n->addable = 7;
			break;
		}
		g = vlog(l);
		if(g >= 0) {
			n->left = r;
			n->right = l;
			l = r;
			r = n->right;
			n->op = OASHL;
			r->vconst = g;
			if(g < 4)
				n->addable = 7;
			break;
		}
		break;

	case ODIV:
	case OLDIV:
		xcom(l);
		xcom(r);
		if(typev[n->type->etype])
			break;
		g = vlog(r);
		if(g >= 0) {
			if(n->op == ODIV)
				n->op = OASHR;
			else
				n->op = OLSHR;
			r->vconst = g;
		}
		break;

	case OSUB:
		xcom(l);
		xcom(r);
		if(typev[n->type->etype])
			break;
		if(vconst(l) == 0) {
			n->op = ONEG;
			n->left = r;
			n->right = Z;
		}
		break;

	case OXOR:
		xcom(l);
		xcom(r);
		if(typev[n->type->etype])
			break;
		if(vconst(l) == -1) {
			n->op = OCOM;
			n->left = r;
			n->right = Z;
		}
		break;

	case OASMUL:
	case OASLMUL:
		xcom(l);
		xcom(r);
		if(typev[n->type->etype])
			break;
		g = vlog(r);
		if(g >= 0) {
			n->op = OASASHL;
			r->vconst = g;
		}
		goto aseae;

	case OASDIV:
	case OASLDIV:
		xcom(l);
		xcom(r);
		if(typev[n->type->etype])
			break;
		g = vlog(r);
		if(g >= 0) {
			if(n->op == OASDIV)
				n->op = OASASHR;
			else
				n->op = OASLSHR;
			r->vconst = g;
		}
		goto aseae;

	case OASLMOD:
	case OASMOD:
		xcom(l);
		xcom(r);
		if(typev[n->type->etype])
			break;

	aseae:		/* hack that there are no byte/short mul/div operators */
		if(n->type->etype == TCHAR || n->type->etype == TSHORT) {
			n->right = new1(OCAST, n->right, Z);
			n->right->type = types[TLONG];
			n->type = types[TLONG];
		}
		if(n->type->etype == TUCHAR || n->type->etype == TUSHORT) {
			n->right = new1(OCAST, n->right, Z);
			n->right->type = types[TULONG];
			n->type = types[TULONG];
		}
		goto asop;

	case OASXOR:
	case OASOR:
	case OASADD:
	case OASSUB:
	case OASLSHR:
	case OASASHR:
	case OASASHL:
	case OASAND:
	case OAS:
		xcom(l);
		xcom(r);
		if(typev[n->type->etype])
			break;

	asop:
		if(l->addable > INDEXED &&
		   l->complex < FNX &&
		   r && r->complex < FNX)
			n->addable = l->addable;
		break;

	case OPOSTINC:
	case OPREINC:
	case OPOSTDEC:
	case OPREDEC:
		xcom(l);
		if(typev[n->type->etype])
			break;
		if(l->addable > INDEXED &&
		   l->complex < FNX)
			n->addable = l->addable;
		break;

	default:
		if(l != Z)
			xcom(l);
		if(r != Z)
			xcom(r);
		break;
	}

brk:
	n->complex = 0;
	if(n->addable >= 10)
		return;
	if(l != Z)
		n->complex = l->complex;
	if(r != Z) {
		if(r->complex == n->complex)
			n->complex = r->complex+1;
		else
		if(r->complex > n->complex)
			n->complex = r->complex;
	}
	if(n->complex == 0)
		n->complex++;

	if(com64(n))
		return;

	switch(n->op) {

	case OFUNC:
		n->complex = FNX;
		break;

	case OADD:
	case OMUL:
	case OLMUL:
	case OXOR:
	case OAND:
	case OOR:
		/*
		 * symmetric operators, make right side simple
		 * if same, put constant on left to get movq
		 */
		if(r->complex > l->complex ||
		  (r->complex == l->complex && r->addable == 20)) {
			n->left = r;
			n->right = l;
		}
		break;

	case OLE:
	case OLT:
	case OGE:
	case OGT:
	case OEQ:
	case ONE:
		/*
		 * relational operators, make right side simple
		 * if same, put constant on left to get movq
		 */
		if(r->complex > l->complex || r->addable == 20) {
			n->left = r;
			n->right = l;
			n->op = invrel[relindex(n->op)];
		}
		break;
	}
}
Example #2
0
/*
 *	calculate addressability as follows
 *		CONST ==> 20		$value
 *		NAME ==> 10		name
 *		REGISTER ==> 11		register
 *		INDREG ==> 12		*[(reg)+offset]
 *		&10 ==> 2		$name
 *		ADD(2, 20) ==> 2	$name+offset
 *		ADD(3, 20) ==> 3	$(reg)+offset
 *		&12 ==> 3		$(reg)+offset
 *		*11 ==> 11		??
 *		*2 ==> 10		name
 *		*3 ==> 12		*(reg)+offset
 *	calculate complexity (number of registers)
 */
void
xcom(Node *n)
{
	Node *l, *r;
	int t;

	if(n == Z)
		return;
	l = n->left;
	r = n->right;
	n->addable = 0;
	n->complex = 0;
	switch(n->op) {
	case OCONST:
		n->addable = 20;
		return;

	case OREGISTER:
		n->addable = 11;
		return;

	case OINDREG:
		n->addable = 12;
		return;

	case ONAME:
		n->addable = 10;
		return;

	case OADDR:
		xcom(l);
		if(l->addable == 10)
			n->addable = 2;
		if(l->addable == 12)
			n->addable = 3;
		break;

	case OIND:
		xcom(l);
		if(l->addable == 11)
			n->addable = 12;
		if(l->addable == 3)
			n->addable = 12;
		if(l->addable == 2)
			n->addable = 10;
		break;

	case OADD:
		xcom(l);
		xcom(r);
		if(l->addable == 20) {
			if(r->addable == 2)
				n->addable = 2;
			if(r->addable == 3)
				n->addable = 3;
		}
		if(r->addable == 20) {
			if(l->addable == 2)
				n->addable = 2;
			if(l->addable == 3)
				n->addable = 3;
		}
		break;

/*
	case OSUB:
		xcom(l);
		xcom(r);
		if(typefd[n->type->etype] || typev[n->type->etype])
			break;
		if(vconst(l) == 0)
			n->op = ONEG;
			n->left = l;
			n->right = Z;
		}
		break;
*/

	case OASHL:
	case OASHR:
	case OLSHR:
	case OASASHL:
	case OASASHR:
	case OASLSHR:
		xcom(l);
		xcom(r);
		if(sconst(r) && r->vconst < 0){
			r->vconst = -r->vconst;
			switch(n->op){
			case OASHL:	n->op = OASHR; break;
			case OASHR:	n->op = OASHL; break;
			case OLSHR:	n->op = OASHL; break;
			case OASASHL:	n->op = OASASHR; break;
			case OASASHR:	n->op = OASASHL; break;
			case OASLSHR:	n->op = OASASHL; break;
			}
		}
		break;
	
	case OASLMUL:
	case OASMUL:
		xcom(l);
		xcom(r);
		t = vlog(r);
		if(t >= 0) {
			n->op = OASASHL;
			r->vconst = t;
			r->type = types[TINT];
		}
		break;

	case OMUL:
	case OLMUL:
		xcom(l);
		xcom(r);
		t = vlog(r);
		if(t >= 0) {
			n->op = OASHL;
			r->vconst = t;
			r->type = types[TINT];
		}
		t = vlog(l);
		if(t >= 0) {
			n->op = OASHL;
			n->left = r;
			n->right = l;
			r = l;
			l = n->left;
			r->vconst = t;
			r->type = types[TINT];
		}
		break;

	case OASLDIV:
		xcom(l);
		xcom(r);
		t = vlog(r);
		if(t >= 0) {
			n->op = OASLSHR;
			r->vconst = t;
			r->type = types[TINT];
		}
		break;

	case OLDIV:
		xcom(l);
		xcom(r);
		t = vlog(r);
		if(t >= 0) {
			n->op = OLSHR;
			r->vconst = t;
			r->type = types[TINT];
		}
		break;

	case OASLMOD:
		xcom(l);
		xcom(r);
		t = vlog(r);
		if(t >= 0) {
			n->op = OASAND;
			r->vconst--;
		}
		break;

	case OLMOD:
		xcom(l);
		xcom(r);
		t = vlog(r);
		if(t >= 0) {
			n->op = OAND;
			r->vconst--;
		}
		break;

	default:
		if(l != Z)
			xcom(l);
		if(r != Z)
			xcom(r);
		break;
	}
	if(n->addable >= 10)
		return;

	if(l != Z)
		n->complex = l->complex;
	if(r != Z) {
		if(r->complex == n->complex)
			n->complex = r->complex+1;
		else
		if(r->complex > n->complex)
			n->complex = r->complex;
	}
	if(n->complex == 0)
		n->complex++;

	if(com64(n))
		return;

	switch(n->op) {
	case OFUNC:
		n->complex = FNX;
		break;

	case OLE:
	case OLT:
	case OGE:
	case OGT:
	case OHI:
	case OHS:
	case OLO:
	case OLS:
		/*
		 * immediate operators, make const on right
		 */
		if(l->op == OCONST) {
			n->left = r;
			n->right = l;
			n->op = invrel[relindex(n->op)];
		}
		break;

	case OADD:
	case OXOR:
	case OAND:
	case OOR:
	case OEQ:
	case ONE:
		/*
		 * immediate operators, make const on right
		 */
		if(l->op == OCONST) {
			n->left = r;
			n->right = l;
		}
		break;
	}
}