]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: Inline pointer sized T2I interface conversions
authorDaniel Morsing <daniel.morsing@gmail.com>
Tue, 11 Sep 2012 19:42:30 +0000 (21:42 +0200)
committerDaniel Morsing <daniel.morsing@gmail.com>
Tue, 11 Sep 2012 19:42:30 +0000 (21:42 +0200)
This CL also adds support for marking the likelyness of IF nodes in the AST being true. This feature is being used here to mark the slow path as unlikely.

src/pkg/runtime:
benchmark                  old ns/op    new ns/op    delta
BenchmarkConvT2IUintptr           16            1  -91.63%

test/bench/go1:
benchmark                 old ns/op    new ns/op    delta
BenchmarkBinaryTree17    5416917000   5461355000   +0.82%
BenchmarkFannkuch11      3810355000   3842609000   +0.85%
BenchmarkGobDecode         19950950     19855420   -0.48%
BenchmarkGobEncode         11301220     11308530   +0.06%
BenchmarkGzip             548119600    546869200   -0.23%
BenchmarkGunzip           176145400    180208300   +2.31%
BenchmarkJSONEncode        93117400     70163100  -24.65%
BenchmarkJSONDecode       406626800    409999200   +0.83%
BenchmarkMandelbrot200      6300992      6317866   +0.27%
BenchmarkParse              7664396      7451625   -2.78%
BenchmarkRevcomp         1189424000   1412332000  +18.74%
BenchmarkTemplate         491308400    458654200   -6.65%

benchmark                  old MB/s     new MB/s  speedup
BenchmarkGobDecode            38.47        38.66    1.00x
BenchmarkGobEncode            67.92        67.87    1.00x
BenchmarkGzip                 35.40        35.48    1.00x
BenchmarkGunzip              110.16       107.68    0.98x
BenchmarkJSONEncode           20.84        27.66    1.33x
BenchmarkJSONDecode            4.77         4.73    0.99x
BenchmarkParse                 7.56         7.77    1.03x
BenchmarkRevcomp             213.69       179.96    0.84x
BenchmarkTemplate              3.95         4.23    1.07x

R=rsc, dave, nigeltao
CC=golang-dev
https://golang.org/cl/6351090

src/cmd/gc/builtin.c
src/cmd/gc/gen.c
src/cmd/gc/go.h
src/cmd/gc/runtime.go
src/cmd/gc/walk.c
src/pkg/runtime/iface.c

index 535e38fac58d713d3df53954a1f82ea5427e4d19..6354fa22c8ca0937ba3708ee7f06bfa69cabed1f 100644 (file)
@@ -39,6 +39,7 @@ char *runtimeimport =
        "func @\"\".stringiter2(? string, ? int) (@\"\".retk int, @\"\".retv rune)\n"
        "func @\"\".copy(@\"\".to any, @\"\".fr any, @\"\".wid uint32) (? int)\n"
        "func @\"\".slicestringcopy(@\"\".to any, @\"\".fr any) (? int)\n"
+       "func @\"\".typ2Itab(@\"\".typ *byte, @\"\".typ2 *byte, @\"\".cache **byte) (@\"\".ret *byte)\n"
        "func @\"\".convI2E(@\"\".elem any) (@\"\".ret any)\n"
        "func @\"\".convI2I(@\"\".typ *byte, @\"\".elem any) (@\"\".ret any)\n"
        "func @\"\".convT2E(@\"\".typ *byte, @\"\".elem any) (@\"\".ret any)\n"
index ebb410ba54cd4d9818d8049c731bab1e9521d627..9b667775eb3d7930d16782fb0897616f72e981aa 100644 (file)
@@ -410,7 +410,7 @@ gen(Node *n)
                p1 = gjmp(P);                   //              goto test
                p2 = gjmp(P);                   // p2:          goto else
                patch(p1, pc);                          // test:
-               bgen(n->ntest, 0, 0, p2);                       //              if(!test) goto p2
+               bgen(n->ntest, 0, -n->likely, p2);              //              if(!test) goto p2
                genlist(n->nbody);                              //              then
                p3 = gjmp(P);                   //              goto done
                patch(p2, pc);                          // else:
@@ -746,12 +746,17 @@ ret:
 void
 cgen_eface(Node *n, Node *res)
 {
+       /* 
+        * the right node of an eface may contain function calls that uses res as an argument,
+        * so it's important that it is done first
+        */
        Node dst;
        dst = *res;
        dst.type = types[tptr];
-       cgen(n->left, &dst);
        dst.xoffset += widthptr;
        cgen(n->right, &dst);
+       dst.xoffset -= widthptr;
+       cgen(n->left, &dst);
 }
 
 /*
index 7bbaabb37800459f7221461bf41715c932ea022d..4a8d191dc7b6c2ea850a85e3d51914ffb5b3144f 100644 (file)
@@ -257,6 +257,7 @@ struct      Node
        uchar   implicit;
        uchar   addrtaken;      // address taken, even if not moved to heap
        uchar   dupok;  // duplicate definitions ok (for func)
+       schar   likely; // likeliness of if statement
 
        // most nodes
        Type*   type;
index 408f624cff5688ad17fa0816f0aaab6c6ce78f9e..7ab24a0440f406259f3791bf6ef5a5ba612e6b33 100644 (file)
@@ -59,6 +59,7 @@ func copy(to any, fr any, wid uint32) int
 func slicestringcopy(to any, fr any) int
 
 // interface conversions
+func typ2Itab(typ *byte, typ2 *byte, cache **byte) (ret *byte)
 func convI2E(elem any) (ret any)
 func convI2I(typ *byte, elem any) (ret any)
 func convT2E(typ *byte, elem any) (ret any)
index 4855b13ba943e5b4f2bc8cd61caa2555d1e86287..935fa6d65d7387ee2c752cfab07d71b38efd750a 100644 (file)
@@ -374,7 +374,7 @@ walkexpr(Node **np, NodeList **init)
        int et;
        int64 v;
        int32 lno;
-       Node *n, *fn;
+       Node *n, *fn, *n1, *n2;
        Sym *sym;
        char buf[100], *p;
 
@@ -771,6 +771,44 @@ walkexpr(Node **np, NodeList **init)
                        l = nod(OADDR, sym->def, N);
                        l->addable = 1;
                        ll = list(ll, l);
+
+                       if(n->left->type->width == widthptr &&
+                          isint[simsimtype(n->left->type)]) {
+                               /* For pointer types, we can make a special form of optimization
+                                *
+                                * These statements are put onto the expression init list:
+                                *      Itab *tab = atomicloadtype(&cache);
+                                *      if(tab == nil)
+                                *              tab = typ2Itab(type, itype, &cache);
+                                *
+                                * The CONVIFACE expression is replaced with this:
+                                *      OEFACE{tab, ptr};
+                                */
+                               l = temp(ptrto(types[TUINT8]));
+
+                               n1 = nod(OAS, l, sym->def);
+                               typecheck(&n1, Etop);
+                               *init = list(*init, n1);
+
+                               fn = syslook("typ2Itab", 1);
+                               n1 = nod(OCALL, fn, N);
+                               n1->list = ll;
+                               typecheck(&n1, Erv);
+                               walkexpr(&n1, init);
+
+                               n2 = nod(OIF, N, N);
+                               n2->ntest = nod(OEQ, l, nodnil());
+                               n2->nbody = list1(nod(OAS, l, n1));
+                               n2->likely = -1;
+                               typecheck(&n2, Etop);
+                               *init = list(*init, n2);
+
+                               l = nod(OEFACE, l, n->left);
+                               l->typecheck = n->typecheck; 
+                               l->type = n->type;
+                               n = l;
+                               goto ret;
+                       }
                }
                ll = list(ll, n->left);
                argtype(fn, n->left->type);
@@ -1168,7 +1206,7 @@ walkexpr(Node **np, NodeList **init)
                else
                        r = nod(OOROR, nod(ONE, nod(OITAB, n->left, N), nod(OITAB, n->right, N)), r);
                typecheck(&r, Erv);
-               walkexpr(&r, nil);
+               walkexpr(&r, init);
                r->type = n->type;
                n = r;
                goto ret;
index 864954d0d523c1973108553cfb0c3c26bc6ccda9..8e0150d07b91c90d98ed4a29b93207ab59a2f8b9 100644 (file)
@@ -183,6 +183,18 @@ copyout(Type *t, void **src, void *dst)
                alg->copy(size, dst, *src);
 }
 
+#pragma textflag 7
+void
+runtime·typ2Itab(Type *t, InterfaceType *inter, Itab **cache, Itab *ret)
+{
+       Itab *tab;
+
+       tab = itab(inter, t, 0);
+       runtime·atomicstorep(cache, tab);
+       ret = tab;
+       FLUSH(&ret);
+}
+
 // func convT2I(typ *byte, typ2 *byte, cache **byte, elem any) (ret any)
 #pragma textflag 7
 void