diff options
Diffstat (limited to 'src/cmd/6g/peep.c')
-rw-r--r-- | src/cmd/6g/peep.c | 673 |
1 files changed, 167 insertions, 506 deletions
diff --git a/src/cmd/6g/peep.c b/src/cmd/6g/peep.c index cd2881ec4..5ccf90103 100644 --- a/src/cmd/6g/peep.c +++ b/src/cmd/6g/peep.c @@ -33,61 +33,50 @@ #include "gg.h" #include "opt.h" -static void conprop(Reg *r); -static void elimshortmov(Reg *r); -static int prevl(Reg *r, int reg); -static void pushback(Reg *r); -static int regconsttyp(Adr*); +static void conprop(Flow *r); +static void elimshortmov(Graph *g); +static int prevl(Flow *r, int reg); +static void pushback(Flow *r); +static int regconsttyp(Adr*); +static int subprop(Flow*); +static int copyprop(Graph*, Flow*); +static int copy1(Adr*, Adr*, Flow*, int); +static int copyas(Adr*, Adr*); +static int copyau(Adr*, Adr*); +static int copysub(Adr*, Adr*, Adr*, int); + +static uint32 gactive; // do we need the carry bit static int needc(Prog *p) { + ProgInfo info; + while(p != P) { - switch(p->as) { - case AADCL: - case AADCQ: - case ASBBL: - case ASBBQ: - case ARCRB: - case ARCRW: - case ARCRL: - case ARCRQ: + proginfo(&info, p); + if(info.flags & UseCarry) return 1; - case AADDB: - case AADDW: - case AADDL: - case AADDQ: - case ASUBB: - case ASUBW: - case ASUBL: - case ASUBQ: - case AJMP: - case ARET: - case ACALL: + if(info.flags & (SetCarry|KillCarry)) return 0; - default: - if(p->to.type == D_BRANCH) - return 0; - } p = p->link; } return 0; } -static Reg* -rnops(Reg *r) +static Flow* +rnops(Flow *r) { Prog *p; - Reg *r1; + Flow *r1; - if(r != R) + if(r != nil) for(;;) { p = r->prog; if(p->as != ANOP || p->from.type != D_NONE || p->to.type != D_NONE) break; r1 = uniqs(r); - if(r1 == R) + if(r1 == nil) break; r = r1; } @@ -95,57 +84,26 @@ rnops(Reg *r) } void -peep(void) +peep(Prog *firstp) { - Reg *r, *r1, *r2; + Flow *r, *r1; + Graph *g; 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; - p->reg = r2; - - r2->p1 = r; - r->s1 = r2; - r2->s1 = r1; - r1->p1 = r2; - - r = r2; - t++; - - case ADATA: - case AGLOBL: - case ANAME: - case ASIGNAME: - case ALOCALS: - case ATYPE: - p = p->link; - } - } - + g = flowstart(firstp, sizeof(Flow)); + if(g == nil) + return; + gactive = 0; + // byte, word arithmetic elimination. - elimshortmov(r); + elimshortmov(g); // constant propagation // find MOV $con,R followed by // another MOV $con,R without // setting R in the interim - for(r=firstr; r!=R; r=r->link) { + for(r=g->start; r!=nil; r=r->link) { p = r->prog; switch(p->as) { case ALEAL: @@ -171,10 +129,10 @@ peep(void) loop1: if(debug['P'] && debug['v']) - dumpit("loop1", firstr); + dumpit("loop1", g->start, 0); t = 0; - for(r=firstr; r!=R; r=r->link) { + for(r=g->start; r!=nil; r=r->link) { p = r->prog; switch(p->as) { case AMOVL: @@ -183,11 +141,11 @@ loop1: case AMOVSD: if(regtyp(&p->to)) if(regtyp(&p->from)) { - if(copyprop(r)) { + if(copyprop(g, r)) { excise(r); t++; } else - if(subprop(r) && copyprop(r)) { + if(subprop(r) && copyprop(g, r)) { excise(r); t++; } @@ -200,7 +158,7 @@ loop1: case AMOVWLSX: if(regtyp(&p->to)) { r1 = rnops(uniqs(r)); - if(r1 != R) { + if(r1 != nil) { p1 = r1->prog; if(p->as == p1->as && p->to.type == p1->from.type){ p1->as = AMOVL; @@ -219,7 +177,7 @@ loop1: case AMOVQL: if(regtyp(&p->to)) { r1 = rnops(uniqs(r)); - if(r1 != R) { + if(r1 != nil) { p1 = r1->prog; if(p->as == p1->as && p->to.type == p1->from.type){ p1->as = AMOVQ; @@ -302,7 +260,7 @@ loop1: // can be replaced by MOVAPD, which moves the pair of float64s // instead of just the lower one. We only use the lower one, but // the processor can do better if we do moves using both. - for(r=firstr; r!=R; r=r->link) { + for(r=g->start; r!=nil; r=r->link) { p = r->prog; if(p->as == AMOVLQZX) if(regtyp(&p->from)) @@ -319,7 +277,7 @@ loop1: // load pipelining // push any load from memory as early as possible // to give it time to complete before use. - for(r=firstr; r!=R; r=r->link) { + for(r=g->start; r!=nil; r=r->link) { p = r->prog; switch(p->as) { case AMOVB: @@ -331,17 +289,19 @@ loop1: pushback(r); } } + + flowend(g); } static void -pushback(Reg *r0) +pushback(Flow *r0) { - Reg *r, *b; + Flow *r, *b; Prog *p0, *p, t; - b = R; + b = nil; p0 = r0->prog; - for(r=uniqp(r0); r!=R && uniqs(r)!=R; r=uniqp(r)) { + for(r=uniqp(r0); r!=nil && uniqs(r)!=nil; r=uniqp(r)) { p = r->prog; if(p->as != ANOP) { if(!regconsttyp(&p->from) || !regtyp(&p->to)) @@ -354,11 +314,11 @@ pushback(Reg *r0) b = r; } - if(b == R) { + if(b == nil) { if(debug['v']) { print("no pushback: %P\n", r0->prog); if(r) - print("\t%P [%d]\n", r->prog, uniqs(r)!=R); + print("\t%P [%d]\n", r->prog, uniqs(r)!=nil); } return; } @@ -401,7 +361,7 @@ pushback(Reg *r0) } void -excise(Reg *r) +excise(Flow *r) { Prog *p; @@ -416,38 +376,6 @@ excise(Reg *r) ostats.ndelmov++; } -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; -} - int regtyp(Adr *a) { @@ -468,13 +396,16 @@ regtyp(Adr *a) // when possible. a movb into a register // can smash the entire 32-bit register without // causing any trouble. +// +// TODO: Using the Q forms here instead of the L forms +// seems unnecessary, and it makes the instructions longer. static void -elimshortmov(Reg *r) +elimshortmov(Graph *g) { Prog *p; + Flow *r; - USED(r); - for(r=firstr; r!=R; r=r->link) { + for(r=g->start; r!=nil; r=r->link) { p = r->prog; if(regtyp(&p->to)) { switch(p->as) { @@ -557,6 +488,7 @@ elimshortmov(Reg *r) } } +// is 'a' a register or constant? static int regconsttyp(Adr *a) { @@ -574,38 +506,21 @@ regconsttyp(Adr *a) // is reg guaranteed to be truncated by a previous L instruction? static int -prevl(Reg *r0, int reg) +prevl(Flow *r0, int reg) { Prog *p; - Reg *r; + Flow *r; + ProgInfo info; - for(r=uniqp(r0); r!=R; r=uniqp(r)) { + for(r=uniqp(r0); r!=nil; r=uniqp(r)) { p = r->prog; if(p->to.type == reg) { - switch(p->as) { - case AADDL: - case AANDL: - case ADECL: - case ADIVL: - case AIDIVL: - case AIMULL: - case AINCL: - case AMOVL: - case AMULL: - case AORL: - case ARCLL: - case ARCRL: - case AROLL: - case ARORL: - case ASALL: - case ASARL: - case ASHLL: - case ASHRL: - case ASUBL: - case AXORL: - return 1; + proginfo(&info, p); + if(info.flags & RightWrite) { + if(info.flags & SizeL) + return 1; + return 0; } - return 0; } } return 0; @@ -625,12 +540,13 @@ prevl(Reg *r0, int reg) * hopefully, then the former or latter MOV * will be eliminated by copy propagation. */ -int -subprop(Reg *r0) +static int +subprop(Flow *r0) { Prog *p; + ProgInfo info; Adr *v1, *v2; - Reg *r; + Flow *r; int t; if(debug['P'] && debug['v']) @@ -648,104 +564,31 @@ subprop(Reg *r0) print("\tnot regtype %D; return 0\n", v2); return 0; } - for(r=uniqp(r0); r!=R; r=uniqp(r)) { + for(r=uniqp(r0); r!=nil; r=uniqp(r)) { if(debug['P'] && debug['v']) print("\t? %P\n", r->prog); - if(uniqs(r) == R) { + if(uniqs(r) == nil) { if(debug['P'] && debug['v']) print("\tno unique successor\n"); break; } p = r->prog; - switch(p->as) { - case ACALL: + proginfo(&info, p); + if(info.flags & Call) { if(debug['P'] && debug['v']) print("\tfound %P; return 0\n", p); return 0; + } - case AIMULL: - case AIMULQ: - case AIMULW: - if(p->to.type != D_NONE) - break; - goto giveup; - - case ARCLB: - case ARCLL: - case ARCLQ: - case ARCLW: - case ARCRB: - case ARCRL: - case ARCRQ: - case ARCRW: - case AROLB: - case AROLL: - case AROLQ: - case AROLW: - case ARORB: - case ARORL: - case ARORQ: - case ARORW: - case ASALB: - case ASALL: - case ASALQ: - case ASALW: - case ASARB: - case ASARL: - case ASARQ: - case ASARW: - case ASHLB: - case ASHLL: - case ASHLQ: - case ASHLW: - case ASHRB: - case ASHRL: - case ASHRQ: - case ASHRW: - if(p->from.type == D_CONST) - break; - goto giveup; - - case ADIVB: - case ADIVL: - case ADIVQ: - case ADIVW: - case AIDIVB: - case AIDIVL: - case AIDIVQ: - case AIDIVW: - case AIMULB: - case AMULB: - case AMULL: - case AMULQ: - case AMULW: - - case AREP: - case AREPN: - - case ACWD: - case ACDQ: - case ACQO: - - case ASTOSB: - case ASTOSL: - case ASTOSQ: - case AMOVSB: - case AMOVSL: - case AMOVSQ: - giveup: + if(info.reguse | info.regset) { if(debug['P'] && debug['v']) print("\tfound %P; return 0\n", p); return 0; - - case AMOVL: - case AMOVQ: - case AMOVSS: - case AMOVSD: - if(p->to.type == v1->type) - goto gotit; - break; } + + if((info.flags & Move) && (info.flags & (SizeL|SizeQ|SizeF|SizeD)) && p->to.type == v1->type) + goto gotit; + if(copyau(&p->from, v2) || copyau(&p->to, v2)) { if(debug['P'] && debug['v']) @@ -798,13 +641,13 @@ gotit: * set v1 F=1 * set v2 return success */ -int -copyprop(Reg *r0) +static int +copyprop(Graph *g, Flow *r0) { Prog *p; Adr *v1, *v2; - Reg *r; + USED(g); if(debug['P'] && debug['v']) print("copyprop %P\n", r0->prog); p = r0->prog; @@ -812,37 +655,36 @@ copyprop(Reg *r0) v2 = &p->to; if(copyas(v1, v2)) return 1; - for(r=firstr; r!=R; r=r->link) - r->active = 0; + gactive++; return copy1(v1, v2, r0->s1, 0); } -int -copy1(Adr *v1, Adr *v2, Reg *r, int f) +static int +copy1(Adr *v1, Adr *v2, Flow *r, int f) { int t; Prog *p; - if(r->active) { + if(r->active == gactive) { if(debug['P']) print("act set; return 1\n"); return 1; } - r->active = 1; + r->active = gactive; if(debug['P']) print("copy %D->%D f=%d\n", v1, v2, f); - for(; r != R; r = r->s1) { + for(; r != nil; r = r->s1) { p = r->prog; if(debug['P']) print("%P", p); - if(!f && uniqp(r) == R) { + if(!f && uniqp(r) == nil) { f = 1; if(debug['P']) print("; merge; f=%d", f); } t = copyu(p, v2, A); switch(t) { - case 2: /* rar, cant split */ + case 2: /* rar, can't split */ if(debug['P']) print("; %D rar; return 0\n", v2); return 0; @@ -905,255 +747,10 @@ copy1(Adr *v1, Adr *v2, Reg *r, int f) int copyu(Prog *p, Adr *v, Adr *s) { + ProgInfo info; switch(p->as) { - - default: - if(debug['P']) - print("unknown op %A\n", p->as); - /* SBBL; ADCL; FLD1; SAHF */ - return 2; - - - case ANEGB: - case ANEGW: - case ANEGL: - case ANEGQ: - case ANOTB: - case ANOTW: - case ANOTL: - case ANOTQ: - if(copyas(&p->to, v)) - return 2; - break; - - case ALEAL: /* lhs addr, rhs store */ - case ALEAQ: - if(copyas(&p->from, v)) - return 2; - - - case ANOP: /* rhs store */ - case AMOVL: - case AMOVQ: - case AMOVBLSX: - case AMOVBLZX: - case AMOVBQSX: - case AMOVBQZX: - case AMOVLQSX: - case AMOVLQZX: - case AMOVWLSX: - case AMOVWLZX: - case AMOVWQSX: - case AMOVWQZX: - case AMOVQL: - - case AMOVSS: - case AMOVSD: - case ACVTSD2SL: - case ACVTSD2SQ: - case ACVTSD2SS: - case ACVTSL2SD: - case ACVTSL2SS: - case ACVTSQ2SD: - case ACVTSQ2SS: - case ACVTSS2SD: - case ACVTSS2SL: - case ACVTSS2SQ: - case ACVTTSD2SL: - case ACVTTSD2SQ: - case ACVTTSS2SL: - case ACVTTSS2SQ: - if(copyas(&p->to, v)) { - if(s != A) - return copysub(&p->from, v, s, 1); - if(copyau(&p->from, v)) - return 4; - return 3; - } - goto caseread; - - case ARCLB: - case ARCLL: - case ARCLQ: - case ARCLW: - case ARCRB: - case ARCRL: - case ARCRQ: - case ARCRW: - case AROLB: - case AROLL: - case AROLQ: - case AROLW: - case ARORB: - case ARORL: - case ARORQ: - case ARORW: - case ASALB: - case ASALL: - case ASALQ: - case ASALW: - case ASARB: - case ASARL: - case ASARQ: - case ASARW: - case ASHLB: - case ASHLL: - case ASHLQ: - case ASHLW: - case ASHRB: - case ASHRL: - case ASHRQ: - case ASHRW: - if(copyas(&p->to, v)) - return 2; - if(copyas(&p->from, v)) - if(p->from.type == D_CX) - return 2; - goto caseread; - - case AADDB: /* rhs rar */ - case AADDL: - case AADDQ: - case AADDW: - case AANDB: - case AANDL: - case AANDQ: - case AANDW: - case ADECL: - case ADECQ: - case ADECW: - case AINCL: - case AINCQ: - case AINCW: - case ASUBB: - case ASUBL: - case ASUBQ: - case ASUBW: - case AORB: - case AORL: - case AORQ: - case AORW: - case AXORB: - case AXORL: - case AXORQ: - case AXORW: - case AMOVB: - case AMOVW: - - case AADDSD: - case AADDSS: - case ACMPSD: - case ACMPSS: - case ADIVSD: - case ADIVSS: - case AMAXSD: - case AMAXSS: - case AMINSD: - case AMINSS: - case AMULSD: - case AMULSS: - case ARCPSS: - case ARSQRTSS: - case ASQRTSD: - case ASQRTSS: - case ASUBSD: - case ASUBSS: - case AXORPD: - if(copyas(&p->to, v)) - return 2; - goto caseread; - - case ACMPL: /* read only */ - case ACMPW: - case ACMPB: - case ACMPQ: - - case ACOMISD: - case ACOMISS: - case AUCOMISD: - case AUCOMISS: - caseread: - 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; - - case AJGE: /* no reference */ - case AJNE: - case AJLE: - case AJEQ: - case AJHI: - case AJLS: - case AJMI: - case AJPL: - case AJGT: - case AJLT: - case AJCC: - case AJCS: - - case AADJSP: - case AWAIT: - case ACLD: - break; - - case AIMULL: - case AIMULQ: - case AIMULW: - if(p->to.type != D_NONE) { - if(copyas(&p->to, v)) - return 2; - goto caseread; - } - - case ADIVB: - case ADIVL: - case ADIVQ: - case ADIVW: - case AIDIVB: - case AIDIVL: - case AIDIVQ: - case AIDIVW: - case AIMULB: - case AMULB: - case AMULL: - case AMULQ: - case AMULW: - - case ACWD: - case ACDQ: - case ACQO: - if(v->type == D_AX || v->type == D_DX) - return 2; - goto caseread; - - case AREP: - case AREPN: - if(v->type == D_CX) - return 2; - goto caseread; - - case AMOVSB: - case AMOVSL: - case AMOVSQ: - if(v->type == D_DI || v->type == D_SI) - return 2; - goto caseread; - - case ASTOSB: - case ASTOSL: - case ASTOSQ: - if(v->type == D_AX || v->type == D_DI) - return 2; - goto caseread; - - case AJMP: /* funny */ + case AJMP: if(s != A) { if(copysub(&p->to, v, s, 1)) return 1; @@ -1163,12 +760,12 @@ copyu(Prog *p, Adr *v, Adr *s) return 1; return 0; - case ARET: /* funny */ + case ARET: if(s != A) return 1; return 3; - case ACALL: /* funny */ + case ACALL: if(REGEXT && v->type <= REGEXT && v->type > exregoffset) return 2; if(REGARG >= 0 && v->type == (uchar)REGARG) @@ -1185,11 +782,47 @@ copyu(Prog *p, Adr *v, Adr *s) return 4; return 3; - case ATEXT: /* funny */ + case ATEXT: if(REGARG >= 0 && v->type == (uchar)REGARG) return 3; return 0; } + + proginfo(&info, p); + + if((info.reguse|info.regset) & RtoB(v->type)) + return 2; + + if(info.flags & LeftAddr) + if(copyas(&p->from, v)) + return 2; + + if((info.flags & (RightRead|RightWrite)) == (RightRead|RightWrite)) + if(copyas(&p->to, v)) + return 2; + + if(info.flags & RightWrite) { + if(copyas(&p->to, v)) { + if(s != A) + return copysub(&p->from, v, s, 1); + if(copyau(&p->from, v)) + return 4; + return 3; + } + } + + if(info.flags & (LeftAddr|LeftRead|LeftWrite|RightAddr|RightRead|RightWrite)) { + 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; + } + return 0; } @@ -1198,7 +831,7 @@ copyu(Prog *p, Adr *v, Adr *s) * could be set/use depending on * semantics */ -int +static int copyas(Adr *a, Adr *v) { if(a->type != v->type) @@ -1211,10 +844,23 @@ copyas(Adr *a, Adr *v) return 0; } +int +sameaddr(Addr *a, Addr *v) +{ + if(a->type != v->type) + return 0; + if(regtyp(v)) + return 1; + if(v->type == D_AUTO || v->type == D_PARAM) + if(v->offset == a->offset) + return 1; + return 0; +} + /* * either direct or indirect */ -int +static int copyau(Adr *a, Adr *v) { @@ -1242,7 +888,7 @@ copyau(Adr *a, Adr *v) * substitute s for v in a * return failure to substitute */ -int +static int copysub(Adr *a, Adr *v, Adr *s, int f) { int t; @@ -1275,9 +921,9 @@ copysub(Adr *a, Adr *v, Adr *s, int f) } static void -conprop(Reg *r0) +conprop(Flow *r0) { - Reg *r; + Flow *r; Prog *p, *p0; int t; Adr *v0; @@ -1288,9 +934,9 @@ conprop(Reg *r0) loop: r = uniqs(r); - if(r == R || r == r0) + if(r == nil || r == r0) return; - if(uniqp(r) == R) + if(uniqp(r) == nil) return; p = r->prog; @@ -1318,3 +964,18 @@ loop: break; } } + +int +smallindir(Addr *a, Addr *reg) +{ + return regtyp(reg) && + a->type == D_INDIR + reg->type && + a->index == D_NONE && + 0 <= a->offset && a->offset < 4096; +} + +int +stackaddr(Addr *a) +{ + return regtyp(a) && a->type == D_SP; +} |