/*
* 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)
{
Prog *p;
Adr *v1, *v2;
Reg *r;
int t;
case AADD:
case AADDU:
case ASUB:
case ASUBU:
case ASLL:
case ASRL:
case ASRA:
case AOR:
case AAND:
case AXOR:
case AMUL:
case AMULU:
case ADIV:
case ADIVU:
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 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;
}
/*
* 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)
*/
copyu(Prog *p, Adr *v, Adr *s)
{
case ANOP: /* read, write */
case AMOVW:
case AMOVF:
case AMOVD:
case AMOVH:
case AMOVHU:
case AMOVB:
case AMOVBU:
case AMOVDW:
case AMOVWD:
case AMOVFD:
case AMOVDF:
if(s != A) {
if(copysub(&p->from, v, s, 1))
return 1;
if(!copyas(&p->to, v))
if(copysub(&p->to, v, s, 1))
return 1;
return 0;
}
if(copyas(&p->to, v)) {
if(copyau(&p->from, v))
return 4;
return 3;
}
if(copyau(&p->from, v))
return 1;
if(copyau(&p->to, v))
return 1;
return 0;
case ASGT: /* read, read, write */
case ASGTU:
case AADD:
case AADDU:
case ASUB:
case ASUBU:
case ASLL:
case ASRL:
case ASRA:
case AOR:
case ANOR:
case AAND:
case AXOR:
case AMUL:
case AMULU:
case ADIV:
case ADIVU:
case AADDF:
case AADDD:
case ASUBF:
case ASUBD:
case AMULF:
case AMULD:
case ADIVF:
case ADIVD:
if(s != A) {
if(copysub(&p->from, v, s, 1))
return 1;
if(copysub1(p, v, s, 1))
return 1;
if(!copyas(&p->to, v))
if(copysub(&p->to, v, s, 1))
return 1;
return 0;
}
if(copyas(&p->to, v)) {
if(p->reg == NREG)
p->reg = p->to.reg;
if(copyau(&p->from, v))
return 4;
if(copyau1(p, v))
return 4;
return 3;
}
if(copyau(&p->from, v))
return 1;
if(copyau1(p, v))
return 1;
if(copyau(&p->to, v))
return 1;
return 0;
case ABEQ: /* read, read */
case ABNE:
case ABGTZ:
case ABGEZ:
case ABLTZ:
case ABLEZ:
case ACMPEQD:
case ACMPEQF:
case ACMPGED:
case ACMPGEF:
case ACMPGTD:
case ACMPGTF:
case ABFPF:
case ABFPT:
if(s != A) {
if(copysub(&p->from, v, s, 1))
return 1;
return copysub1(p, v, s, 1);
}
if(copyau(&p->from, v))
return 1;
if(copyau1(p, v))
return 1;
return 0;
switch(p->as) {
case ABEQ:
case ABNE:
case ABGTZ:
case ABGEZ:
case ABLTZ:
case ABLEZ:
case ASGT:
case ASGTU:
case AADD:
case AADDU:
case ASUB:
case ASUBU:
case ASLL:
case ASRL:
case ASRA:
case AOR:
case AAND:
case AXOR:
case AMUL:
case AMULU:
case ADIV:
case ADIVU:
return D_REG;
case ACMPEQD:
case ACMPEQF:
case ACMPGED:
case ACMPGEF:
case ACMPGTD:
case ACMPGTF:
case AADDF:
case AADDD:
case ASUBF:
case ASUBD:
case AMULF:
case AMULD:
case ADIVF:
case ADIVD:
return D_FREG;
}
return D_NONE;
}
/*
* direct reference,
* could be set/use depending on
* semantics
*/
int
copyas(Adr *a, Adr *v)
{