⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 peep.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "gc.h"int xtramodes(Reg*, Adr*);voidpeep(void){	Reg *r, *r1, *r2;	Prog *p, *p1;	int t;/* * complete R structure */	t = 0;	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;			t++;		case ADATA:		case AGLOBL:		case ANAME:		case ASIGNAME:			p = p->link;		}	}loop1:	t = 0;	for(r=firstr; r!=R; r=r->link) {		p = r->prog;		if(p->as == ASLL || p->as == ASRL || p->as == ASRA) {			/*			 * elide shift into D_SHIFT operand of subsequent instruction			 */			if(shiftprop(r)) {				excise(r);				t++;			}		}		if(p->as == AMOVW || p->as == AMOVF || p->as == AMOVD)		if(regtyp(&p->to)) {			if(p->from.type == D_CONST)				constprop(&p->from, &p->to, r->s1);			else if(regtyp(&p->from))			if(p->from.type == p->to.type) {				if(copyprop(r)) {					excise(r);					t++;				} else				if(subprop(r) && copyprop(r)) {					excise(r);					t++;				}			}		}	}	if(t)		goto loop1;	/*	 * look for MOVB x,R; MOVB R,R	 */	for(r=firstr; r!=R; r=r->link) {		p = r->prog;		switch(p->as) {		default:			continue;		case AEOR:			/*			 * EOR -1,x,y => MVN x,y			 */			if(p->from.type == D_CONST && 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;			}			continue;		case AMOVH:		case AMOVHU:		case AMOVB:		case AMOVBU:			if(p->to.type != D_REG)				continue;			break;		}		r1 = r->link;		if(r1 == R)			continue;		p1 = r1->prog;		if(p1->as != p->as)			continue;		if(p1->from.type != D_REG || p1->from.reg != p->to.reg)			continue;		if(p1->to.type != D_REG || p1->to.reg != p->to.reg)			continue;		excise(r1);	}	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(p->from.type != D_CONST || 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();}voidexcise(Reg *r){	Prog *p;	p = r->prog;	p->as = ANOP;	p->scond = zprog.scond;	p->from = zprog.from;	p->to = zprog.to;	p->reg = zprog.reg; /**/}Reg*uniqp(Reg *r){	Reg *r1;	r1 = r->p1;	if(r1 == R) {		r1 = r->p2;		if(r1 == R || r1->p2link != 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;}intregtyp(Adr *a){	if(a->type == D_REG)		return 1;	if(a->type == D_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. */intsubprop(Reg *r0){	Prog *p;	Adr *v1, *v2;	Reg *r;	int t;	p = r0->prog;	v1 = &p->from;	if(!regtyp(v1))		return 0;	v2 = &p->to;	if(!regtyp(v2))		return 0;	for(r=uniqp(r0); r!=R; r=uniqp(r)) {		if(uniqs(r) == R)			break;		p = r->prog;		switch(p->as) {		case ABL:			return 0;		case ACMP:		case ACMN:		case AADD:		case ASUB:		case ARSB:		case ASLL:		case ASRL:		case ASRA:		case AORR:		case AAND:		case AEOR:		case AMUL:		case ADIV:		case ADIVU:		case ACMPF:		case ACMPD:		case AADDD:		case AADDF:		case ASUBD:		case ASUBF:		case AMULD:		case AMULF:		case ADIVD:		case ADIVF:			if(p->to.type == v1->type)			if(p->to.reg == v1->reg) {				if(p->reg == NREG)					p->reg = p->to.reg;				goto gotit;			}			break;		case AMOVF:		case AMOVD:		case AMOVW:			if(p->to.type == v1->type)			if(p->to.reg == v1->reg)				goto gotit;			break;		case AMOVM:			t = 1<<v2->reg;			if((p->from.type == D_CONST && (p->from.offset&t)) ||			   (p->to.type == D_CONST && (p->to.offset&t)))				return 0;			break;		}		if(copyau(&p->from, v2) ||		   copyau1(p, v2) ||		   copyau(&p->to, v2))			break;		if(copysub(&p->from, v1, v2, 0) ||		   copysub1(p, v1, v2, 0) ||		   copysub(&p->to, v1, v2, 0))			break;	}	return 0;gotit:	copysub(&p->to, v1, v2, 1);	if(debug['P']) {		print("gotit: %D->%D\n%P", v1, v2, r->prog);		if(p->from.type == v2->type)			print(" excise");		print("\n");	}	for(r=uniqs(r); r!=r0; r=uniqs(r)) {		p = r->prog;		copysub(&p->from, v1, v2, 1);		copysub1(p, v1, v2, 1);		copysub(&p->to, v1, v2, 1);		if(debug['P'])			print("%P\n", r->prog);	}	t = v1->reg;	v1->reg = v2->reg;	v2->reg = t;	if(debug['P'])		print("%P 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 */intcopyprop(Reg *r0){	Prog *p;	Adr *v1, *v2;	Reg *r;	p = r0->prog;	v1 = &p->from;	v2 = &p->to;	if(copyas(v1, v2))		return 1;	for(r=firstr; r!=R; r=r->link)		r->active = 0;	return copy1(v1, v2, r0->s1, 0);}intcopy1(Adr *v1, Adr *v2, Reg *r, int f){	int t;	Prog *p;	if(r->active) {		if(debug['P'])			print("act set; return 1\n");		return 1;	}	r->active = 1;	if(debug['P'])		print("copy %D->%D f=%d\n", v1, v2, f);	for(; r != R; r = r->s1) {		p = r->prog;		if(debug['P'])			print("%P", p);		if(!f && uniqp(r) == R) {			f = 1;			if(debug['P'])				print("; merge; f=%d", f);		}		t = copyu(p, v2, A);		switch(t) {		case 2:	/* rar, cant split */			if(debug['P'])				print("; %Drar; return 0\n", v2);			return 0;		case 3:	/* set */			if(debug['P'])				print("; %Dset; return 1\n", v2);			return 1;		case 1:	/* used, substitute */		case 4:	/* use and set */			if(f) {				if(!debug['P'])					return 0;				if(t == 4)					print("; %Dused+set and f=%d; return 0\n", v2, f);				else					print("; %Dused and f=%d; return 0\n", v2, f);				return 0;			}			if(copyu(p, v2, v1)) {				if(debug['P'])					print("; sub fail; return 0\n");				return 0;			}			if(debug['P'])				print("; sub%D/%D", v2, v1);			if(t == 4) {				if(debug['P'])					print("; %Dused+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(debug['P'])					print("; %Dset and !f; f=%d", v1, f);			}		}		if(debug['P'])			print("\n");		if(r->s2)			if(!copy1(v1, v2, r->s2, f))				return 0;	}	return 1;}/* * The idea is to remove redundant constants. *	$c1->v1 *	($c1->v2 s/$c1/v1)* *	set v1  return * The v1->v2 should be eliminated by copy propagation. */voidconstprop(Adr *c1, Adr *v1, Reg *r){	Prog *p;	if(debug['C'])		print("constprop %D->%D\n", c1, v1);	for(; r != R; r = r->s1) {		p = r->prog;		if(debug['C'])			print("%P", p);		if(uniqp(r) == R) {			if(debug['C'])				print("; merge; return\n");			return;		}		if(p->as == AMOVW && copyas(&p->from, c1)) {				if(debug['C'])					print("; sub%D/%D", &p->from, v1);				p->from = *v1;		} else if(copyu(p, v1, A) > 1) {			if(debug['C'])				print("; %Dset; return\n", v1);			return;		}		if(debug['C'])			print("\n");		if(r->s2)			constprop(c1, v1, r->s2);	}}/* * ASLL x,y,w * .. (not use w, not set x y w) * AXXX w,a,b (a != w) * .. (not use w) * (set w) * ----------- changed to * .. * AXXX (x<<y),a,b * .. */#define FAIL(msg) { if(debug['H']) print("\t%s; FAILURE\n", msg); return 0; }intshiftprop(Reg *r){	Reg *r1;	Prog *p, *p1, *p2;	int n, o;	Adr a;	p = r->prog;	if(p->to.type != D_REG)		FAIL("BOTCH: result not reg");	n = p->to.reg;	a = zprog.from;	if(p->reg != NREG && p->reg != p->to.reg) {		a.type = D_REG;		a.reg = p->reg;	}	if(debug['H'])		print("shiftprop\n%P", p);	r1 = r;	for(;;) {		/* find first use of shift result; abort if shift operands or result are changed */		r1 = uniqs(r1);		if(r1 == R)			FAIL("branch");		if(uniqp(r1) == R)			FAIL("merge");		p1 = r1->prog;		if(debug['H'])			print("\n%P", p1);		switch(copyu(p1, &p->to, A)) {		case 0:	/* not used or set */			if((p->from.type == D_REG && copyu(p1, &p->from, A) > 1) ||			   (a.type == D_REG && copyu(p1, &a, A) > 1))				FAIL("args modified");			continue;		case 3:	/* set, not used */			FAIL("BOTCH: noref");		}		break;	}	/* check whether substitution can be done */	switch(p1->as) {	default:		FAIL("non-dpi");	case AAND:	case AEOR:	case AADD:	case AADC:	case AORR:	case ASUB:	case ARSB:	case ASBC:	case ARSC:		if(p1->reg == n || (p1->reg == NREG && p1->to.type == D_REG && p1->to.reg == n)) {			if(p1->from.type != D_REG)				FAIL("can't swap");			p1->reg = p1->from.reg;			p1->from.reg = n;			switch(p1->as) {			case ASUB:				p1->as = ARSB;				break;			case ARSB:				p1->as = ASUB;				break;			case ASBC:				p1->as = ARSC;				break;			case ARSC:				p1->as = ASBC;				break;			}			if(debug['H'])				print("\t=>%P", p1);		}	case ABIC:	case ACMP:	case ACMN:		if(p1->reg == n)			FAIL("can't swap");		if(p1->reg == NREG && p1->to.reg == n)			FAIL("shift result used twice");	case AMVN:		if(p1->from.type == D_SHIFT)			FAIL("shift result used in shift");		if(p1->from.type != D_REG || p1->from.reg != n)			FAIL("BOTCH: where is it used?");		break;	}	/* check whether shift result is used subsequently */	p2 = p1;	if(p1->to.reg != n)	for (;;) {		r1 = uniqs(r1);		if(r1 == R)			FAIL("inconclusive");		p1 = r1->prog;		if(debug['H'])			print("\n%P", p1);		switch(copyu(p1, &p->to, A)) {		case 0:	/* not used or set */			continue;		case 3: /* set, not used */			break;		default:/* used */			FAIL("reused");		}		break;	}	/* make the substitution */	p2->from.type = D_SHIFT;	p2->from.reg = NREG;	o = p->reg;	if(o == NREG)		o = p->to.reg;	switch(p->from.type){	case D_CONST:		o |= (p->from.offset&0x1f)<<7;		break;	case D_REG:		o |= (1<<4) | (p->from.reg<<8);		break;	}	switch(p->as){	case ASLL:		o |= 0<<5;		break;	case ASRL:		o |= 1<<5;		break;	case ASRA:		o |= 2<<5;		break;	}	p2->from.offset = o;	if(debug['H'])		print("\t=>%P\tSUCCEED\n", p2);	return 1;}Reg*findpre(Reg *r, Adr *v){	Reg *r1;	for(r1=uniqp(r); r1!=R; r=r1,r1=uniqp(r)) {		if(uniqs(r1) != r)			return R;		switch(copyu(r1->prog, v, A)) {		case 1: /* used */		case 2: /* read-alter-rewrite */			return R;		case 3: /* set */		case 4: /* set and used */			return r1;		}	}	return R;}Reg*findinc(Reg *r, Reg *r2, Adr *v){	Reg *r1;	Prog *p;	for(r1=uniqs(r); r1!=R && r1!=r2; r=r1,r1=uniqs(r)) {		if(uniqp(r1) != r)			return R;		switch(copyu(r1->prog, v, A)) {		case 0: /* not touched */			continue;		case 4: /* set and used */			p = r1->prog;			if(p->as == AADD)			if(p->from.type == D_CONST)			if(p->from.offset > -4096 && p->from.offset < 4096)				return r1;		default:			return R;		}	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -