enum {
        WORDSIZE = sizeof(uint32),
        WORDBITS = 32,
+       WORDMASK = WORDBITS - 1,
+       WORDSHIFT = 5,
 };
 
 static uintptr
 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
        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;
 }
 
 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*));
 
 /*
 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);
 
                        // 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;
                        }
        }
        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 {
 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);
 {
        Prog *p;
 
+       if(debuglive == 0)
+               return;
+
        for(p = firstp; p != P; p = p->link) {
                if(0)
                        print("analyzing '%P'\n", p);
        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;
                }
        }
        Array *cfg, *vars;
        Liveness *lv;
        int debugdelta;
+       NodeList *l;
 
        // Change name to dump debugging information only for a specific function.
        debugdelta = 0;
        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);