]> Cypherpunks repositories - gostls13.git/commitdiff
inline slicearray
authorKen Thompson <ken@golang.org>
Thu, 27 Aug 2009 20:19:44 +0000 (13:19 -0700)
committerKen Thompson <ken@golang.org>
Thu, 27 Aug 2009 20:19:44 +0000 (13:19 -0700)
R=rsc
OCL=33974
CL=33974

src/cmd/6g/cgen.c
src/cmd/6g/gg.h
src/cmd/6g/ggen.c
test/ken/slicearray.go [new file with mode: 0644]

index fcdf7ead9af7ed248bda601d76cf36930c4cbeed..ab712e5435e93abff78ccf2913c0cec2d1b6e2a6 100644 (file)
@@ -35,6 +35,10 @@ cgen(Node *n, Node *res)
        if(initflag && gen_as_init(n, res))
                goto ret;
 
+       // inline slices
+       if(cgen_inline(n, res))
+               goto ret;
+
        if(n->ullman >= UINF) {
                if(n->op == OINDREG)
                        fatal("cgen: this is going to misscompile");
index ca90762cf72b45e3c2e552e88e4632d39152fed0..a2896bb153e82274607517ca292e0342ee9c41d9 100644 (file)
@@ -93,6 +93,7 @@ Prog* gins(int, Node*, Node*);
 int    samaddr(Node*, Node*);
 void   naddr(Node*, Addr*);
 void   cgen_aret(Node*, Node*);
+int    cgen_inline(Node*, Node*);
 
 /*
  * gsubr.c
index 5c2a8953b297e46ebfaa4cc468aa97a0b0396eac..8bae94917702a3f93f0b4241ce17d1dbe7b1df68 100644 (file)
@@ -1172,3 +1172,171 @@ yes:
 //print("%P\n", p);
        return 1;
 }
+
+void
+getargs(NodeList *nn, Node *reg, int n)
+{
+       NodeList *l;
+       int i;
+
+       l = nn;
+       for(i=0; i<n; i++) {
+               if(!smallintconst(l->n->right)) {
+                       regalloc(reg+i, l->n->right->type, N);
+                       cgen(l->n->right, reg+i);
+               } else
+                       reg[i] = *l->n->right;
+               l = l->next;
+       }
+       // botch - need second pass to sort by offset
+}
+
+void
+cmpandthrow(Node *nodes, int l, int r)
+{
+       vlong cl, cr;
+       Prog *p1;
+       int op, c;
+
+       op = OLE;
+       if(smallintconst(nodes+l)) {
+               cl = mpgetfix((nodes+l)->val.u.xval);
+               if(cl == 0)
+                       return;
+               if(smallintconst(nodes+r)) {
+                       cr = mpgetfix((nodes+r)->val.u.xval);
+                       if(cl > cr)
+                               ginscall(throwindex, 0);
+                       return;
+               }
+
+               // put the constant on the right
+               op = brrev(op);
+               c = l;
+               l = r;
+               r = c;
+       }
+
+       gins(optoas(OCMP, types[TUINT32]), nodes+l, nodes+r);
+       p1 = gbranch(optoas(op, types[TUINT32]), T);
+       ginscall(throwindex, 0);
+       patch(p1, pc);
+}
+
+// generate inline code for
+//     slicearray
+//     sliceslice
+//     arraytoslice
+int
+cgen_inline(Node *n, Node *res)
+{
+       Node nodes[10];
+       Node n1, n2;
+       vlong v;
+       int i;
+
+       if(n->op != OCALLFUNC)
+               goto no;
+       if(n->left->op != ONAME)
+               goto no;
+       if(!res->addable)
+               goto no;
+       if(strcmp(n->left->sym->package, "sys") != 0)
+               goto no;
+       if(strcmp(n->left->sym->name, "slicearray") == 0)
+               goto slicearray;
+       if(strcmp(n->left->sym->name, "sliceslice") == 0)
+               goto sliceslice;
+       if(strcmp(n->left->sym->name, "arraytoslice") == 0)
+               goto arraytoslice;
+       goto no;
+
+slicearray:
+       getargs(n->list, nodes, 5);
+
+       // if(hb[3] > nel[1]) goto throw
+       cmpandthrow(nodes, 3, 1);
+
+       // if(lb[2] > hb[3]) goto throw
+       cmpandthrow(nodes, 2, 3);
+
+
+       // len = hb[3] - lb[2] (destroys hb)
+       n2 = *res;
+       n2.xoffset += Array_nel;
+
+       if(smallintconst(nodes+3) && smallintconst(nodes+2)) {
+               v = mpgetfix((nodes+3)->val.u.xval) -
+                       mpgetfix((nodes+2)->val.u.xval);
+               nodconst(&n1, types[TUINT32], v);
+               gins(optoas(OAS, types[TUINT32]), &n1, &n2);
+       } else {
+               regalloc(&n1, types[TUINT32], nodes+3);
+               gmove(nodes+3, &n1);
+               gins(optoas(OSUB, types[TUINT32]), nodes+2, &n1);
+               gins(optoas(OAS, types[TUINT32]), &n1, &n2);
+               regfree(&n1);
+       }
+
+       // cap = nel[1] - lb[2] (destroys nel)
+       n2 = *res;
+       n2.xoffset += Array_cap;
+
+       if(smallintconst(nodes+1) && smallintconst(nodes+2)) {
+               v = mpgetfix((nodes+1)->val.u.xval) -
+                       mpgetfix((nodes+2)->val.u.xval);
+               nodconst(&n1, types[TUINT32], v);
+               gins(optoas(OAS, types[TUINT32]), &n1, &n2);
+       } else {
+               regalloc(&n1, types[TUINT32], nodes+1);
+               gmove(nodes+1, &n1);
+               gins(optoas(OSUB, types[TUINT32]), nodes+2, &n1);
+               gins(optoas(OAS, types[TUINT32]), &n1, &n2);
+               regfree(&n1);
+       }
+
+       // ary = old[0] + (lb[2] * width[4]) (destroys old)
+       n2 = *res;
+       n2.xoffset += Array_array;
+
+       if(smallintconst(nodes+2) && smallintconst(nodes+4)) {
+               v = mpgetfix((nodes+2)->val.u.xval) *
+                       mpgetfix((nodes+4)->val.u.xval);
+               nodconst(&n1, types[tptr], v);
+               gins(optoas(OADD, types[tptr]), &n1, nodes+0);
+       } else {
+               regalloc(&n1, types[tptr], nodes+2);
+               gmove(nodes+2, &n1);
+               if(!smallintconst(nodes+4) || mpgetfix((nodes+4)->val.u.xval) != 1)
+                       gins(optoas(OMUL, types[tptr]), nodes+4, &n1);
+               gins(optoas(OADD, types[tptr]), &n1, nodes+0);
+               regfree(&n1);
+       }
+       gins(optoas(OAS, types[tptr]), nodes+0, &n2);
+
+       // ret.len = hb[3]-lb[2];
+       // ret.cap = nel[1]-lb[2];
+       // ret.array = old[0] + lb[3]*width[4];
+       for(i=0; i<5; i++) {
+               if(!smallintconst(nodes+i))
+                       regfree(nodes+i);
+       }
+       return 1;
+
+sliceslice:
+       // if(hb > old.cap) goto throw;
+       // if(lb > hb) goto throw;
+       // ret.len = hb-lb;
+       // ret.cap = old.cap - lb;
+       // ret.array = old.array + lb*width;
+       goto no;
+
+arraytoslice:
+       // ret.len = nel;
+       // ret.cap = nel;
+       // ret.array = old;
+       goto no;
+
+no:
+       return 0;
+}
diff --git a/test/ken/slicearray.go b/test/ken/slicearray.go
new file mode 100644 (file)
index 0000000..31faa9c
--- /dev/null
@@ -0,0 +1,127 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2009 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.
+
+
+package main
+
+var    bx      [10]byte
+var    by      []byte;
+var    fx      [10]float
+var    fy      []float;
+var    lb,hb   int
+var    t       int
+
+func
+main()
+{
+       // width 1 (byte)
+       lb = 0; hb = 10;
+       by = bx[lb:hb]; tstb();
+       by = bx[lb:10]; tstb();
+       by = bx[0:hb]; tstb();
+       by = bx[0:10]; tstb();
+
+       lb = 2; hb = 10;
+       by = bx[lb:hb]; tstb();
+       by = bx[lb:10]; tstb();
+       by = bx[2:hb]; tstb();
+       by = bx[2:10]; tstb();
+
+       lb = 0; hb = 8;
+       by = bx[lb:hb]; tstb();
+       by = bx[lb:8]; tstb();
+       by = bx[0:hb]; tstb();
+       by = bx[0:8]; tstb();
+
+       lb = 2; hb = 8;
+       by = bx[lb:hb]; tstb();
+       by = bx[lb:8]; tstb();
+       by = bx[2:hb]; tstb();
+       by = bx[2:8]; tstb();
+
+       // width 4 (float)
+       lb = 0; hb = 10;
+       fy = fx[lb:hb]; tstf();
+       fy = fx[lb:10]; tstf();
+       fy = fx[0:hb]; tstf();
+       fy = fx[0:10]; tstf();
+
+       lb = 2; hb = 10;
+       fy = fx[lb:hb]; tstf();
+       fy = fx[lb:10]; tstf();
+       fy = fx[2:hb]; tstf();
+       fy = fx[2:10]; tstf();
+
+       lb = 0; hb = 8;
+       fy = fx[lb:hb]; tstf();
+       fy = fx[lb:8]; tstf();
+       fy = fx[0:hb]; tstf();
+       fy = fx[0:8]; tstf();
+
+       lb = 2; hb = 8;
+       fy = fx[lb:hb]; tstf();
+       fy = fx[lb:8]; tstf();
+       fy = fx[2:hb]; tstf();
+       fy = fx[2:8]; tstf();
+}
+
+func
+tstb()
+{
+       t++;
+       if len(by) != hb-lb {
+               panicln("t=", t, "lb=", lb, "hb=", hb,
+                       "len=", len(by), "hb-lb=", hb-lb);
+       }
+       if cap(by) != len(bx)-lb {
+               panicln("t=", t, "lb=", lb, "hb=", hb,
+                       "cap=", cap(by), "len(bx)-lb=", len(bx)-lb);
+       }
+       for i:=lb; i<hb; i++ {
+               if bx[i] != by[i-lb] {
+                       panicln("t=", t, "lb=", lb, "hb=", hb,
+                               "bx[", i, "]=", bx[i],
+                               "by[", i-lb, "]=", by[i-lb]);
+               }
+       }
+       by = nil;
+}
+
+func
+tstf()
+{
+       t++;
+       if len(fy) != hb-lb {
+               panicln("t=", t, "lb=", lb, "hb=", hb,
+                       "len=", len(fy), "hb-lb=", hb-lb);
+       }
+       if cap(fy) != len(fx)-lb {
+               panicln("t=", t, "lb=", lb, "hb=", hb,
+                       "cap=", cap(fy), "len(fx)-lb=", len(fx)-lb);
+       }
+       for i:=lb; i<hb; i++ {
+               if fx[i] != fy[i-lb] {
+                       panicln("t=", t, "lb=", lb, "hb=", hb,
+                               "fx[", i, "]=", fx[i],
+                               "fy[", i-lb, "]=", fy[i-lb]);
+               }
+       }
+       fy = nil;
+}
+
+func
+init()
+{
+       for i:=0; i<len(bx); i++ {
+               bx[i] = byte(i+20);
+       }
+       by = nil;
+
+       for i:=0; i<len(fx); i++ {
+               fx[i] = float(i+20);
+       }
+       fy = nil;
+}