From e081f25c3e602804fc3bd0780e09bf35d2a098cb Mon Sep 17 00:00:00 2001 From: Ken Thompson Date: Sat, 22 Nov 2008 17:58:53 -0800 Subject: [PATCH] reg and peep R=r OCL=19871 CL=19871 --- src/cmd/6g/cgen.c | 8 +- src/cmd/6g/gen.c | 36 ++++++++- src/cmd/6g/gsubr.c | 140 ++++++++++++++++++++++------------- src/cmd/6g/opt.h | 25 ++++--- src/cmd/6g/peep.c | 30 ++++++-- src/cmd/6g/reg.c | 181 +++++++++++++++++++++++++++++++-------------- src/cmd/gc/go.h | 1 + src/cmd/gc/walk.c | 15 +++- 8 files changed, 306 insertions(+), 130 deletions(-) diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c index 4fb9e3415d..d6f27a9296 100644 --- a/src/cmd/6g/cgen.c +++ b/src/cmd/6g/cgen.c @@ -176,12 +176,14 @@ cgen(Node *n, Node *res) gins(optoas(OCMP, types[tptr]), &n1, &n2); p1 = gbranch(optoas(OEQ, types[tptr]), T); - n1.op = OINDREG; - n1.type = types[TINT32]; - gmove(&n1, res); + n2 = n1; + n2.op = OINDREG; + n2.type = types[TINT32]; + gmove(&n2, &n1); patch(p1, pc); + gmove(&n1, res); regfree(&n1); break; } diff --git a/src/cmd/6g/gen.c b/src/cmd/6g/gen.c index 4851f5ad9c..3d47360be8 100644 --- a/src/cmd/6g/gen.c +++ b/src/cmd/6g/gen.c @@ -100,9 +100,8 @@ if(throwreturn == N) { pc->as = ARET; // overwrite AEND pc->lineno = lineno; - if(debug['N']) { + if(!debug['N'] || debug['R'] || debug['P']) regopt(ptxt); - } // fill in argument size ptxt->to.offset = rnd(curfn->type->argwid, maxround); @@ -918,6 +917,33 @@ cgen_asop(Node *n) nl = n->left; nr = n->right; + if(nl->addable && nr->op == OLITERAL) + switch(n->etype) { + case OADD: + if(!isint[nl->type->etype]) + goto com; + if(mpgetfix(nr->val.u.xval) != 1) + goto com; + gins(optoas(OINC, nl->type), N, nl); + goto ret; + case OSUB: + if(!isint[nl->type->etype]) + goto com; + if(mpgetfix(nr->val.u.xval) != 1) + goto com; + gins(optoas(ODEC, nl->type), N, nl); + goto ret; + + com: + case OXOR: + case OAND: + case OOR: + if(!isint[nl->type->etype]) + break; + gins(optoas(n->etype, nl->type), nr, nl); + goto ret; + } + if(nr->ullman >= UINF && nl->ullman >= UINF) { tempname(&n1, nr->type); cgen(nr, &n1); @@ -960,10 +986,12 @@ cgen_as(Node *nl, Node *nr, int op) Node nc, n1; Type *tl; uint32 w, c; + int iszer; if(nl == N) return; + iszer = 0; if(nr == N || isnil(nr)) { if(nl->op == OLIST) { cgen_as(nl->left, nr, op); @@ -1008,6 +1036,7 @@ cgen_as(Node *nl, Node *nr, int op) } /* invent a "zero" for the rhs */ + iszer = 1; nr = &nc; memset(nr, 0, sizeof(*nr)); switch(tl->etype) { @@ -1062,6 +1091,9 @@ cgen_as(Node *nl, Node *nr, int op) return; cgen(nr, nl); + if(iszer && nl->addable) + gins(ANOP, nl, N); // used + ret: ; diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c index 62e986a169..273e10f873 100644 --- a/src/cmd/6g/gsubr.c +++ b/src/cmd/6g/gsubr.c @@ -383,7 +383,7 @@ gmove(Node *f, Node *t) case TPTR32: a = AMOVL; if(t64) - a = AMOVLQZX; /* could probably use plain MOVL */ + a = AMOVLQZX; goto ld; case TINT64: if(isfloat[tt]) { @@ -480,50 +480,50 @@ gmove(Node *f, Node *t) /* * integer to integer ******** - a = AGOK; break; + * a = AGOK; break; - case CASE(TBOOL, TBOOL): - case CASE(TINT8, TBOOL): - case CASE(TUINT8, TBOOL): - case CASE(TINT16, TBOOL): - case CASE(TUINT16, TBOOL): - case CASE(TINT32, TBOOL): - case CASE(TUINT32, TBOOL): - case CASE(TPTR64, TBOOL): + * case CASE(TBOOL, TBOOL): + * case CASE(TINT8, TBOOL): + * case CASE(TUINT8, TBOOL): + * case CASE(TINT16, TBOOL): + * case CASE(TUINT16, TBOOL): + * case CASE(TINT32, TBOOL): + * case CASE(TUINT32, TBOOL): + * case CASE(TPTR64, TBOOL): - case CASE(TBOOL, TINT8): - case CASE(TINT8, TINT8): - case CASE(TUINT8, TINT8): - case CASE(TINT16, TINT8): - case CASE(TUINT16, TINT8): - case CASE(TINT32, TINT8): - case CASE(TUINT32, TINT8): - case CASE(TPTR64, TINT8): + * case CASE(TBOOL, TINT8): + * case CASE(TINT8, TINT8): + * case CASE(TUINT8, TINT8): + * case CASE(TINT16, TINT8): + * case CASE(TUINT16, TINT8): + * case CASE(TINT32, TINT8): + * case CASE(TUINT32, TINT8): + * case CASE(TPTR64, TINT8): - case CASE(TBOOL, TUINT8): - case CASE(TINT8, TUINT8): - case CASE(TUINT8, TUINT8): - case CASE(TINT16, TUINT8): - case CASE(TUINT16, TUINT8): - case CASE(TINT32, TUINT8): - case CASE(TUINT32, TUINT8): - case CASE(TPTR64, TUINT8): + * case CASE(TBOOL, TUINT8): + * case CASE(TINT8, TUINT8): + * case CASE(TUINT8, TUINT8): + * case CASE(TINT16, TUINT8): + * case CASE(TUINT16, TUINT8): + * case CASE(TINT32, TUINT8): + * case CASE(TUINT32, TUINT8): + * case CASE(TPTR64, TUINT8): - case CASE(TINT16, TINT16): - case CASE(TUINT16, TINT16): - case CASE(TINT32, TINT16): - case CASE(TUINT32, TINT16): - case CASE(TPTR64, TINT16): + * case CASE(TINT16, TINT16): + * case CASE(TUINT16, TINT16): + * case CASE(TINT32, TINT16): + * case CASE(TUINT32, TINT16): + * case CASE(TPTR64, TINT16): - case CASE(TINT16, TUINT16): - case CASE(TUINT16, TUINT16): - case CASE(TINT32, TUINT16): - case CASE(TUINT32, TUINT16): - case CASE(TPTR64, TUINT16): + * case CASE(TINT16, TUINT16): + * case CASE(TUINT16, TUINT16): + * case CASE(TINT32, TUINT16): + * case CASE(TUINT32, TUINT16): + * case CASE(TPTR64, TUINT16): - case CASE(TINT64, TUINT): - case CASE(TINT64, TUINT32): - case CASE(TUINT64, TUINT32): + * case CASE(TINT64, TUINT): + * case CASE(TINT64, TUINT32): + * case CASE(TUINT64, TUINT32): *****/ a = AMOVL; break; @@ -534,25 +534,21 @@ gmove(Node *f, Node *t) case CASE(TUINT64, TINT8): case CASE(TUINT64, TINT16): case CASE(TUINT64, TINT32): + a = AMOVLQSX; // this looks bad + break; + case CASE(TINT32, TINT64): case CASE(TINT32, TPTR64): a = AMOVLQSX; -// if(f->op == OCONST) { -// f->val.vval &= (uvlong)0xffffffffU; -// if(f->val.vval & 0x80000000) -// f->val.vval |= (vlong)0xffffffff << 32; -// a = AMOVQ; -// } break; case CASE(TUINT32, TINT64): case CASE(TUINT32, TUINT64): case CASE(TUINT32, TPTR64): - a = AMOVL; /* same effect as AMOVLQZX */ -// if(f->op == OCONST) { -// f->val.vval &= (uvlong)0xffffffffU; -// a = AMOVQ; -// } + case CASE(TPTR32, TINT64): + case CASE(TPTR32, TUINT64): + case CASE(TPTR32, TPTR64): + a = AMOVLQZX; break; case CASE(TPTR64, TINT64): @@ -1239,6 +1235,50 @@ optoas(int op, Type *t) a = ASUBSD; break; + case CASE(OINC, TINT8): + case CASE(OINC, TUINT8): + a = AINCB; + break; + + case CASE(OINC, TINT16): + case CASE(OINC, TUINT16): + a = AINCW; + break; + + case CASE(OINC, TINT32): + case CASE(OINC, TUINT32): + case CASE(OINC, TPTR32): + a = AINCL; + break; + + case CASE(OINC, TINT64): + case CASE(OINC, TUINT64): + case CASE(OINC, TPTR64): + a = AINCQ; + break; + + case CASE(ODEC, TINT8): + case CASE(ODEC, TUINT8): + a = ADECB; + break; + + case CASE(ODEC, TINT16): + case CASE(ODEC, TUINT16): + a = ADECW; + break; + + case CASE(ODEC, TINT32): + case CASE(ODEC, TUINT32): + case CASE(ODEC, TPTR32): + a = ADECL; + break; + + case CASE(ODEC, TINT64): + case CASE(ODEC, TUINT64): + case CASE(ODEC, TPTR64): + a = ADECQ; + break; + case CASE(OMINUS, TINT8): case CASE(OMINUS, TUINT8): a = ANEGB; diff --git a/src/cmd/6g/opt.h b/src/cmd/6g/opt.h index a73e45ffc7..571bcd6cb7 100644 --- a/src/cmd/6g/opt.h +++ b/src/cmd/6g/opt.h @@ -60,7 +60,6 @@ struct Bits uint32 b[BITS]; }; - struct Reg { @@ -75,14 +74,12 @@ struct Reg Bits regdiff; Bits act; - int32 regu; - int32 loop; /* could be shorter */ - int32 rpo; /* reverse post ordering */ + int32 regu; // register used bitmap + int32 rpo; // reverse post ordering int32 active; -// uint32 magic; -// int32 pc; -// Reg* log5; + uint16 loop; // x5 for every loop + uchar refset; // diagnostic generated Reg* p1; Reg* p2; @@ -130,10 +127,9 @@ EXTERN Bits externs; EXTERN Bits params; EXTERN Bits consts; EXTERN Bits addrs; +EXTERN Bits ovar; EXTERN int change; EXTERN Bits zbits; -EXTERN uchar typechlpfd[NTYPE]; // botch -EXTERN uchar typev[NTYPE]; // botch EXTERN int32 maxnr; EXTERN int32* idom; @@ -150,6 +146,15 @@ int beq(Bits, Bits); int bset(Bits, uint); int Qconv(Fmt *fp); int bitno(int32); +struct +{ + int32 ncvtreg; + int32 nspill; + int32 nreload; + int32 ndelmov; + int32 nvar; + int32 naddr; +} ostats; /* * reg.c @@ -167,6 +172,8 @@ void paint1(Reg*, int); uint32 paint2(Reg*, int); void paint3(Reg*, int, int32, int); void addreg(Adr*, int); +void dumpit(char *str, Reg *r0); +int noreturn(Prog *p); /* * peep.c diff --git a/src/cmd/6g/peep.c b/src/cmd/6g/peep.c index b85e88d158..cdf8a8bc35 100644 --- a/src/cmd/6g/peep.c +++ b/src/cmd/6g/peep.c @@ -31,6 +31,7 @@ #include "gg.h" #include "opt.h" + static int needc(Prog *p) { @@ -67,7 +68,7 @@ rnops(Reg *r) Reg *r1; if(r != R) - for(;;){ + for(;;) { p = r->prog; if(p->as != ANOP || p->from.type != D_NONE || p->to.type != D_NONE) break; @@ -103,6 +104,8 @@ peep(void) r2->link = r1; r2->prog = p; + p->reg = r2; + r2->p1 = r; r->s1 = r2; r2->s1 = r1; @@ -119,10 +122,11 @@ peep(void) } } - pc = 0; /* speculating it won't kill */ - loop1: + if(debug['P'] && debug['v']) + dumpit("loop1", firstr); + t = 0; for(r=firstr; r!=R; r=r->link) { p = r->prog; @@ -186,13 +190,15 @@ loop1: if(p->from.offset == -1){ if(p->as == AADDQ) p->as = ADECQ; - else if(p->as == AADDL) + else + if(p->as == AADDL) p->as = ADECL; else p->as = ADECW; p->from = zprog.from; } - else if(p->from.offset == 1){ + else + if(p->from.offset == 1){ if(p->as == AADDQ) p->as = AINCQ; else if(p->as == AADDL) @@ -211,16 +217,19 @@ loop1: if(p->from.offset == -1) { if(p->as == ASUBQ) p->as = AINCQ; - else if(p->as == ASUBL) + else + if(p->as == ASUBL) p->as = AINCL; else p->as = AINCW; p->from = zprog.from; } - else if(p->from.offset == 1){ + else + if(p->from.offset == 1){ if(p->as == ASUBQ) p->as = ADECQ; - else if(p->as == ASUBL) + else + if(p->as == ASUBL) p->as = ADECL; else p->as = ADECW; @@ -239,9 +248,14 @@ excise(Reg *r) Prog *p; p = r->prog; + if(debug['P'] && debug['v']) + print("%P ===delete===\n", p); + p->as = ANOP; p->from = zprog.from; p->to = zprog.to; + + ostats.ndelmov++; } Reg* diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c index 3e319919db..0715faa097 100644 --- a/src/cmd/6g/reg.c +++ b/src/cmd/6g/reg.c @@ -34,11 +34,8 @@ #include "opt.h" #define P2R(p) (Reg*)(p->reg) -#define MAGIC 0xb00fbabe static int first = 1; -static void dumpit(char *str, Reg *r0); -static int noreturn(Prog *p); Reg* rega(void) @@ -70,6 +67,30 @@ rcmp(const void *a1, const void *a2) return p2->varno - p1->varno; } +void +setoutvar(void) +{ + Type *t; + Node *n; + Addr a; + Iter save; + Bits bit; + int z; + + t = structfirst(&save, getoutarg(curfn->type)); + while(t != T) { + n = nodarg(t, 1); + a = zprog.from; + naddr(n, &a); + bit = mkvar(R, &a); + for(z=0; zs2 = r1; @@ -404,7 +440,9 @@ regopt(Prog *firstp) r1->p2 = r; } } -//dumpit("pass2", firstr); + + if(debug['R'] && debug['v']) + dumpit("pass2", firstr); /* * pass 2.5 @@ -414,7 +452,9 @@ regopt(Prog *firstp) r->active = 0; change = 0; loopit(firstr, nr); -//dumpit("pass2.5", firstr); + + if(debug['R'] && debug['v']) + dumpit("pass2.5", firstr); /* * pass 3 @@ -443,7 +483,8 @@ loop11: if(change) goto loop1; -//dumpit("pass3", firstr); + if(debug['R'] && debug['v']) + dumpit("pass3", firstr); /* * pass 4 @@ -458,7 +499,8 @@ loop2: if(change) goto loop2; -//dumpit("pass4", firstr); + if(debug['R'] && debug['v']) + dumpit("pass4", firstr); /* * pass 5 @@ -470,10 +512,11 @@ loop2: for(z=0; zrefahead.b[z] | r->calahead.b[z]) & ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]); - if(bany(&bit)) { - warn("used and not set: %Q", bit); - if(debug['R'] && !debug['w']) - print("used and not set: %Q\n", bit); + if(bany(&bit) && !r->refset) { + // should never happen - all variables are preset + if(debug['w']) + print("%L: used and not set: %Q\n", r->prog->lineno, bit); + r->refset = 1; } } for(r = firstr; r != R; r = r->link) @@ -484,10 +527,10 @@ loop2: for(z=0; zset.b[z] & ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]); - if(bany(&bit)) { - warn("set and not used: %Q", bit); - if(debug['R']) - print("set and not used: %Q\n", bit); + if(bany(&bit) && !r->refset) { + if(debug['w']) + print("%L: set and not used: %Q\n", r->prog->lineno, bit); + r->refset = 1; excise(r); } for(z=0; zenter = r; rgp->varno = i; change = 0; - if(debug['R'] && debug['v']) - print("\n"); paint1(r, i); bit.b[i/32] &= ~(1L<<(i%32)); - if(change <= 0) { - if(debug['R']) - print("%L$%d: %Q\n", - r->prog->lineno, change, blsh(i)); + if(change <= 0) continue; - } rgp->cost = change; nregion++; if(nregion >= NRGN) { - fatal("too many regions"); + if(debug['R'] && debug['v']) + print("too many regions\n"); goto brk; } rgp++; @@ -534,11 +572,14 @@ brk: rgp++; } + if(debug['R'] && debug['v']) + dumpit("pass6", firstr); + /* * pass 7 * peep-hole on basic block */ - if(debug['P']) { + if(!debug['R'] || debug['P']) { peep(); } @@ -547,14 +588,43 @@ brk: * free aux structures */ for(p=firstp; p!=P; p=p->link) { - while(p->link && p->link->as == ANOP) + while(p->link != P && p->link->as == ANOP) p->link = p->link->link; + if(p->to.type == D_BRANCH) + while(p->to.branch != P && p->to.branch->as == ANOP) + p->to.branch = p->to.branch->link; } if(r1 != R) { r1->link = freer; freer = firstr; } + + if(debug['R']) { + if(ostats.ncvtreg || + ostats.nspill || + ostats.nreload || + ostats.ndelmov || + ostats.nvar || + ostats.naddr || + 0) + print("\nstats\n"); + + if(ostats.ncvtreg) + print(" %4ld cvtreg\n", ostats.ncvtreg); + if(ostats.nspill) + print(" %4ld spill\n", ostats.nspill); + if(ostats.nreload) + print(" %4ld reload\n", ostats.nreload); + if(ostats.ndelmov) + print(" %4ld delmov\n", ostats.ndelmov); + if(ostats.nvar) + print(" %4ld delmov\n", ostats.nvar); + if(ostats.naddr) + print(" %4ld delmov\n", ostats.naddr); + + memset(&ostats, 0, sizeof(ostats)); + } } /* @@ -585,7 +655,7 @@ addmove(Reg *r, int bn, int rn, int f) a->etype = v->etype; a->type = v->name; - // need to chean this up with wptr and + // need to clean this up with wptr and // some of the defaults p1->as = AMOVL; switch(v->etype) { @@ -611,7 +681,7 @@ addmove(Reg *r, int bn, int rn, int f) p1->as = AMOVSS; break; case TFLOAT64: - p1->as = AMOVSS; + p1->as = AMOVSD; break; case TINT: case TUINT: @@ -631,8 +701,9 @@ addmove(Reg *r, int bn, int rn, int f) if(v->etype == TUINT16) p1->as = AMOVW; } -// if(debug['R']) - print("%P\t.a%P\n", p, p1); + if(debug['R'] && debug['v']) + print("%P ===add=== %P\n", p, p1); + ostats.nspill++; } uint32 @@ -670,8 +741,10 @@ mkvar(Reg *r, Adr *a) * mark registers used */ t = a->type; - r->regu |= doregbits(t); - r->regu |= doregbits(a->index); + if(r != R) { + r->regu |= doregbits(t); + r->regu |= doregbits(a->index); + } switch(t) { default: @@ -682,6 +755,7 @@ mkvar(Reg *r, Adr *a) for(z=0; ztype = t; + ostats.naddr++; goto none; case D_EXTERN: case D_STATIC: @@ -727,6 +801,7 @@ mkvar(Reg *r, Adr *a) v->etype = et; if(debug['R']) print("bit=%2d et=%2d %D\n", i, et, a); + ostats.nvar++; out: bit = blsh(i); @@ -738,7 +813,8 @@ out: params.b[z] |= bit.b[z]; if(v->etype != et) { /* funny punning */ -print("pun %d %d %S\n", v->etype, et, s); + if(debug['R']) + print("pun %d %d %S\n", v->etype, et, s); for(z=0; zset.b[z]) | @@ -1044,9 +1121,6 @@ paint1(Reg *r, int bn) if(LOAD(r) & ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z])) & bb) { change -= CLOAD * r->loop; - if(debug['R'] && debug['v']) - print("%ld%P\tld %Q $%d\n", r->loop, - r->prog, blsh(bn), change); } for(;;) { r->act.b[z] |= bb; @@ -1054,23 +1128,14 @@ paint1(Reg *r, int bn) if(r->use1.b[z] & bb) { change += CREF * r->loop; - if(debug['R'] && debug['v']) - print("%ld%P\tu1 %Q $%d\n", r->loop, - p, blsh(bn), change); } if((r->use2.b[z]|r->set.b[z]) & bb) { change += CREF * r->loop; - if(debug['R'] && debug['v']) - print("%ld%P\tu2 %Q $%d\n", r->loop, - p, blsh(bn), change); } if(STORE(r) & r->regdiff.b[z] & bb) { change -= CLOAD * r->loop; - if(debug['R'] && debug['v']) - print("%ld%P\tst %Q $%d\n", r->loop, - p, blsh(bn), change); } if(r->refbehind.b[z] & bb) @@ -1226,18 +1291,18 @@ paint3(Reg *r, int bn, int32 rb, int rn) p = r->prog; if(r->use1.b[z] & bb) { - if(debug['R']) + if(debug['R'] && debug['v']) print("%P", p); addreg(&p->from, rn); - if(debug['R']) - print("\t.c%P\n", p); + if(debug['R'] && debug['v']) + print(" ===change== %P\n", p); } if((r->use2.b[z]|r->set.b[z]) & bb) { - if(debug['R']) + if(debug['R'] && debug['v']) print("%P", p); addreg(&p->to, rn); - if(debug['R']) - print("\t.c%P\n", p); + if(debug['R'] && debug['v']) + print(" ===change== %P\n", p); } if(STORE(r) & r->regdiff.b[z] & bb) @@ -1272,6 +1337,8 @@ addreg(Adr *a, int rn) a->sym = 0; a->offset = 0; a->type = rn; + + ostats.ncvtreg++; } int32 @@ -1286,8 +1353,7 @@ RtoB(int r) int BtoR(int32 b) { - - b &= 0xffffL; + b &= 0x3fffL; // no R14 or R15 if(b == 0) return 0; return bitno(b) + D_AX; @@ -1317,7 +1383,7 @@ BtoF(int32 b) return bitno(b) - 16 + FREGMIN; } -static void +void dumpit(char *str, Reg *r0) { Reg *r, *r1; @@ -1380,7 +1446,7 @@ dumpit(char *str, Reg *r0) static Sym* symlist[10]; -static int +int noreturn(Prog *p) { Sym *s; @@ -1388,6 +1454,7 @@ noreturn(Prog *p) if(symlist[0] == S) { symlist[0] = pkglookup("throwindex", "sys"); + symlist[1] = pkglookup("panicl", "sys"); } s = p->to.sym; diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index c5e35a1e48..ce1d4cee50 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -284,6 +284,7 @@ enum OEQ, ONE, OLT, OLE, OGE, OGT, OADD, OSUB, OOR, OXOR, OMUL, ODIV, OMOD, OLSH, ORSH, OAND, + OINC, ODEC, // placeholders - not used OFUNC, OLABEL, OBREAK, diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index 685267c279..1c87e05eb0 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -1094,7 +1094,20 @@ loop: goto ret; nottop: - yyerror("didn't expect %O here", n->op); + switch(top) { + default: + yyerror("didn't expect %O here", n->op); + break; + case Etop: + yyerror("operation %O not allowed in statement context", n->op); + break; + case Elv: + yyerror("operation %O not allowed in assignment context", n->op); + break; + case Erv: + yyerror("operation %O not allowed in expression context", n->op); + break; + } goto ret; badt: