File:  [Plan 9 NeXT] / lucent / sys / src / alef / k / peep.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:01:04 2018 UTC (8 years, 1 month ago) by root
Branches: lucent, MAIN
CVS tags: plan9, HEAD
Plan 9 NeXT

#include <u.h>
#include <libc.h>
#include <bio.h>
#include <ctype.h>
#define Extern extern
#include "parl.h"
#include "globl.h"

void
peep(void)
{
	Reg *r, *r1, *r2;
	Inst *p;
	int t;
/*
 * complete R structure
 */
	t = 0;
	for(r=firstr; r!=R; r=r1) {
		r1 = r->next;
		if(r1 == R)
			break;
		p = r->prog->next;
		while(p != r1->prog)
		switch(p->op) {
		default:
			r2 = rega();
			r->next = r2;
			r2->next = r1;

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

			r = r2;
			t++;

		case ADATA:
		case ADYNT:
		case AINIT:
		case AGLOBL:
		case ANAME:
			p = p->next;
		}
	}

loop1:
	t = 0;
	for(r=firstr; r!=R; r=r->next) {
		p = r->prog;
		if(p->op == AMOVW || p->op == AFMOVF || p->op == AFMOVD)
		if(regtyp(&p->dst)) {
			if(regtyp(&p->src1))
			if(p->src1.type == p->dst.type) {
				if(copyprop(r)) {
					excise(r);
					t++;
				} else
				if(subprop(r) && copyprop(r)) {
					excise(r);
					t++;
				}
			}
			if(regzer(&p->src1))
			if(p->dst.type == A_REG) {
				p->src1.type = A_REG;
				p->src1.reg = 0;
				if(copyprop(r)) {
					excise(r);
					t++;
				} else
				if(subprop(r) && copyprop(r)) {
					excise(r);
					t++;
				}
			}
		}
	}
	if(t)
		goto loop1;
}

void
excise(Reg *r)
{
	Inst *p;

	p = r->prog;
	p->op = ANOP;
	p->src1 = zprog.src1;
	p->dst = zprog.dst;
	p->reg = zprog.reg; /**/
}

Reg*
uniqp(Reg *r)
{
	Reg *r1;

	r1 = r->p1;
	if(r1 == R) {
		r1 = r->p2;
		if(r1 == R || r1->p2next != R)
			return R;
	} else
		if(r->p2 != R)
			return R;
	return r1;
}

Reg*
uniqs(Reg *r)
{
	Reg *r1;

	r1 = r->s1;
	if(r1 == R) {
		r1 = r->s2;
		if(r1 == R)
			return R;
	} else
		if(r->s2 != R)
			return R;
	return r1;
}

regzer(Adres *a)
{

	if(a->type == A_CONST)
		if(a->sym == ZeroS)
			if(a->ival == 0)
				return 1;
	if(a->type == A_REG)
		if(a->reg == 0)
			return 1;
	return 0;
}

regtyp(Adres *a)
{

	if(a->type == A_REG) {
		if(a->reg != 0)
			return 1;
		return 0;
	}
	if(a->type == A_FREG)
		return 1;
	return 0;
}

/*
 * the idea is to substitute
 * one register for another
 * from one MOV to another
 *	MOV	a, R0
 *	ADD	b, R0	/ no use of R1
 *	MOV	R0, R1
 * would be converted to
 *	MOV	a, R1
 *	ADD	b, R1
 *	MOV	R1, R0
 * hopefully, then the former or latter MOV
 * will be eliminated by copy propagation.
 */
int
subprop(Reg *r0)
{
	Inst *p;
	Adres *v1, *v2;
	Reg *r;
	int t;

	p = r0->prog;
	v1 = &p->src1;
	if(!regtyp(v1))
		return 0;
	v2 = &p->dst;
	if(!regtyp(v2))
		return 0;
	for(r=uniqp(r0); r!=R; r=uniqp(r)) {
		if(uniqs(r) == R)
			break;
		p = r->prog;
		switch(p->op) {
		case AJMPL:
			return 0;

		case AADD:
		case ASUB:
		case ASLL:
		case ASRL:
		case ASRA:
		case AOR:
		case AAND:
		case AXOR:
		case AMUL:
		case ADIV:
		case ADIVL:
		case AMOD:
		case AMODL:

		case AFADDD:
		case AFADDF:
		case AFSUBD:
		case AFSUBF:
		case AFMULD:
		case AFMULF:
		case AFDIVD:
		case AFDIVF:
			if(p->dst.type == v1->type)
			if(p->dst.reg == v1->reg) {
				if(p->reg == Nreg)
					p->reg = p->dst.reg;
				goto gotit;
			}
			break;

		case AFMOVF:
		case AFMOVD:
		case AMOVW:
			if(p->dst.type == v1->type)
			if(p->dst.reg == v1->reg)
				goto gotit;
			break;
		}
		if(copyau(&p->src1, v2) ||
		   copyau1(p, v2) ||
		   copyau(&p->dst, v2))
			break;
		if(copysub(&p->src1, v1, v2, 0) ||
		   copysub1(p, v1, v2, 0) ||
		   copysub(&p->dst, v1, v2, 0))
			break;
	}
	return 0;

gotit:
	copysub(&p->dst, v1, v2, 1);
	if(opt('P')) {
		print("gotit: %a->%a\n%i", v1, v2, r->prog);
		if(p->src1.type == v2->type)
			print(" excise");
		print("\n");
	}
	for(r=uniqs(r); r!=r0; r=uniqs(r)) {
		p = r->prog;
		copysub(&p->src1, v1, v2, 1);
		copysub1(p, v1, v2, 1);
		copysub(&p->dst, v1, v2, 1);
		if(opt('P'))
			print("%i\n", r->prog);
	}
	t = v1->reg;
	v1->reg = v2->reg;
	v2->reg = t;
	if(opt('P'))
		print("%i last\n", r->prog);
	return 1;
}

/*
 * The idea is to remove redundant copies.
 *	v1->v2	F=0
 *	(use v2	s/v2/v1/)*
 *	set v1	F=1
 *	use v2	return fail
 *	-----------------
 *	v1->v2	F=0
 *	(use v2	s/v2/v1/)*
 *	set v1	F=1
 *	set v2	return success
 */
int
copyprop(Reg *r0)
{
	Inst *p;
	Adres *v1, *v2;
	Reg *r;

	p = r0->prog;
	v1 = &p->src1;
	v2 = &p->dst;
	if(copyas(v1, v2))
		return 1;
	for(r=firstr; r!=R; r=r->next)
		r->active = 0;
	return copy1(v1, v2, r0->s1, 0);
}

copy1(Adres *v1, Adres *v2, Reg *r, int f)
{
	int t;
	Inst *p;

	if(r->active) {
		if(opt('P'))
			print("act set; return 1\n");
		return 1;
	}
	r->active = 1;
	if(opt('P'))
		print("copy %a->%a f=%d\n", v1, v2, f);
	for(; r != R; r = r->s1) {
		p = r->prog;
		if(opt('P'))
			print("%i", p);
		if(!f && uniqp(r) == R) {
			f = 1;
			if(opt('P'))
				print("; merge; f=%d", f);
		}
		t = copyu(p, v2, A);
		switch(t) {
		case 2:	/* rar, cant split */
			if(opt('P'))
				print("; %arar; return 0\n", v2);
			return 0;

		case 3:	/* set */
			if(opt('P'))
				print("; %aset; return 1\n", v2);
			return 1;

		case 1:	/* used, substitute */
		case 4:	/* use and set */
			if(f) {
				if(!opt('P'))
					return 0;
				if(t == 4)
					print("; %aused+set and f=%d; return 0\n", v2, f);
				else
					print("; %aused and f=%d; return 0\n", v2, f);
				return 0;
			}
			if(copyu(p, v2, v1)) {
				if(opt('P'))
					print("; sub fail; return 0\n");
				return 0;
			}
			if(opt('P'))
				print("; sub%a/%a", v2, v1);
			if(t == 4) {
				if(opt('P'))
					print("; %aused+set; return 1\n", v2);
				return 1;
			}
			break;
		}
		if(!f) {
			t = copyu(p, v1, A);
			if(!f && (t == 2 || t == 3 || t == 4)) {
				f = 1;
				if(opt('P'))
					print("; %aset and !f; f=%d", v1, f);
			}
		}
		if(opt('P'))
			print("\n");
		if(r->s2)
			if(!copy1(v1, v2, r->s2, f))
				return 0;
	}
	return 1;
}

/*
 * return
 * 1 if v only used (and substitute),
 * 2 if read-alter-rewrite
 * 3 if set
 * 4 if set and used
 * 0 otherwise (not touched)
 */
int
copyu(Inst *p, Adres *v, Adres *s)
{

	switch(p->op) {

	default:
		if(opt('P'))
			print(" (???)");
		return 2;


	case ANOP:	/* read, write */
	case AMOVW:
	case AMOVH:
	case AMOVHU:
	case AMOVB:
	case AMOVBU:

	case AFMOVF:
	case AFMOVD:
	case AFMOVDW:
	case AFMOVWD:
	case AFMOVFW:
	case AFMOVWF:
	case AFMOVFD:
	case AFMOVDF:
		if(s != A) {
			if(copysub(&p->src1, v, s, 1))
				return 1;
			if(!copyas(&p->dst, v))
				if(copysub(&p->dst, v, s, 1))
					return 1;
			return 0;
		}
		if(copyas(&p->dst, v)) {
			if(copyau(&p->src1, v))
				return 4;
			return 3;
		}
		if(copyau(&p->src1, v))
			return 1;
		if(copyau(&p->dst, v))
			return 1;
		return 0;

	case AADD:	/* read read write */
	case ASUB:
	case ASLL:
	case ASRL:
	case ASRA:
	case AOR:
	case AAND:
	case AXOR:
	case AMUL:
	case ADIV:
	case ADIVL:
	case AMOD:
	case AMODL:

	case AFADDF:
	case AFADDD:
	case AFSUBF:
	case AFSUBD:
	case AFMULF:
	case AFMULD:
	case AFDIVF:
	case AFDIVD:
		if(s != A) {
			if(copysub(&p->src1, v, s, 1))
				return 1;
			if(copysub1(p, v, s, 1))
				return 1;
			if(!copyas(&p->dst, v))
				if(copysub(&p->dst, v, s, 1))
					return 1;
			return 0;
		}
		if(copyas(&p->dst, v)) {
			if(p->reg == Nreg)
				p->reg = p->dst.reg;
			if(copyau(&p->src1, v))
				return 4;
			if(copyau1(p, v))
				return 4;
			return 3;
		}
		if(copyau(&p->src1, v))
			return 1;
		if(copyau1(p, v))
			return 1;
		if(copyau(&p->dst, v))
			return 1;
		return 0;

	case ABA:	/* no reference */
	case ABCC:
	case ABCS:
	case ABE:
	case ABG:
	case ABGE:
	case ABGU:
	case ABL:
	case ABLE:
	case ABLEU:
	case ABN:
	case ABNE:
	case ABNEG:
	case ABPOS:
	case ABVC:
	case ABVS:
	case AFBA:
	case AFBE:
	case AFBG:
	case AFBGE:
	case AFBL:
	case AFBLE:
	case AFBLG:
	case AFBN:
	case AFBNE:
	case AFBO:
	case AFBU:
	case AFBUE:
	case AFBUG:
	case AFBUGE:
	case AFBUL:
	case AFBULE:
		break;

	case ACMP:	/* read read */
	case AFCMPD:
	case AFCMPF:
		if(s != A) {
			if(copysub(&p->src1, v, s, 1))
				return 1;
			return copysub(&p->dst, v, s, 1);
		}
		if(copyau(&p->src1, v))
			return 1;
		if(copyau(&p->dst, v))
			return 1;
		break;

	case AJMP:	/* funny */
		if(s != A) {
			if(copysub(&p->dst, v, s, 1))
				return 1;
			return 0;
		}
		if(copyau(&p->dst, v))
			return 1;
		return 0;

	case ARETURN:	/* funny */
		if(v->type == A_REG && v->reg == REGRET)
			return 2;
		if(v->type == A_FREG && v->reg == FREGRET)
			return 2;

	case AJMPL:	/* funny */
		if(v->type == A_REG) {
			if(v->reg == Regspass)
				return 2;
			if(v->reg == RegSP)
				return 2;
		}
		if(s != A) {
			if(copysub(&p->dst, v, s, 1))
				return 1;
			return 0;
		}
		if(copyau(&p->dst, v))
			return 4;
		return 3;

	case ATEXT:	/* funny */
		if(v->type == A_REG)
			if(v->reg == Regspass)
				return 3;
		return 0;
	}
	return 0;
}

int
a2type(Inst *p)
{

	switch(p->op) {
	case AADD:
	case ASUB:
	case ASLL:
	case ASRL:
	case ASRA:
	case AOR:
	case AAND:
	case AXOR:
	case AMUL:
	case ADIV:
	case ADIVL:
	case AMOD:
	case AMODL:
		return A_REG;

	case AFADDF:
	case AFADDD:
	case AFSUBF:
	case AFSUBD:
	case AFMULF:
	case AFMULD:
	case AFDIVF:
	case AFDIVD:
		return A_FREG;
	}
	return A_NONE;
}

/*
 * direct reference,
 * could be set/use depending on
 * semantics
 */
int
copyas(Adres *a, Adres *v)
{

	if(regtyp(v))
		if(a->type == v->type)
		if(a->reg == v->reg)
			return 1;
	return 0;
}

/*
 * either direct or indirect
 */
int
copyau(Adres *a, Adres *v)
{

	if(copyas(a, v))
		return 1;
	if(v->type == A_REG)
		if(a->type == A_INDREG)
			if(v->reg == a->reg)
				return 1;
	return 0;
}

int
copyau1(Inst *p, Adres *v)
{

	if(regtyp(v))
		if(p->src1.type == v->type || p->dst.type == v->type)
		if(p->reg == v->reg) {
			if(a2type(p) != v->type)
				print("botch a2type %i\n", p);
			return 1;
		}
	return 0;
}

/*
 * substitute s for v in a
 * return failure to substitute
 */
int
copysub(Adres *a, Adres *v, Adres *s, int f)
{

	if(f)
	if(copyau(a, v))
		a->reg = s->reg;
	return 0;
}

int
copysub1(Inst *p1, Adres *v, Adres *s, int f)
{

	if(f)
	if(copyau1(p1, v))
		p1->reg = s->reg;
	return 0;
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.