/* * findinc finds ADD instructions with a constant * argument which falls within the immed_12 range. */ static Flow* findinc(Flow *r, Flow *r2, Adr *v) { Flow *r1; Prog *p; for(r1=uniqs(r); r1!=nil && r1!=r2; r=r1,r1=uniqs(r)) { if(uniqp(r1) != r) return nil; switch(copyu(r1->prog, v, A)) { case 0: /* not touched */ continue; case 4: /* set and used */ p = r1->prog; if(p->as == AADD) if(isdconst(&p->from)) if(p->from.offset > -4096 && p->from.offset < 4096) return r1; default: return nil; } } return nil; }
/* * shortprop eliminates redundant zero/sign extensions. * * MOVBS x, R * <no use R> * MOVBS R, R' * * changed to * * MOVBS x, R * ... * MOVB R, R' (compiled to mov) * * MOVBS above can be a MOVBS, MOVBU, MOVHS or MOVHU. */ static int shortprop(Flow *r) { Prog *p, *p1; Flow *r1; p = r->prog; r1 = findpre(r, &p->from); if(r1 == nil) return 0; p1 = r1->prog; if(p1->as == p->as) { // Two consecutive extensions. goto gotit; } if(p1->as == AMOVW && isdconst(&p1->from) && p1->from.offset >= 0 && p1->from.offset < 128) { // Loaded an immediate. goto gotit; } return 0; gotit: if(debug['P']) print("shortprop\n%P\n%P", p1, p); switch(p->as) { case AMOVBS: case AMOVBU: p->as = AMOVB; break; case AMOVHS: case AMOVHU: p->as = AMOVH; break; } if(debug['P']) print(" => %A\n", p->as); return 1; }
void peep(Prog *firstp) { Flow *r; Graph *g; Prog *p; int t; g = flowstart(firstp, sizeof(Flow)); if(g == nil) return; for(r=g->start, t=0; r!=nil; r=r->link, t++) r->active = t; loop1: if(debug['P'] && debug['v']) dumpit("loop1", g->start, 0); t = 0; for(r=g->start; r!=nil; r=r->link) { p = r->prog; switch(p->as) { case ASLL: case ASRL: case ASRA: /* * elide shift into D_SHIFT operand of subsequent instruction */ // if(shiftprop(r)) { // excise(r); // t++; // break; // } break; case AMOVB: case AMOVH: case AMOVW: case AMOVF: case AMOVD: if(regtyp(&p->from)) if(p->from.type == p->to.type) if(p->scond == C_SCOND_NONE) { if(copyprop(g, r)) { excise(r); t++; break; } if(subprop(r) && copyprop(g, r)) { excise(r); t++; break; } } break; case AMOVHS: case AMOVHU: case AMOVBS: case AMOVBU: if(p->from.type == D_REG) { if(shortprop(r)) t++; } break; #ifdef NOTDEF if(p->scond == C_SCOND_NONE) if(regtyp(&p->to)) if(isdconst(&p->from)) { constprop(&p->from, &p->to, r->s1); } break; #endif } } if(t) goto loop1; for(r=g->start; r!=nil; r=r->link) { p = r->prog; switch(p->as) { case AEOR: /* * EOR -1,x,y => MVN x,y */ if(isdconst(&p->from) && 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; } break; } } for(r=g->start; r!=nil; r=r->link) { p = r->prog; switch(p->as) { case AMOVW: case AMOVB: case AMOVBS: case AMOVBU: if(p->from.type == D_OREG && p->from.offset == 0) xtramodes(g, r, &p->from); else if(p->to.type == D_OREG && p->to.offset == 0) xtramodes(g, r, &p->to); else continue; break; // case ACMP: // /* // * elide CMP $0,x if calculation of x can set condition codes // */ // if(isdconst(&p->from) || p->from.offset != 0) // continue; // r2 = r->s1; // if(r2 == nil) // 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 != nil && r1->prog->as == ANOP); // if(r1 == nil) // 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(g); flowend(g); }
void peep(void) { Reg *r, *r1, *r2; Prog *p, *p1; int t; p1 = nil; USED(p1); // ... in unreachable code... /* * complete R structure */ 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; case ADATA: case AGLOBL: case ANAME: case ASIGNAME: p = p->link; } } //dumpit("begin", firstr); loop1: t = 0; for(r=firstr; r!=R; r=r->link) { p = r->prog; switch(p->as) { case ASLL: case ASRL: case ASRA: /* * elide shift into D_SHIFT operand of subsequent instruction */ // if(shiftprop(r)) { // excise(r); // t++; // break; // } break; case AMOVW: case AMOVF: case AMOVD: if(regtyp(&p->from)) if(p->from.type == p->to.type) if(p->scond == C_SCOND_NONE) { if(copyprop(r)) { excise(r); t++; break; } if(subprop(r) && copyprop(r)) { excise(r); t++; break; } } break; #ifdef NOTDEF if(p->scond == C_SCOND_NONE) if(regtyp(&p->to)) if(isdconst(&p->from)) { constprop(&p->from, &p->to, r->s1); } break; #endif } } if(t) goto loop1; return; #ifdef NOTDEF for(r=firstr; r!=R; r=r->link) { p = r->prog; switch(p->as) { // case AEOR: // /* // * EOR -1,x,y => MVN x,y // */ // if(isdconst(&p->from) && 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; // } // break; case AMOVH: case AMOVHU: case AMOVB: case AMOVBU: /* * look for MOVB x,R; MOVB R,R */ if(p->to.type != D_REG) break; if(r1 == R) break; p1 = r1->prog; if(p1->as != p->as) break; if(p1->from.type != D_REG || p1->from.reg != p->to.reg) break; if(p1->to.type != D_REG || p1->to.reg != p->to.reg) break; excise(r1); break; } r1 = r->link; } // 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(isdconst(&p->from) || 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(); #endif }