]> Cypherpunks repositories - gostls13.git/commitdiff
gc: O(1) string comparison when lengths differ
authorRuss Cox <rsc@golang.org>
Wed, 6 Oct 2010 13:53:12 +0000 (09:53 -0400)
committerRuss Cox <rsc@golang.org>
Wed, 6 Oct 2010 13:53:12 +0000 (09:53 -0400)
R=ken2
CC=golang-dev
https://golang.org/cl/2331045

src/cmd/5g/cgen.c
src/cmd/6g/cgen.c
src/cmd/8g/cgen.c
src/cmd/gc/gen.c
src/cmd/gc/go.h
src/cmd/gc/subr.c
src/cmd/gc/walk.c

index 9306436ee6df8389efad63a118ead07c85613003..9185aa5acd3ea37680aadf58f5f76d41216b9689 100644 (file)
@@ -820,6 +820,9 @@ bgen(Node *n, int true, Prog *to)
        if(n == N)
                n = nodbool(1);
 
+       if(n->ninit != nil)
+               genlist(n->ninit);
+
        nl = n->left;
        nr = n->right;
 
index 9bca759961ee83e8b6ada1c37b0cb636d76658fe..8c6bfd99b8ff00805238b739bb36afef0649de20 100644 (file)
@@ -699,6 +699,9 @@ bgen(Node *n, int true, Prog *to)
        if(n == N)
                n = nodbool(1);
 
+       if(n->ninit != nil)
+               genlist(n->ninit);
+
        nl = n->left;
        nr = n->right;
 
index f054a89f40e67be09b6defa8cef265fe07b793f2..b0fd9917493c82915d953a0f0904e2b414bdfe87 100644 (file)
@@ -754,6 +754,9 @@ bgen(Node *n, int true, Prog *to)
        if(n == N)
                n = nodbool(1);
 
+       if(n->ninit != nil)
+               genlist(n->ninit);
+
        nl = n->left;
        nr = n->right;
 
index 724f16ae61081cd20228ee0ebb61fb95a76f4ffa..d2396aa09f0aa70732c71dbc390cd48f8ffd4b14 100644 (file)
@@ -248,9 +248,6 @@ gen(Node *n)
 
                gen(n->nincr);                          // contin:      incr
                patch(p1, pc);                          // test:
-               if(n->ntest != N)
-                       if(n->ntest->ninit != nil)
-                               genlist(n->ntest->ninit);
                bgen(n->ntest, 0, breakpc);             //              if(!test) goto break
                genlist(n->nbody);                              //              body
                gjmp(continpc);
@@ -263,9 +260,6 @@ gen(Node *n)
                p1 = gjmp(P);                   //              goto test
                p2 = gjmp(P);                   // p2:          goto else
                patch(p1, pc);                          // test:
-               if(n->ntest != N)
-                       if(n->ntest->ninit != nil)
-                               genlist(n->ntest->ninit);
                bgen(n->ntest, 0, p2);                  //              if(!test) goto p2
                genlist(n->nbody);                              //              then
                p3 = gjmp(P);                   //              goto done
index 5dd9356ef4dadd2cb4670c3404533f5e820fa67f..490710b7e00ff6a978b8e4ee0239cb9addbcc22c 100644 (file)
@@ -1109,6 +1109,7 @@ Type*     ptrto(Type *t);
 void*  remal(void *p, int32 on, int32 n);
 Sym*   restrictlookup(char *name, Pkg *pkg);
 Node*  safeexpr(Node *n, NodeList **init);
+Node*  cheapexpr(Node *n, NodeList **init);
 int32  setlineno(Node *n);
 void   setmaxarg(Type *t);
 Type*  shallow(Type *t);
index 00f213e18fae912adb82f13065cb9c7515d3295e..9dd4a386a4775e5691256f0a001936d95dc7a277 100644 (file)
@@ -2595,7 +2595,7 @@ brrev(int a)
 }
 
 /*
- * return side effect-free appending side effects to init.
+ * return side effect-free n, appending side effects to init.
  * result is assignable if n is.
  */
 Node*
@@ -2652,6 +2652,24 @@ safeexpr(Node *n, NodeList **init)
        // make a copy; must not be used as an lvalue
        if(islvalue(n))
                fatal("missing lvalue case in safeexpr: %N", n);
+       return cheapexpr(n, init);
+}
+
+/*
+ * return side-effect free and cheap n, appending side effects to init.
+ * result may not be assignable.
+ */
+Node*
+cheapexpr(Node *n, NodeList **init)
+{
+       Node *a, *l;
+
+       switch(n->op) {
+       case ONAME:
+       case OLITERAL:
+               return n;
+       }
+
        l = nod(OXXX, N, N);
        tempname(l, n->type);
        a = nod(OAS, l, n);
index 803977482e219d8ea998545b1c0702a4e22038e3..a3368aa2d5ff0cf08609fdb6763777924559c33f 100644 (file)
@@ -654,8 +654,6 @@ walkexpr(Node **np, NodeList **init)
        case OAND:
        case OOR:
        case OXOR:
-       case OANDAND:
-       case OOROR:
        case OSUB:
        case OMUL:
        case OEQ:
@@ -669,6 +667,17 @@ walkexpr(Node **np, NodeList **init)
                walkexpr(&n->left, init);
                walkexpr(&n->right, init);
                goto ret;
+       
+       case OANDAND:
+       case OOROR:
+               walkexpr(&n->left, init);
+               // cannot put side effects from n->right on init,
+               // because they cannot run before n->left is checked.
+               // save elsewhere and store on the eventual n->right.
+               ll = nil;
+               walkexpr(&n->right, &ll);
+               n->right->ninit = concat(n->right->ninit, ll);
+               goto ret;
 
        case OPRINT:
        case OPRINTN:
@@ -1196,11 +1205,27 @@ walkexpr(Node **np, NodeList **init)
                        goto ret;
                }
 
+               // prepare for rewrite below
+               if(n->etype == OEQ || n->etype == ONE) {
+                       n->left = cheapexpr(n->left, init);
+                       n->right = cheapexpr(n->right, init);
+               }
+
                // sys_cmpstring(s1, s2) :: 0
                r = mkcall("cmpstring", types[TINT], init,
                        conv(n->left, types[TSTRING]),
                        conv(n->right, types[TSTRING]));
                r = nod(n->etype, r, nodintconst(0));
+
+               // quick check of len before full compare for == or !=
+               if(n->etype == OEQ || n->etype == ONE) {
+                       if(n->etype == OEQ)
+                               r = nod(OANDAND, nod(OEQ, nod(OLEN, n->left, N), nod(OLEN, n->right, N)), r);
+                       else
+                               r = nod(OOROR, nod(ONE, nod(OLEN, n->left, N), nod(OLEN, n->right, N)), r);
+                       typecheck(&r, Erv);
+                       walkexpr(&r, nil);
+               }
                typecheck(&r, Erv);
                n = r;
                goto ret;