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);