diff --git a/src/cmd/gc/array.c b/src/cmd/gc/array.c index 5e53c1ff0e2e6..611fc9fbd406d 100644 --- a/src/cmd/gc/array.c +++ b/src/cmd/gc/array.c @@ -108,20 +108,6 @@ arrayadd(Array *array, void *element) arrayset(array, array->length - 1, element); } -int32 -arrayindexof(Array *array, void *element) -{ - void *p; - int32 i; - - for(i = 0; i < array->length; i++) { - p = arrayget(array, i); - if(memcmp(p, &element, array->size) == 0) - return i; - } - return -1; -} - void arraysort(Array *array, int (*cmp)(const void*, const void*)) { diff --git a/src/cmd/gc/bv.c b/src/cmd/gc/bv.c index 2efbbc565e338..0e8f8d4739477 100644 --- a/src/cmd/gc/bv.c +++ b/src/cmd/gc/bv.c @@ -9,6 +9,8 @@ enum { WORDSIZE = sizeof(uint32), WORDBITS = 32, + WORDMASK = WORDBITS - 1, + WORDSHIFT = 5, }; static uintptr @@ -94,13 +96,35 @@ bvconcat(Bvec *src1, Bvec *src2) int bvget(Bvec *bv, int32 i) { - uint32 mask, word; - if(i < 0 || i >= bv->n) fatal("bvget: index %d is out of bounds with length %d\n", i, bv->n); - mask = 1U << (i % WORDBITS); - word = bv->b[i / WORDBITS] & mask; - return word ? 1 : 0; + return (bv->b[i>>WORDSHIFT] >> (i&WORDMASK)) & 1; +} + +// bvnext returns the smallest index >= i for which bvget(bv, i) == 1. +// If there is no such index, bvnext returns -1. +int +bvnext(Bvec *bv, int32 i) +{ + uint32 w; + + // Jump i ahead to next word with bits. + if((bv->b[i>>WORDSHIFT]>>(i&WORDMASK)) == 0) { + i &= ~WORDMASK; + i += WORDBITS; + while(i < bv->n && bv->b[i>>WORDSHIFT] == 0) + i += WORDBITS; + } + if(i >= bv->n) + return -1; + + // Find 1 bit. + w = bv->b[i>>WORDSHIFT]>>(i&WORDMASK); + while((w&1) == 0) { + w>>=1; + i++; + } + return i; } int @@ -109,7 +133,7 @@ bvisempty(Bvec *bv) int32 i; for(i = 0; i < bv->n; i += WORDBITS) - if(bv->b[i / WORDBITS] != 0) + if(bv->b[i>>WORDSHIFT] != 0) return 0; return 1; } diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index 30b210f92e57d..c3da5f636a388 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -1017,7 +1017,6 @@ int32 arraylength(Array *array); void* arrayget(Array *array, int32 index); void arrayset(Array *array, int32 index, void *element); void arrayadd(Array *array, void *element); -int32 arrayindexof(Array* array, void *element); void arraysort(Array* array, int (*cmp)(const void*, const void*)); /* @@ -1043,6 +1042,7 @@ int bvcmp(Bvec *bv1, Bvec *bv2); void bvcopy(Bvec *dst, Bvec *src); Bvec* bvconcat(Bvec *src1, Bvec *src2); int bvget(Bvec *bv, int32 i); +int32 bvnext(Bvec *bv, int32 i); int bvisempty(Bvec *bv); void bvnot(Bvec *bv); void bvor(Bvec *dst, Bvec *src1, Bvec *src2); diff --git a/src/cmd/gc/plive.c b/src/cmd/gc/plive.c index 9026f6003e81b..e67b0af757b48 100644 --- a/src/cmd/gc/plive.c +++ b/src/cmd/gc/plive.c @@ -283,13 +283,30 @@ getvariables(Node *fn) // For arguments and results, the bitmap covers all variables, // so we must include all the variables, even the ones without // pointers. + // + // The Node.opt field is available for use by optimization passes. + // We use it to hold the index of the node in the variables array, plus 1 + // (so that 0 means the Node is not in the variables array). + // Each pass should clear opt when done, but you never know, + // so clear them all ourselves too. + // The Node.curfn field is supposed to be set to the current function + // already, but for some compiler-introduced names it seems not to be, + // so fix that here. + // Later, when we want to find the index of a node in the variables list, + // we will check that n->curfn == curfn and n->opt > 0. Then n->opt - 1 + // is the index in the variables list. + ll->n->opt = nil; + ll->n->curfn = curfn; switch(ll->n->class) { case PAUTO: - if(haspointers(ll->n->type)) + if(haspointers(ll->n->type)) { + ll->n->opt = (void*)(uintptr)(arraylength(result)+1); arrayadd(result, &ll->n); + } break; case PPARAM: case PPARAMOUT: + ll->n->opt = (void*)(uintptr)(arraylength(result)+1); arrayadd(result, &ll->n); break; } @@ -718,14 +735,16 @@ progeffects(Prog *prog, Array *vars, Bvec *uevar, Bvec *varkill, Bvec *avarinit) } if(info.flags & (LeftRead | LeftWrite | LeftAddr)) { from = &prog->from; - if (from->node != nil && from->sym != nil) { + if (from->node != nil && from->sym != nil && from->node->curfn == curfn) { switch(from->node->class & ~PHEAP) { case PAUTO: case PPARAM: case PPARAMOUT: - pos = arrayindexof(vars, from->node); + pos = (int)(uintptr)from->node->opt - 1; // index in vars if(pos == -1) goto Next; + if(pos >= arraylength(vars) || *(Node**)arrayget(vars, pos) != from->node) + fatal("bad bookkeeping in liveness %N %d", from->node, pos); if(from->node->addrtaken) { bvset(avarinit, pos); } else { @@ -741,14 +760,16 @@ progeffects(Prog *prog, Array *vars, Bvec *uevar, Bvec *varkill, Bvec *avarinit) Next: if(info.flags & (RightRead | RightWrite | RightAddr)) { to = &prog->to; - if (to->node != nil && to->sym != nil) { + if (to->node != nil && to->sym != nil && to->node->curfn == curfn) { switch(to->node->class & ~PHEAP) { case PAUTO: case PPARAM: case PPARAMOUT: - pos = arrayindexof(vars, to->node); + pos = (int)(uintptr)to->node->opt - 1; // index in vars if(pos == -1) goto Next1; + if(pos >= arraylength(vars) || *(Node**)arrayget(vars, pos) != to->node) + fatal("bad bookkeeping in liveness %N %d", to->node, pos); if(to->node->addrtaken) { if(prog->as != AVARKILL) bvset(avarinit, pos); @@ -1020,6 +1041,9 @@ checkptxt(Node *fn, Prog *firstp) { Prog *p; + if(debuglive == 0) + return; + for(p = firstp; p != P; p = p->link) { if(0) print("analyzing '%P'\n", p); @@ -1172,21 +1196,17 @@ twobitlivepointermap(Liveness *lv, Bvec *liveout, Array *vars, Bvec *args, Bvec vlong xoffset; int32 i; - for(i = 0; i < arraylength(vars); i++) { + for(i = 0; (i = bvnext(liveout, i)) >= 0; i++) { node = *(Node**)arrayget(vars, i); switch(node->class) { case PAUTO: - if(bvget(liveout, i)) { - xoffset = node->xoffset + stkptrsize; - twobitwalktype1(node->type, &xoffset, locals); - } + xoffset = node->xoffset + stkptrsize; + twobitwalktype1(node->type, &xoffset, locals); break; case PPARAM: case PPARAMOUT: - if(bvget(liveout, i)) { - xoffset = node->xoffset; - twobitwalktype1(node->type, &xoffset, args); - } + xoffset = node->xoffset; + twobitwalktype1(node->type, &xoffset, args); break; } } @@ -1944,6 +1964,7 @@ liveness(Node *fn, Prog *firstp, Sym *argssym, Sym *livesym) Array *cfg, *vars; Liveness *lv; int debugdelta; + NodeList *l; // Change name to dump debugging information only for a specific function. debugdelta = 0; @@ -1984,6 +2005,9 @@ liveness(Node *fn, Prog *firstp, Sym *argssym, Sym *livesym) twobitwritesymbol(lv->argslivepointers, argssym); // Free everything. + for(l=fn->dcl; l != nil; l = l->next) + if(l->n != N) + l->n->opt = nil; freeliveness(lv); arrayfree(vars); freecfg(cfg);