case ACMPB:
case ACMPW:
case ACMPL:
case ABSR:
return 0;
case ABRA:
case ABGE:
case ABNE:
case ABLE:
case ABEQ:
case ABHI:
case ABLS:
case ABMI:
case ABPL:
case ABGT:
case ABLT:
case ABCC:
case ABCS:
case APEA:
case ALEA:
case ANOP:
case AFADDD:
case AFMULD:
case AFDIVD:
case AFSUBD:
case AFADDF:
case AFMULF:
case AFDIVF:
case AFSUBF:
case AADJSP:
return -1;
case AADDW:
case AADDL:
case ASUBW:
case ASUBL:
case ACLRL:
case ACLRW:
if(p->to.type >= D_A0 && p->to.type < D_A0+8)
goto areg;
case AADDB:
case ASUBB:
case AANDB:
case AANDW:
case AANDL:
case AORB:
case AORW:
case AORL:
case AEORB:
case AEORW:
case AEORL:
case ALSLB:
case ALSLW:
case ALSLL:
case ALSRB:
case ALSRW:
case ALSRL:
case AASLB:
case AASLW:
case AASLL:
case AASRB:
case AASRW:
case AASRL:
case ATSTB:
case ATSTW:
case ATSTL:
case ANEGB:
case ANEGW:
case ANEGL:
case ACLRB:
if(asize(p->as) != s)
break;
if(compat(&rp->to, &p->to))
return 1;
break;
case AMOVW:
case AMOVL:
if(p->to.type >= D_A0 && p->to.type < D_A0+8)
goto areg;
case AMOVB:
if(asize(p->as) != s)
break;
if(compat(&rp->to, &p->to))
return 1;
if(compat(&rp->to, &p->from))
return 1;
}
return 0;
t = a->type;
if(t >= (D_A0|I_INDIR) && t < ((D_A0+NREG)|I_INDIR))
while(a->offset == 0 && a->index == D_NONE)
return t & D_MASK;
return D_NONE;
}
int
asize(int a)
{
switch(a) {
case AFTSTD:
case AFMOVED:
case AFADDD:
case AFSUBD:
case AFMULD:
case AFDIVD:
case AFCMPD:
case AFNEGD:
return 8;
case AFTSTF:
case AFMOVEF:
case AFADDF:
case AFSUBF:
case AFMULF:
case AFDIVF:
case AFCMPF:
case AFNEGF:
case ACLRL:
case ATSTL:
case AMOVL:
case AADDL:
case ASUBL:
case ACMPL:
case AANDL:
case AORL:
case AEORL:
case ALSLL:
case ALSRL:
case AASLL:
case AASRL:
case ANEGL:
return 4;
case ACLRW:
case ATSTW:
case AMOVW:
case AADDW:
case ASUBW:
case ACMPW:
case AANDW:
case AORW:
case AEORW:
case ALSLW:
case ALSRW:
case AASLW:
case AASRW:
case ANEGW:
return 2;
case ACLRB:
case ATSTB:
case AMOVB:
case AADDB:
case ASUBB:
case ACMPB:
case AANDB:
case AORB:
case AEORB:
case ALSLB:
case ALSRB:
case AASLB:
case AASRB:
case ANEGB:
return 1;
}
if(debug['P'])
print("unknown asize %A\n", p->as);
return 0;
}
if(t >= D_R0 && t < D_R0+8)
return 1;
if(t >= D_A0 && t < D_A0+8)
return 1;
if(t >= D_F0 && t < D_F0+8)
return 1;
return 0;
}
int
anyvar(Adr *a)
{
if(regtyp(a->type))
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 MOVL
* will be eliminated by copy propagation.
*/
int
subprop(Reg *r0)
{
Prog *p;
Adr *v1, *v2;
Reg *r;
int t;
p = r0->prog;
v1 = &p->from;
if(!regtyp(v1->type))
return 0;
v2 = &p->to;
if(!regtyp(v2->type))
return 0;
for(r=uniqp(r0); r!=R; r=uniqp(r)) {
if(uniqs(r) == R)
break;
p = r->prog;
switch(p->as) {
case ADIVUW: /* these set Rn and Rn+1 */
case ADIVUL:
case ADIVSW:
case ADIVSL:
case ABSR:
return 0;
int
copy1(Adr *v1, Adr *v2, Reg *r, int f)
{
int t;
if(r->active) {
if(debug['P'])
print("copyret 1\n");
return 1;
}
r->active = 1;
if(debug['P'])
print("copy %D->%D\n", v1, v2);
for(; r != R; r = r->s1) {
if(debug['P'])
print("%P", r->prog);
if(!f && uniqp(r) == R) {
f = 1;
if(debug['P'])
print("; merge; f=%d", f);
}
t = copyu(r->prog, v2, A);
switch(t) {
case 2: /* rar, cant split */
if(debug['P'])
print("; rar return 0\n");
return 0;
case 3: /* set */
if(debug['P'])
print("; set; return 1\n");
return 1;
case 1: /* used, substitute */
case 4: /* use and set */
if(f) {
if(debug['P'])
print("; used and f; return 0\n");
return 0;
}
if(copyu(r->prog, v2, v1)) {
if(debug['P'])
print("; sub fail; return 0\n");
return 0;
}
if(debug['P'])
print("; substitute");
if(t == 4) {
if(debug['P'])
print("; used and set; return 1\n");
return 1;
}
break;
}
if(!f) {
t = copyu(r->prog, v1, A);
if(!f && (t == 2 || t == 3 || t == 4)) {
if(debug['P'])
print("; f set used");
f = 1;
}
}
if(debug['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(Prog *p, Adr *v, Adr *s)
{
int t;
switch(p->as) {
default:
if(debug['P'])
print("unknown op %A\n", p->as);
return 2;
case ALEA: /* lhs addr, rhs store */
if(copyas(&p->from, v))
return 2;
case AMOVL: /* rhs store */
case ACLRL:
case AFMOVEF:
case AFMOVED:
case AFMOVEB:
case AFMOVEW:
case AFMOVEL:
case ANOP:
if(copyas(&p->to, v)) {
if(s != A)
return copysub(&p->from, v, s, p, 1);
if(copyau(&p->from, v))
return 4;
return 3;
}
goto caseread;
case AADDL: /* rhs rar */
case AADDW:
case AADDB:
case ASUBL:
case ASUBW:
case ASUBB:
case AANDL:
case AANDW:
case AANDB:
case AORL:
case AORW:
case AORB:
case AEORL:
case AEORW:
case AEORB:
case AASRL:
case AASRW:
case AASRB:
case AASLL:
case AASLW:
case AASLB:
case ALSRL:
case ALSRW:
case ALSRB:
case ANOTL:
case ANOTW:
case ANOTB:
case ANEGL:
case ANEGW:
case ANEGB:
case AEXTBL:
case AEXTWL:
case AEXTBW:
case AMULSL:
case AMULUL:
case AMOVW: /* only sets part of register */
case AMOVB:
case ACLRW:
case ACLRB:
case AFADDD:
case AFMULD:
case AFDIVD:
case AFSUBD:
case AFNEGD:
case AFADDF:
case AFMULF:
case AFDIVF:
case AFSUBF:
case AFNEGF:
if(copyas(&p->to, v))
return 2;
goto caseread;
case ACMPL: /* read only */
case ACMPW:
case ACMPB:
case AFCMPF:
case AFCMPD:
case ATSTL:
case ATSTW:
case ATSTB:
case AFTSTF:
case AFTSTD:
caseread:
if(s != A) {
if(copysub(&p->from, v, s, p, 1))
return 1;
return copysub(&p->to, v, s, p, 1);
}
if(copyau(&p->from, v))
return 1;
if(copyau(&p->to, v))
return 1;
break;
case ABRA: /* no reference */
case ABGE:
case ABNE:
case ABLE:
case ABEQ:
case ABHI:
case ABLS:
case ABMI:
case ABPL:
case ABGT:
case ABLT:
case ABCC:
case ABCS:
case AFBEQ:
case AFBNE:
case AFBGT:
case AFBGE:
case AFBLE:
case AFBLT:
case AADJSP:
case ACASEW:
break;
case ADIVUW: /* these set Rn and Rn+1 */
case ADIVUL:
case ADIVSW:
case ADIVSL:
t = v->type;
if(t == p->to.type || t == p->to.type+1)
return 2;
goto caseread;
case ARTS: /* funny */
t = v->type;
if(t == D_R0 || t == D_F0)
return 2;
if(t >= D_R0 && t < D_R0+NREG)
if(t-D_R0 > exregoffset)
return 2;
if(t >= D_A0 && t < D_A0+NREG)
if(t-D_A0 > exaregoffset)
return 2;
if(t >= D_F0 && t < D_F0+NREG)
if(t-D_F0 > exfregoffset)
return 2;
return 3;
case ABSR: /* funny */
t = v->type;
if(t >= D_R0 && t < D_R0+NREG)
if(t-D_R0 > exregoffset)
return 2;
if(t >= D_A0 && t < D_A0+NREG)
if(t-D_A0 > exaregoffset)
return 2;
if(t >= D_F0 && t < D_F0+NREG)
if(t-D_F0 > exfregoffset)
return 2;
return 3;
}
return 0;
}
/*
* direct reference,
* could be set/use depending on
* semantics
*/
int
copyas(Adr *a, Adr *v)
{