From 23fc0ac061e559995d710069312a2ffb953ed8fe Mon Sep 17 00:00:00 2001 From: Ken Thompson Date: Sun, 14 Dec 2008 17:06:06 -0800 Subject: [PATCH] more code optimization R=r OCL=21159 CL=21159 --- src/cmd/6g/cgen.c | 25 ++-- src/cmd/6g/gg.h | 4 +- src/cmd/6g/gsubr.c | 299 +++++++++++++++++++++++++++++++++++++++------ src/cmd/6g/reg.c | 1 + 4 files changed, 278 insertions(+), 51 deletions(-) diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c index 300020eabf4..29e61c661ab 100644 --- a/src/cmd/6g/cgen.c +++ b/src/cmd/6g/cgen.c @@ -54,8 +54,7 @@ cgen(Node *n, Node *res) f = 1; // gen thru register switch(n->op) { case OLITERAL: - if(isint[n->type->etype]) - if(n->type->width <= 4) + if(smallintconst(n)) f = 0; break; case OREGISTER: @@ -63,7 +62,7 @@ cgen(Node *n, Node *res) break; } - if(sudoaddable(res, n->type, &addr, &n1)) { + if(sudoaddable(res, n->type, &addr)) { a = optoas(OAS, res->type); if(f) { regalloc(&n2, res->type, N); @@ -73,7 +72,7 @@ cgen(Node *n, Node *res) } else p1 = gins(a, n, N); p1->to = addr; - regfree(&n1); + sudoclean(); goto ret; } @@ -101,7 +100,7 @@ cgen(Node *n, Node *res) goto ret; } - if(sudoaddable(n, res->type, &addr, &n1)) { + if(sudoaddable(n, res->type, &addr)) { a = optoas(OAS, n->type); if(res->op == OREGISTER) { p1 = gins(a, N, res); @@ -113,7 +112,7 @@ cgen(Node *n, Node *res) gins(a, &n2, res); regfree(&n2); } - regfree(&n1); + sudoclean(); goto ret; } @@ -317,11 +316,11 @@ abop: // asymmetric binary regalloc(&n1, nl->type, res); cgen(nl, &n1); - if(sudoaddable(nr, nl->type, &addr, &n2)) { + if(sudoaddable(nr, nl->type, &addr)) { p1 = gins(a, N, &n1); p1->from = addr; gmove(&n1, res); - regfree(&n2); + sudoclean(); regfree(&n1); goto ret; } @@ -724,7 +723,7 @@ bgen(Node *n, int true, Prog *to) a = brcom(a); // make simplest on right - if(nl->ullman < nr->ullman) { + if(nl->op == OLITERAL || nl->ullman < nr->ullman) { a = brrev(a); r = nl; nl = nr; @@ -755,10 +754,16 @@ bgen(Node *n, int true, Prog *to) break; } - regalloc(&n1, nl->type, N); cgen(nl, &n1); + if(smallintconst(nr)) { + gins(optoas(OCMP, nr->type), &n1, nr); + patch(gbranch(a, nr->type), to); + regfree(&n1); + break; + } + regalloc(&n2, nr->type, N); cgen(nr, &n2); diff --git a/src/cmd/6g/gg.h b/src/cmd/6g/gg.h index df83aed6883..051fa12156f 100644 --- a/src/cmd/6g/gg.h +++ b/src/cmd/6g/gg.h @@ -199,7 +199,9 @@ void tempname(Node*, Type*); Plist* newplist(void); int isfat(Type*); void setmaxarg(Type*); -int sudoaddable(Node*, Type*, Addr*, Node*); +int smallintconst(Node*); +void sudoclean(void); +int sudoaddable(Node*, Type*, Addr*); /* * list.c diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c index 28acd0c83f6..c4798b77ed3 100644 --- a/src/cmd/6g/gsubr.c +++ b/src/cmd/6g/gsubr.c @@ -113,12 +113,16 @@ ginit(void) reg[i] = 0; for(i=D_X0; i<=D_X7; i++) reg[i] = 0; + +// reg[D_DI]++; // for movstring +// reg[D_SI]++; // for movstring + reg[D_AX]++; // for divide reg[D_CX]++; // for shift - reg[D_DI]++; // for movstring reg[D_DX]++; // for divide - reg[D_SI]++; // for movstring reg[D_SP]++; // for stack + reg[D_R14]++; // reserved for m + reg[D_R15]++; // reserved for u } void @@ -126,12 +130,16 @@ gclean(void) { int i; +// reg[D_DI]--; // for movstring +// reg[D_SI]--; // for movstring + reg[D_AX]--; // for divide reg[D_CX]--; // for shift - reg[D_DI]--; // for movstring reg[D_DX]--; // for divide - reg[D_SI]--; // for movstring reg[D_SP]--; // for stack + reg[D_R14]--; // reserved for m + reg[D_R15]--; // reserved for u + for(i=D_AX; i<=D_R15; i++) if(reg[i]) yyerror("reg %R left allocated\n", i); @@ -1810,59 +1818,270 @@ dotoffset(Node *n, int *oary, Node **nn) } int -sudoaddable(Node *n, Type *t, Addr *a, Node *reg) +smallintconst(Node *n) { - int et, o, i; + if(n->op == OLITERAL) + switch(simtype[n->type->etype]) { + case TINT8: + case TUINT8: + case TINT16: + case TUINT16: + case TINT32: + case TUINT32: + case TBOOL: + case TPTR32: + return 1; + } + return 0; +} + +enum +{ + ODynam = 1<<0, + OPtrto = 1<<1, +}; + +static Node clean[20]; +static int cleani = 0; + +void +sudoclean(void) +{ + if(clean[cleani-1].op != OEMPTY) + regfree(&clean[cleani-1]); + if(clean[cleani-2].op != OEMPTY) + regfree(&clean[cleani-2]); + cleani -= 2; +} + +int +sudoaddable(Node *n, Type *t, Addr *a) +{ + int et, o, i, w; int oary[10]; - Node n1, *nn; + vlong v; + Node n0, n1, n2, *nn, *l, *r; + Node *reg, *reg1; + Prog *p1; + + // make a cleanup slot + cleani += 2; + reg = &clean[cleani-1]; + reg1 = &clean[cleani-2]; + reg->op = OEMPTY; + reg1->op = OEMPTY; if(n->type == T || t == T) - return 0; + goto no; et = simtype[n->type->etype]; if(et != simtype[t->etype]) - return 0; + goto no; switch(n->op) { default: - return 0; + goto no; case ODOT: case ODOTPTR: - o = dotoffset(n, oary, &nn); - if(nn == N) - return 0; + goto odot; - if(0) { - dump("\nXX", n); - dump("YY", nn); - for(i=0; i= 0) { - agen(nn, reg); - n1.xoffset = oary[0]; - } else { - cgen(nn, reg); - n1.xoffset = -(oary[0]+1); - } +odot: + o = dotoffset(n, oary, &nn); + if(nn == N) + goto no; - for(i=1; i= 0) - fatal("cant happen"); - gins(AMOVQ, &n1, reg); - n1.xoffset = -(oary[i]+1); - } + if(0) { + dump("\nXX", n); + dump("YY", nn); + for(i=0; i= 0) { + agen(nn, reg); + n1.xoffset = oary[0]; + } else { + cgen(nn, reg); + n1.xoffset = -(oary[0]+1); + } - a->type = D_NONE; - a->index = D_NONE; - naddr(&n1, a); + for(i=1; i= 0) + fatal("cant happen"); + gins(AMOVQ, &n1, reg); + n1.xoffset = -(oary[i]+1); + } + + a->type = D_NONE; + a->index = D_NONE; + naddr(&n1, a); + goto yes; + +oindex: + l = n->left; + r = n->right; + if(l->ullman >= UINF || r->ullman >= UINF) + goto no; + + // set o to type of array + o = 0; + if(isptr[l->type->etype]) { + o += OPtrto; + if(l->type->type->etype != TARRAY) + fatal("not ptr ary"); + if(l->type->type->bound < 0) + o += ODynam; + } else { + if(l->type->etype != TARRAY) + fatal("not ary"); + if(l->type->bound < 0) + o += ODynam; + } + + w = n->type->width; + if(w == 0) + fatal("index is zero width"); + if(whatis(r) == Wlitint) + goto oindex_const; + + switch(w) { + default: + goto no; + case 1: + case 2: + case 4: + case 8: break; } + + // load the array (reg) + if(l->ullman > r->ullman) { + regalloc(reg, types[tptr], N); + if(o & OPtrto) + cgen(l, reg); + else + agen(l, reg); + } + + // load the index (reg1) + t = types[TUINT64]; + if(issigned[r->type->etype]) + t = types[TINT64]; + regalloc(reg1, t, N); + cgen(r, reg1); + + // load the array (reg) + if(l->ullman <= r->ullman) { + regalloc(reg, types[tptr], N); + if(o & OPtrto) + cgen(l, reg); + else + agen(l, reg); + } + + // check bounds + if(!debug['B']) { + if(o & ODynam) { + n2 = *reg; + n2.op = OINDREG; + n2.type = types[tptr]; + n2.xoffset = offsetof(Array, nel); + } else { + nodconst(&n2, types[TUINT64], l->type->bound); + if(o & OPtrto) + nodconst(&n2, types[TUINT64], l->type->type->bound); + } + gins(optoas(OCMP, types[TUINT32]), reg1, &n2); + p1 = gbranch(optoas(OLT, types[TUINT32]), T); + gins(ACALL, N, throwindex); + patch(p1, pc); + } + + if(o & ODynam) { + n2 = *reg; + n2.op = OINDREG; + n2.type = types[tptr]; + n2.xoffset = offsetof(Array, array); + gmove(&n2, reg); + } + + naddr(reg1, a); + a->offset = 0; + a->scale = w; + a->index = a->type; + a->type = reg->val.u.reg + D_INDIR; + + goto yes; + +oindex_const: + // index is constant + // can check statically and + // can multiply by width statically + + regalloc(reg, types[tptr], N); + if(o & OPtrto) + cgen(l, reg); + else + agen(l, reg); + + v = mpgetfix(r->val.u.xval); + if(o & ODynam) { + + if(!debug['B']) { + n1 = *reg; + n1.op = OINDREG; + n1.type = types[tptr]; + n1.xoffset = offsetof(Array, nel); + nodconst(&n2, types[TUINT64], v); + gins(optoas(OCMP, types[TUINT32]), &n1, &n2); + p1 = gbranch(optoas(OGT, types[TUINT32]), T); + gins(ACALL, N, throwindex); + patch(p1, pc); + } + + n1 = *reg; + n1.op = OINDREG; + n1.type = types[tptr]; + n1.xoffset = offsetof(Array, array); + gmove(&n1, reg); + + } else + if(!debug['B']) { + if(v < 0) { + yyerror("out of bounds on array"); + } else + if(o & OPtrto) { + if(v >= l->type->type->bound) + yyerror("out of bounds on array"); + } else + if(v >= l->type->bound) { + yyerror("out of bounds on array"); + } + } + + n2 = *reg; + n2.op = OINDREG; + n2.xoffset = v*w; + a->type = D_NONE; + a->index = D_NONE; + naddr(&n2, a); + goto yes; + +yes: return 1; + +no: + sudoclean(); + return 0; } diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c index 841a2312ebf..0613f0015f9 100644 --- a/src/cmd/6g/reg.c +++ b/src/cmd/6g/reg.c @@ -102,6 +102,7 @@ regopt(Prog *firstp) if(first) { fmtinstall('Q', Qconv); + exregoffset = D_R13; // R14,R15 are external first = 0; }