mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
gc: O(1) string comparison when lengths differ
R=ken2 CC=golang-dev https://golang.org/cl/2331045
This commit is contained in:
parent
30edda690f
commit
30dd191171
7 changed files with 56 additions and 9 deletions
|
|
@ -820,6 +820,9 @@ bgen(Node *n, int true, Prog *to)
|
||||||
if(n == N)
|
if(n == N)
|
||||||
n = nodbool(1);
|
n = nodbool(1);
|
||||||
|
|
||||||
|
if(n->ninit != nil)
|
||||||
|
genlist(n->ninit);
|
||||||
|
|
||||||
nl = n->left;
|
nl = n->left;
|
||||||
nr = n->right;
|
nr = n->right;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -699,6 +699,9 @@ bgen(Node *n, int true, Prog *to)
|
||||||
if(n == N)
|
if(n == N)
|
||||||
n = nodbool(1);
|
n = nodbool(1);
|
||||||
|
|
||||||
|
if(n->ninit != nil)
|
||||||
|
genlist(n->ninit);
|
||||||
|
|
||||||
nl = n->left;
|
nl = n->left;
|
||||||
nr = n->right;
|
nr = n->right;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -754,6 +754,9 @@ bgen(Node *n, int true, Prog *to)
|
||||||
if(n == N)
|
if(n == N)
|
||||||
n = nodbool(1);
|
n = nodbool(1);
|
||||||
|
|
||||||
|
if(n->ninit != nil)
|
||||||
|
genlist(n->ninit);
|
||||||
|
|
||||||
nl = n->left;
|
nl = n->left;
|
||||||
nr = n->right;
|
nr = n->right;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -248,9 +248,6 @@ gen(Node *n)
|
||||||
|
|
||||||
gen(n->nincr); // contin: incr
|
gen(n->nincr); // contin: incr
|
||||||
patch(p1, pc); // test:
|
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
|
bgen(n->ntest, 0, breakpc); // if(!test) goto break
|
||||||
genlist(n->nbody); // body
|
genlist(n->nbody); // body
|
||||||
gjmp(continpc);
|
gjmp(continpc);
|
||||||
|
|
@ -263,9 +260,6 @@ gen(Node *n)
|
||||||
p1 = gjmp(P); // goto test
|
p1 = gjmp(P); // goto test
|
||||||
p2 = gjmp(P); // p2: goto else
|
p2 = gjmp(P); // p2: goto else
|
||||||
patch(p1, pc); // test:
|
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
|
bgen(n->ntest, 0, p2); // if(!test) goto p2
|
||||||
genlist(n->nbody); // then
|
genlist(n->nbody); // then
|
||||||
p3 = gjmp(P); // goto done
|
p3 = gjmp(P); // goto done
|
||||||
|
|
|
||||||
|
|
@ -1109,6 +1109,7 @@ Type* ptrto(Type *t);
|
||||||
void* remal(void *p, int32 on, int32 n);
|
void* remal(void *p, int32 on, int32 n);
|
||||||
Sym* restrictlookup(char *name, Pkg *pkg);
|
Sym* restrictlookup(char *name, Pkg *pkg);
|
||||||
Node* safeexpr(Node *n, NodeList **init);
|
Node* safeexpr(Node *n, NodeList **init);
|
||||||
|
Node* cheapexpr(Node *n, NodeList **init);
|
||||||
int32 setlineno(Node *n);
|
int32 setlineno(Node *n);
|
||||||
void setmaxarg(Type *t);
|
void setmaxarg(Type *t);
|
||||||
Type* shallow(Type *t);
|
Type* shallow(Type *t);
|
||||||
|
|
|
||||||
|
|
@ -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.
|
* result is assignable if n is.
|
||||||
*/
|
*/
|
||||||
Node*
|
Node*
|
||||||
|
|
@ -2652,6 +2652,24 @@ safeexpr(Node *n, NodeList **init)
|
||||||
// make a copy; must not be used as an lvalue
|
// make a copy; must not be used as an lvalue
|
||||||
if(islvalue(n))
|
if(islvalue(n))
|
||||||
fatal("missing lvalue case in safeexpr: %N", 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);
|
l = nod(OXXX, N, N);
|
||||||
tempname(l, n->type);
|
tempname(l, n->type);
|
||||||
a = nod(OAS, l, n);
|
a = nod(OAS, l, n);
|
||||||
|
|
|
||||||
|
|
@ -654,8 +654,6 @@ walkexpr(Node **np, NodeList **init)
|
||||||
case OAND:
|
case OAND:
|
||||||
case OOR:
|
case OOR:
|
||||||
case OXOR:
|
case OXOR:
|
||||||
case OANDAND:
|
|
||||||
case OOROR:
|
|
||||||
case OSUB:
|
case OSUB:
|
||||||
case OMUL:
|
case OMUL:
|
||||||
case OEQ:
|
case OEQ:
|
||||||
|
|
@ -670,6 +668,17 @@ walkexpr(Node **np, NodeList **init)
|
||||||
walkexpr(&n->right, init);
|
walkexpr(&n->right, init);
|
||||||
goto ret;
|
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 OPRINT:
|
||||||
case OPRINTN:
|
case OPRINTN:
|
||||||
walkexprlist(n->list, init);
|
walkexprlist(n->list, init);
|
||||||
|
|
@ -1196,11 +1205,27 @@ walkexpr(Node **np, NodeList **init)
|
||||||
goto ret;
|
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
|
// sys_cmpstring(s1, s2) :: 0
|
||||||
r = mkcall("cmpstring", types[TINT], init,
|
r = mkcall("cmpstring", types[TINT], init,
|
||||||
conv(n->left, types[TSTRING]),
|
conv(n->left, types[TSTRING]),
|
||||||
conv(n->right, types[TSTRING]));
|
conv(n->right, types[TSTRING]));
|
||||||
r = nod(n->etype, r, nodintconst(0));
|
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);
|
typecheck(&r, Erv);
|
||||||
n = r;
|
n = r;
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue