]> Cypherpunks repositories - gostls13.git/commitdiff
5g, 6g, 8g: shift, opt fixes
authorRuss Cox <rsc@golang.org>
Thu, 28 Jul 2011 22:22:12 +0000 (18:22 -0400)
committerRuss Cox <rsc@golang.org>
Thu, 28 Jul 2011 22:22:12 +0000 (18:22 -0400)
Fixes #1808.

R=ken2
CC=golang-dev
https://golang.org/cl/4813052

src/cmd/5g/cgen64.c
src/cmd/5g/ggen.c
src/cmd/5g/gsubr.c
src/cmd/5g/peep.c
src/cmd/5g/reg.c
src/cmd/6g/gsubr.c
src/cmd/8g/gg.h
src/cmd/8g/ggen.c
src/cmd/8g/reg.c
src/cmd/gc/bits.c
test/fixedbugs/bug356.go [new file with mode: 0644]

index 4da8db2ae2042ecedf83696e3ea6b6dfb9f5376b..b56df765baaae5d0b616031337908dca464eea33 100644 (file)
@@ -158,7 +158,7 @@ cgen64(Node *n, Node *res)
                gins(AMOVW, &hi2, &ch);
                gins(AMOVW, &lo2, &cl);
 
-               // bl * cl
+               // bl * cl -> ah al
                p1 = gins(AMULLU, N, N);
                p1->from.type = D_REG;
                p1->from.reg = bl.val.u.reg;
@@ -168,7 +168,7 @@ cgen64(Node *n, Node *res)
                p1->to.offset = al.val.u.reg;
 //print("%P\n", p1);
 
-               // bl * ch
+               // bl * ch + ah -> ah
                p1 = gins(AMULA, N, N);
                p1->from.type = D_REG;
                p1->from.reg = bl.val.u.reg;
@@ -178,7 +178,7 @@ cgen64(Node *n, Node *res)
                p1->to.offset = ah.val.u.reg;
 //print("%P\n", p1);
 
-               // bh * cl
+               // bh * cl + ah -> ah
                p1 = gins(AMULA, N, N);
                p1->from.type = D_REG;
                p1->from.reg = bh.val.u.reg;
index d5b00b34d50ae9b6dfe14225d1b11ac370b3d1fb..e2f0e6bc0ac417436cc4eaffb001a01f6528bcde 100644 (file)
@@ -470,9 +470,10 @@ samereg(Node *a, Node *b)
 void
 cgen_shift(int op, Node *nl, Node *nr, Node *res)
 {
-       Node n1, n2, n3, t;
+       Node n1, n2, n3, nt, t, lo, hi;
        int w;
-       Prog *p1, *p2, *p3;
+       Prog *p1, *p2, *p3, *pbig;
+       Type *tr;
        uvlong sc;
 
        if(nl->type->width > 4)
@@ -504,16 +505,43 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
                return;
        }
 
-       if(nl->ullman >= nr->ullman) {
-               regalloc(&n2, nl->type, res);
-               cgen(nl, &n2);
-               regalloc(&n1, nr->type, N);
-               cgen(nr, &n1);
+       pbig = P;
+       tr = nr->type;
+       if(tr->width > 4) {
+               tempname(&nt, nr->type);
+               if(nl->ullman >= nr->ullman) {
+                       regalloc(&n2, nl->type, res);
+                       cgen(nl, &n2);
+                       cgen(nr, &nt);
+                       n1 = nt;
+               } else {
+                       cgen(nr, &nt);
+                       regalloc(&n2, nl->type, res);
+                       cgen(nl, &n2);
+               }
+               split64(&nt, &lo, &hi);
+               regalloc(&n1, types[TUINT32], N);
+               regalloc(&n3, types[TUINT32], N);
+               gmove(&lo, &n1);
+               gmove(&hi, &n3);
+               gins(ATST, &n3, N);
+               nodconst(&t, types[TUINT32], w);
+               p1 = gins(AMOVW, &t, &n1);
+               p1->scond = C_SCOND_NE;
+               tr = types[TUINT32];
+               regfree(&n3);
        } else {
-               regalloc(&n1, nr->type, N);
-               cgen(nr, &n1);
-               regalloc(&n2, nl->type, res);
-               cgen(nl, &n2);
+               if(nl->ullman >= nr->ullman) {
+                       regalloc(&n2, nl->type, res);
+                       cgen(nl, &n2);
+                       regalloc(&n1, nr->type, N);
+                       cgen(nr, &n1);
+               } else {
+                       regalloc(&n1, nr->type, N);
+                       cgen(nr, &n1);
+                       regalloc(&n2, nl->type, res);
+                       cgen(nl, &n2);
+               }
        }
 
        // test for shift being 0
@@ -521,7 +549,7 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
        p3 = gbranch(ABEQ, T);
 
        // test and fix up large shifts
-       regalloc(&n3, nr->type, N);
+       regalloc(&n3, tr, N);
        nodconst(&t, types[TUINT32], w);
        gmove(&t, &n3);
        gcmp(ACMP, &n1, &n3);
index 2d921846133266b5482c8e33c49c2f73b11cba6d..ddaf52a8821a95a00dc75f36d5192b63a8e176a2 100644 (file)
@@ -497,6 +497,7 @@ fp:
                n->class = PPARAM;
                break;
        }
+       n->typecheck = 1;
        return n;
 }
 
@@ -1173,6 +1174,7 @@ naddr(Node *n, Addr *a, int canemitcode)
        a->name = D_NONE;
        a->reg = NREG;
        a->node = N;
+       a->etype = 0;
        if(n == N)
                return;
 
@@ -1308,6 +1310,7 @@ naddr(Node *n, Addr *a, int canemitcode)
        case OLEN:
                // len of string or slice
                naddr(n->left, a, canemitcode);
+               a->etype = TINT32;
                if(a->type == D_CONST && a->offset == 0)
                        break;  // len(nil)
                a->offset += Array_nel;
@@ -1318,6 +1321,7 @@ naddr(Node *n, Addr *a, int canemitcode)
        case OCAP:
                // cap of string or slice
                naddr(n->left, a, canemitcode);
+               a->etype = TINT32;
                if(a->type == D_CONST && a->offset == 0)
                        break;  // cap(nil)
                a->offset += Array_cap;
@@ -1327,6 +1331,7 @@ naddr(Node *n, Addr *a, int canemitcode)
 
        case OADDR:
                naddr(n->left, a, canemitcode);
+               a->etype = tptr;
                switch(a->type) {
                case D_OREG:
                        a->type = D_CONST;
@@ -1819,6 +1824,7 @@ odot:
 
        a->type = D_NONE;
        a->name = D_NONE;
+       n1.type = n->type;
        naddr(&n1, a, 1);
        goto yes;
 
@@ -1946,7 +1952,6 @@ oindex:
        a->type = D_OREG;
        a->reg = reg->val.u.reg;
        a->offset = 0;
-
        goto yes;
 
 oindex_const:
index 6f36e12d42ee4f4495857d6eae626cf3d83e683e..6cc93db12c5448d9bd3bf690fbafa17200bf4728 100644 (file)
@@ -933,7 +933,6 @@ xtramodes(Reg *r, Adr *a)
 int
 copyu(Prog *p, Adr *v, Adr *s)
 {
-
        switch(p->as) {
 
        default:
@@ -1011,6 +1010,8 @@ copyu(Prog *p, Adr *v, Adr *s)
                        return 0;
                }
                if(copyas(&p->to, v)) {
+                       if(p->scond != C_SCOND_NONE)
+                               return 2;
                        if(copyau(&p->from, v))
                                return 4;
                        return 3;
@@ -1069,6 +1070,8 @@ copyu(Prog *p, Adr *v, Adr *s)
                        return 0;
                }
                if(copyas(&p->to, v)) {
+                       if(p->scond != C_SCOND_NONE)
+                               return 2;
                        if(p->reg == NREG)
                                p->reg = p->to.reg;
                        if(copyau(&p->from, v))
index 7bb33b7c2565be9a1ca06f533de3236a1a0135bf..2d2a6d01af439a92bcf2001661f8d51e6c2dce52 100644 (file)
@@ -336,6 +336,7 @@ regopt(Prog *firstp)
                case AMULD:
                case ADIVF:
                case ADIVD:
+               case AMULA:
                case AMULAL:
                case AMULALU:
                        for(z=0; z<BITS; z++) {
@@ -770,6 +771,7 @@ addmove(Reg *r, int bn, int rn, int f)
                break;
        case TBOOL:
        case TUINT8:
+//print("movbu %E %d %S\n", v->etype, bn, v->sym);
                p1->as = AMOVBU;
                break;
        case TINT16:
@@ -843,9 +845,6 @@ mkvar(Reg *r, Adr *a)
        n = D_NONE;
 
        flag = 0;
-       if(a->pun)
-               flag = 1;
-
        switch(t) {
        default:
                print("type %d %d %D\n", t, a->name, a);
@@ -928,7 +927,7 @@ mkvar(Reg *r, Adr *a)
                                if(!flag)
                                        return blsh(i);
 
-                       // if they overlaps, disable both
+                       // if they overlap, disable both
                        if(overlap(v->offset, v->width, o, w)) {
                                v->addr = 1;
                                flag = 1;
@@ -952,6 +951,7 @@ mkvar(Reg *r, Adr *a)
 
        i = nvar;
        nvar++;
+//print("var %d %E %D %S\n", i, et, a, s);
        v = var+i;
        v->sym = s;
        v->offset = o;
@@ -963,7 +963,7 @@ mkvar(Reg *r, Adr *a)
        v->node = a->node;
        
        if(debug['R'])
-               print("bit=%2d et=%E pun=%d %D\n", i, et, flag, a);
+               print("bit=%2d et=%2d w=%d+%d %S %D flag=%d\n", i, et, o, w, s, a, v->addr);
 
        bit = blsh(i);
        if(n == D_EXTERN || n == D_STATIC)
@@ -1453,10 +1453,6 @@ paint3(Reg *r, int bn, int32 rb, int rn)
 void
 addreg(Adr *a, int rn)
 {
-
-       if(a->type == D_CONST)
-               fatal("addreg: cant do this %D %d\n", a, rn);
-
        a->sym = 0;
        a->name = D_NONE;
        a->type = D_REG;
@@ -1477,8 +1473,7 @@ addreg(Adr *a, int rn)
 int32
 RtoB(int r)
 {
-
-       if(r < 2 || r >= REGTMP-2)      // excluded R9 and R10 for m and g
+       if(r >= REGTMP-2)       // excluded R9 and R10 for m and g
                return 0;
        return 1L << r;
 }
index 211915f5441f8bb18fe96822e467296749224066..d0d6d0c96d594ba7c10a58bbae1749478999d764 100644 (file)
@@ -473,6 +473,7 @@ fatal("shouldnt be used");
                n->xoffset += types[tptr]->width;
                break;
        }
+       n->typecheck = 1;
        return n;
 }
 
@@ -987,7 +988,6 @@ gins(int as, Node *f, Node *t)
        if(debug['g'])
                print("%P\n", p);
 
-
        w = 0;
        switch(as) {
        case AMOVB:
index 7da60d7677a60294618e34792bd8ed17ddc1f509..9f7a66a2956aafcad3420134e7fc55e3fa065d87 100644 (file)
@@ -9,7 +9,7 @@
 #include "../8l/8.out.h"
 
 #ifndef        EXTERN
-#define EXTERN extern
+#define        EXTERN  extern
 #endif
 
 typedef        struct  Addr    Addr;
index eaf3c01cc299e2deb95801814bfa4bc4314074da..108c493aa382afd1ab1b8fba635cd742450befee 100644 (file)
@@ -620,9 +620,9 @@ cgen_div(int op, Node *nl, Node *nr, Node *res)
 void
 cgen_shift(int op, Node *nl, Node *nr, Node *res)
 {
-       Node n1, n2, cx, oldcx;
+       Node n1, n2, nt, cx, oldcx, hi, lo;
        int a, w;
-       Prog *p1;
+       Prog *p1, *p2;
        uvlong sc;
 
        if(nl->type->width > 4)
@@ -656,8 +656,13 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
                gmove(&cx, &oldcx);
        }
 
-       nodreg(&n1, types[TUINT32], D_CX);
-       regalloc(&n1, nr->type, &n1);           // to hold the shift type in CX
+       if(nr->type->width > 4) {
+               tempname(&nt, nr->type);
+               n1 = nt;
+       } else {
+               nodreg(&n1, types[TUINT32], D_CX);
+               regalloc(&n1, nr->type, &n1);           // to hold the shift type in CX
+       }
 
        if(samereg(&cx, res))
                regalloc(&n2, nl->type, N);
@@ -672,8 +677,21 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
        }
 
        // test and fix up large shifts
-       gins(optoas(OCMP, nr->type), &n1, ncon(w));
-       p1 = gbranch(optoas(OLT, types[TUINT32]), T);
+       if(nr->type->width > 4) {
+               // delayed reg alloc
+               nodreg(&n1, types[TUINT32], D_CX);
+               regalloc(&n1, types[TUINT32], &n1);             // to hold the shift type in CX
+               split64(&nt, &lo, &hi);
+               gmove(&lo, &n1);
+               gins(optoas(OCMP, types[TUINT32]), &hi, ncon(0));
+               p2 = gbranch(optoas(ONE, types[TUINT32]), T);
+               gins(optoas(OCMP, types[TUINT32]), &n1, ncon(w));
+               p1 = gbranch(optoas(OLT, types[TUINT32]), T);
+               patch(p2, pc);
+       } else {
+               gins(optoas(OCMP, nr->type), &n1, ncon(w));
+               p1 = gbranch(optoas(OLT, types[TUINT32]), T);
+       }
        if(op == ORSH && issigned[nl->type->etype]) {
                gins(a, ncon(w-1), &n2);
        } else {
index a4828c3a39c7b63043775e595ae5e825f473e258..2b878f62a23ca2a526f63aaac6a1211004bd3214 100644 (file)
@@ -865,7 +865,7 @@ mkvar(Reg *r, Adr *a)
                        if(v->width == w)
                                return blsh(i);
 
-                       // if they overlaps, disable both
+                       // if they overlap, disable both
                        if(overlap(v->offset, v->width, o, w)) {
                                if(debug['R'])
                                        print("disable %s\n", v->sym->name);
@@ -874,8 +874,6 @@ mkvar(Reg *r, Adr *a)
                        }
                }
        }
-       if(a->pun)
-               flag = 1;
 
        switch(et) {
        case 0:
@@ -902,7 +900,7 @@ mkvar(Reg *r, Adr *a)
        v->node = a->node;
 
        if(debug['R'])
-               print("bit=%2d et=%2d w=%d %S %D flag=%d\n", i, et, w, s, a, v->addr);
+               print("bit=%2d et=%2d w=%d+%d %S %D flag=%d\n", i, et, o, w, s, a, v->addr);
        ostats.nvar++;
 
        bit = blsh(i);
index 1f2a776fd3831f70ead77020670f042687c17e2f..7188ac4111280532679cd8b067d86ab861ec3f79 100644 (file)
@@ -150,8 +150,11 @@ Qconv(Fmt *fp)
                        fmtprint(fp, " ");
                if(var[i].sym == S)
                        fmtprint(fp, "$%lld", var[i].offset);
-               else
+               else {
                        fmtprint(fp, var[i].sym->name);
+                       if(var[i].offset != 0)
+                               fmtprint(fp, "%+d", var[i].offset);
+               }
                bits.b[i/32] &= ~(1L << (i%32));
        }
        return 0;
diff --git a/test/fixedbugs/bug356.go b/test/fixedbugs/bug356.go
new file mode 100644 (file)
index 0000000..d21f0cf
--- /dev/null
@@ -0,0 +1,41 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out || echo BUG: bug344
+
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 1808
+
+package main
+
+func main() {
+       var i uint64
+       var x int = 12345
+
+       if y := x << (i&5); y != 12345<<0 {
+               println("BUG bug344", y)
+               return
+       }
+       
+       i++
+       if y := x << (i&5); y != 12345<<1 {
+               println("BUG bug344a", y)
+       }
+       
+       i = 70
+       if y := x << i; y != 0 {
+               println("BUG bug344b", y)
+       }
+       
+       i = 1<<32
+       if y := x << i; y != 0 {
+               println("BUG bug344c", y)
+       }
+}
+       
+
+/*
+typecheck [1008592b0]
+.   INDREG a(1) l(15) x(24) tc(2) runtime.ret G0 string
+bug343.go:15: internal compiler error: typecheck INDREG
+*/