/*
* 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 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->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)
*/
int
copyu(Prog *p, Adr *v, Adr *s)
{
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->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 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->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 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 AFBNE:
case AFBN:
case AFBLG:
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->from, v, s, 1))
return 1;
return copysub(&p->to, v, s, 1);
}
if(copyau(&p->from, v))
return 1;
if(copyau(&p->to, v))
return 1;
break;
switch(p->as) {
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 D_REG;
case AFADDF:
case AFADDD:
case AFSUBF:
case AFSUBD:
case AFMULF:
case AFMULD:
case AFDIVF:
case AFDIVD:
return D_FREG;
}
return D_NONE;
}
/*
* direct reference,
* could be set/use depending on
* semantics
*/
int
copyas(Adr *a, Adr *v)
{