Example #1
0
/*
 * findinc finds ADD instructions with a constant
 * argument which falls within the immed_12 range.
 */
static Flow*
findinc(Flow *r, Flow *r2, Adr *v)
{
	Flow *r1;
	Prog *p;


	for(r1=uniqs(r); r1!=nil && r1!=r2; r=r1,r1=uniqs(r)) {
		if(uniqp(r1) != r)
			return nil;
		switch(copyu(r1->prog, v, A)) {
		case 0: /* not touched */
			continue;
		case 4: /* set and used */
			p = r1->prog;
			if(p->as == AADD)
			if(isdconst(&p->from))
			if(p->from.offset > -4096 && p->from.offset < 4096)
				return r1;
		default:
			return nil;
		}
	}
	return nil;
}
Example #2
0
/*
 * shortprop eliminates redundant zero/sign extensions.
 *
 *   MOVBS x, R
 *   <no use R>
 *   MOVBS R, R'
 *
 * changed to
 *
 *   MOVBS x, R
 *   ...
 *   MOVB  R, R' (compiled to mov)
 *
 * MOVBS above can be a MOVBS, MOVBU, MOVHS or MOVHU.
 */
static int
shortprop(Flow *r)
{
	Prog *p, *p1;
	Flow *r1;

	p = r->prog;
	r1 = findpre(r, &p->from);
	if(r1 == nil)
		return 0;

	p1 = r1->prog;
	if(p1->as == p->as) {
		// Two consecutive extensions.
		goto gotit;
	}

	if(p1->as == AMOVW && isdconst(&p1->from)
	   && p1->from.offset >= 0 && p1->from.offset < 128) {
		// Loaded an immediate.
		goto gotit;
	}

	return 0;

gotit:
	if(debug['P'])
		print("shortprop\n%P\n%P", p1, p);
	switch(p->as) {
	case AMOVBS:
	case AMOVBU:
		p->as = AMOVB;
		break;
	case AMOVHS:
	case AMOVHU:
		p->as = AMOVH;
		break;
	}
	if(debug['P'])
		print(" => %A\n", p->as);
	return 1;
}
Example #3
0
void
peep(Prog *firstp)
{
	Flow *r;
	Graph *g;
	Prog *p;
	int t;

	g = flowstart(firstp, sizeof(Flow));
	if(g == nil)
		return;
	for(r=g->start, t=0; r!=nil; r=r->link, t++)
		r->active = t;

loop1:
	if(debug['P'] && debug['v'])
		dumpit("loop1", g->start, 0);

	t = 0;
	for(r=g->start; r!=nil; r=r->link) {
		p = r->prog;
		switch(p->as) {
		case ASLL:
		case ASRL:
		case ASRA:
			/*
			 * elide shift into D_SHIFT operand of subsequent instruction
			 */
//			if(shiftprop(r)) {
//				excise(r);
//				t++;
//				break;
//			}
			break;

		case AMOVB:
		case AMOVH:
		case AMOVW:
		case AMOVF:
		case AMOVD:
			if(regtyp(&p->from))
			if(p->from.type == p->to.type)
			if(p->scond == C_SCOND_NONE) {
				if(copyprop(g, r)) {
					excise(r);
					t++;
					break;
				}
				if(subprop(r) && copyprop(g, r)) {
					excise(r);
					t++;
					break;
				}
			}
			break;

		case AMOVHS:
		case AMOVHU:
		case AMOVBS:
		case AMOVBU:
			if(p->from.type == D_REG) {
				if(shortprop(r))
					t++;
			}
			break;

#ifdef NOTDEF
			if(p->scond == C_SCOND_NONE)
			if(regtyp(&p->to))
			if(isdconst(&p->from)) {
				constprop(&p->from, &p->to, r->s1);
			}
			break;
#endif
		}
	}
	if(t)
		goto loop1;

	for(r=g->start; r!=nil; r=r->link) {
		p = r->prog;
		switch(p->as) {
		case AEOR:
			/*
			 * EOR -1,x,y => MVN x,y
			 */
			if(isdconst(&p->from) && p->from.offset == -1) {
				p->as = AMVN;
				p->from.type = D_REG;
				if(p->reg != NREG)
					p->from.reg = p->reg;
				else
					p->from.reg = p->to.reg;
				p->reg = NREG;
			}
			break;
		}
	}

	for(r=g->start; r!=nil; r=r->link) {
		p = r->prog;
		switch(p->as) {
		case AMOVW:
		case AMOVB:
		case AMOVBS:
		case AMOVBU:
			if(p->from.type == D_OREG && p->from.offset == 0)
				xtramodes(g, r, &p->from);
			else
			if(p->to.type == D_OREG && p->to.offset == 0)
				xtramodes(g, r, &p->to);
			else
				continue;
			break;
//		case ACMP:
//			/*
//			 * elide CMP $0,x if calculation of x can set condition codes
//			 */
//			if(isdconst(&p->from) || p->from.offset != 0)
//				continue;
//			r2 = r->s1;
//			if(r2 == nil)
//				continue;
//			t = r2->prog->as;
//			switch(t) {
//			default:
//				continue;
//			case ABEQ:
//			case ABNE:
//			case ABMI:
//			case ABPL:
//				break;
//			case ABGE:
//				t = ABPL;
//				break;
//			case ABLT:
//				t = ABMI;
//				break;
//			case ABHI:
//				t = ABNE;
//				break;
//			case ABLS:
//				t = ABEQ;
//				break;
//			}
//			r1 = r;
//			do
//				r1 = uniqp(r1);
//			while (r1 != nil && r1->prog->as == ANOP);
//			if(r1 == nil)
//				continue;
//			p1 = r1->prog;
//			if(p1->to.type != D_REG)
//				continue;
//			if(p1->to.reg != p->reg)
//			if(!(p1->as == AMOVW && p1->from.type == D_REG && p1->from.reg == p->reg))
//				continue;
//
//			switch(p1->as) {
//			default:
//				continue;
//			case AMOVW:
//				if(p1->from.type != D_REG)
//					continue;
//			case AAND:
//			case AEOR:
//			case AORR:
//			case ABIC:
//			case AMVN:
//			case ASUB:
//			case ARSB:
//			case AADD:
//			case AADC:
//			case ASBC:
//			case ARSC:
//				break;
//			}
//			p1->scond |= C_SBIT;
//			r2->prog->as = t;
//			excise(r);
//			continue;
		}
	}

//	predicate(g);

	flowend(g);
}
Example #4
0
void
peep(void)
{
	Reg *r, *r1, *r2;
	Prog *p, *p1;
	int t;

	p1 = nil;
	USED(p1);		// ... in unreachable code...
/*
 * complete R structure
 */
	for(r=firstr; r!=R; r=r1) {
		r1 = r->link;
		if(r1 == R)
			break;
		p = r->prog->link;
		while(p != r1->prog)
		switch(p->as) {
		default:
			r2 = rega();
			r->link = r2;
			r2->link = r1;

			r2->prog = p;
			r2->p1 = r;
			r->s1 = r2;
			r2->s1 = r1;
			r1->p1 = r2;

			r = r2;

		case ADATA:
		case AGLOBL:
		case ANAME:
		case ASIGNAME:
			p = p->link;
		}
	}
//dumpit("begin", firstr);

loop1:

	t = 0;
	for(r=firstr; r!=R; r=r->link) {
		p = r->prog;
		switch(p->as) {
		case ASLL:
		case ASRL:
		case ASRA:
			/*
			 * elide shift into D_SHIFT operand of subsequent instruction
			 */
//			if(shiftprop(r)) {
//				excise(r);
//				t++;
//				break;
//			}
			break;

		case AMOVW:
		case AMOVF:
		case AMOVD:
			if(regtyp(&p->from))
			if(p->from.type == p->to.type)
			if(p->scond == C_SCOND_NONE) {
				if(copyprop(r)) {
					excise(r);
					t++;
					break;
				}
				if(subprop(r) && copyprop(r)) {
					excise(r);
					t++;
					break;
				}
			}
			break;

#ifdef	NOTDEF
			if(p->scond == C_SCOND_NONE)
			if(regtyp(&p->to))
			if(isdconst(&p->from)) {
				constprop(&p->from, &p->to, r->s1);
			}
			break;
#endif
		}
	}
	if(t)
		goto loop1;

return;

#ifdef	NOTDEF
	for(r=firstr; r!=R; r=r->link) {
		p = r->prog;
		switch(p->as) {
//		case AEOR:
//			/*
//			 * EOR -1,x,y => MVN x,y
//			 */
//			if(isdconst(&p->from) && p->from.offset == -1) {
//				p->as = AMVN;
//				p->from.type = D_REG;
//				if(p->reg != NREG)
//					p->from.reg = p->reg;
//				else
//					p->from.reg = p->to.reg;
//				p->reg = NREG;
//			}
//			break;

		case AMOVH:
		case AMOVHU:
		case AMOVB:
		case AMOVBU:
			/*
			 * look for MOVB x,R; MOVB R,R
			 */
			if(p->to.type != D_REG)
				break;
			if(r1 == R)
				break;
			p1 = r1->prog;
			if(p1->as != p->as)
				break;
			if(p1->from.type != D_REG || p1->from.reg != p->to.reg)
				break;
			if(p1->to.type != D_REG || p1->to.reg != p->to.reg)
				break;
			excise(r1);
			break;
		}
		r1 = r->link;
	}

//	for(r=firstr; r!=R; r=r->link) {
//		p = r->prog;
//		switch(p->as) {
//		case AMOVW:
//		case AMOVB:
//		case AMOVBU:
//			if(p->from.type == D_OREG && p->from.offset == 0)
//				xtramodes(r, &p->from);
//			else
//			if(p->to.type == D_OREG && p->to.offset == 0)
//				xtramodes(r, &p->to);
//			else
//				continue;
//			break;
//		case ACMP:
//			/*
//			 * elide CMP $0,x if calculation of x can set condition codes
//			 */
//			if(isdconst(&p->from) || p->from.offset != 0)
//				continue;
//			r2 = r->s1;
//			if(r2 == R)
//				continue;
//			t = r2->prog->as;
//			switch(t) {
//			default:
//				continue;
//			case ABEQ:
//			case ABNE:
//			case ABMI:
//			case ABPL:
//				break;
//			case ABGE:
//				t = ABPL;
//				break;
//			case ABLT:
//				t = ABMI;
//				break;
//			case ABHI:
//				t = ABNE;
//				break;
//			case ABLS:
//				t = ABEQ;
//				break;
//			}
//			r1 = r;
//			do
//				r1 = uniqp(r1);
//			while (r1 != R && r1->prog->as == ANOP);
//			if(r1 == R)
//				continue;
//			p1 = r1->prog;
//			if(p1->to.type != D_REG)
//				continue;
//			if(p1->to.reg != p->reg)
//			if(!(p1->as == AMOVW && p1->from.type == D_REG && p1->from.reg == p->reg))
//				continue;
//
//			switch(p1->as) {
//			default:
//				continue;
//			case AMOVW:
//				if(p1->from.type != D_REG)
//					continue;
//			case AAND:
//			case AEOR:
//			case AORR:
//			case ABIC:
//			case AMVN:
//			case ASUB:
//			case ARSB:
//			case AADD:
//			case AADC:
//			case ASBC:
//			case ARSC:
//				break;
//			}
//			p1->scond |= C_SBIT;
//			r2->prog->as = t;
//			excise(r);
//			continue;
//		}
//	}

	predicate();
#endif
}