]> Cypherpunks repositories - gostls13.git/commitdiff
more code optimization
authorKen Thompson <ken@golang.org>
Mon, 15 Dec 2008 01:06:06 +0000 (17:06 -0800)
committerKen Thompson <ken@golang.org>
Mon, 15 Dec 2008 01:06:06 +0000 (17:06 -0800)
R=r
OCL=21159
CL=21159

src/cmd/6g/cgen.c
src/cmd/6g/gg.h
src/cmd/6g/gsubr.c
src/cmd/6g/reg.c

index 300020eabf4474a5e74af9d98bccc57ada84a351..29e61c661abd787686f04d058296e362c1be7a3e 100644 (file)
@@ -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);
 
index df83aed68838ae71a2a2e20f2e613d0feaf91317..051fa12156fb22d4c8ceb90ae50df23d32aa6eae 100644 (file)
@@ -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
index 28acd0c83f6544df73768b4156dd8af5fe8aca91..c4798b77ed32850af0b87c63fb19a87715a14cea 100644 (file)
@@ -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;
-
-               if(0) {
-                       dump("\nXX", n);
-                       dump("YY", nn);
-                       for(i=0; i<o; i++)
-                               print(" %d", oary[i]);
-                       print("\n");
-                       return 0;
-               }
+               goto odot;
+
+       case OINDEXPTR:
+               goto no;
+       case OINDEX:
+               goto oindex;
+       }
+
+odot:
+       o = dotoffset(n, oary, &nn);
+       if(nn == N)
+               goto no;
+
+       if(0) {
+               dump("\nXX", n);
+               dump("YY", nn);
+               for(i=0; i<o; i++)
+                       print(" %d", oary[i]);
+               print("\n");
+               goto no;
+       }
+       
+       regalloc(reg, types[tptr], N);
+       n1 = *reg;
+       n1.op = OINDREG;
+       if(oary[0] >= 0) {
+               agen(nn, reg);
+               n1.xoffset = oary[0];
+       } else {
+               cgen(nn, reg);
+               n1.xoffset = -(oary[0]+1);
+       }
 
+       for(i=1; i<o; i++) {
+               if(oary[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);
-               n1 = *reg;
-               n1.op = OINDREG;
-               if(oary[0] >= 0) {
-                       agen(nn, reg);
-                       n1.xoffset = oary[0];
+               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 {
-                       cgen(nn, reg);
-                       n1.xoffset = -(oary[0]+1);
+                       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);
+       }
 
-               for(i=1; i<o; i++) {
-                       if(oary[i] >= 0)
-                               fatal("cant happen");
-                       gins(AMOVQ, &n1, reg);
-                       n1.xoffset = -(oary[i]+1);
+       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);
                }
 
-               a->type = D_NONE;
-               a->index = D_NONE;
-               naddr(&n1, a);
-               break;
+               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;
 }
index 841a2312ebfacaedef7c249fe84124ebb0a88d54..0613f0015f94c87e50d7909b611b001e67f11f17 100644 (file)
@@ -102,6 +102,7 @@ regopt(Prog *firstp)
 
        if(first) {
                fmtinstall('Q', Qconv);
+               exregoffset = D_R13;    // R14,R15 are external
                first = 0;
        }