static void checkreach(Cfg *cfg) { Bitset *reach, *kill; size_t i, j, k; Reaching *r; Node *n, *m; Bb *bb; r = reaching(cfg); // dumpcfg(cfg, stdout); for (i = 0; i < cfg->nbb; i++) { bb = cfg->bb[i]; if (!bb) continue; reach = bsdup(r->in[i]); kill = mkbs(); for (j = 0; j < bb->nnl; j++) { n = bb->nl[j]; if (exprop(n) == Oundef) { bsput(reach, n->nid); } else { m = assignee(n); if (m) for (k = 0; k < r->ndefs[m->expr.did]; k++) bsput(kill, r->defs[m->expr.did][k]); checkundef(n, r, reach, kill); } } bsfree(reach); bsfree(kill); } }
Reaching *reaching(Cfg *cfg) { Bitset **in, **out; Bitset **gen, **kill; Bitset *bbin, *bbout; Reaching *reaching; size_t **defs; /* mapping from did => [def,list] */ size_t *ndefs; size_t i, j; int changed; in = zalloc(cfg->nbb * sizeof(Bb*)); out = zalloc(cfg->nbb * sizeof(Bb*)); gen = zalloc(cfg->nbb * sizeof(Bb*)); kill = zalloc(cfg->nbb * sizeof(Bb*)); defs = zalloc(ndecls * sizeof(size_t*)); ndefs = zalloc(ndecls * sizeof(size_t)); collectdefs(cfg, defs, ndefs); for (i = 0; i < cfg->nbb; i++) { in[i] = mkbs(); out[i] = mkbs(); gen[i] = mkbs(); kill[i] = mkbs(); if (cfg->bb[i]) genkill(cfg->bb[i], defs, ndefs, gen[i], kill[i]); } do { changed = 0; for (i = 0; i < cfg->nbb; i++) { if (!cfg->bb[i]) continue; bbin = mkbs(); for (j = 0; bsiter(cfg->bb[i]->pred, &j); j++) bsunion(bbin, out[j]); bbout = bsdup(bbin); bsdiff(bbout, kill[i]); bsunion(bbout, gen[i]); if (!bseq(out[i], bbout) || !bseq(in[i], bbin)) { changed = 1; bsfree(in[i]); bsfree(out[i]); in[i] = bbin; out[i] = bbout; } } } while (changed); reaching = xalloc(sizeof(Reaching)); reaching->in = in; reaching->out = out; reaching->defs = defs; reaching->ndefs = ndefs; return reaching; }
static Nodes * circbreak1(ASTNode *n) { ASTNode *idx; BitSet *visit; ASTNode *m; int r; if(n->t == ASTASS && n->n2 != nil && n->n2->t == ASTISUB) { idx = n->n2->n1; assert(idx != nil && idx->t == ASTIDX); if(n->n1->t == ASTSSA && idx->n1->t == ASTSSA && idx->n1->semv == idx->n1->semv->sym->semc[1]) { visit = bsnew(nvars); r = findcircles(idx->n1->semv, n->n1->semv, visit); bsfree(visit); if(r) { m = nodedup(n); m->n2 = nodedup(m->n2); m->n2->n1 = nodedup(m->n2->n1); m->n2->n1->n1 = node(ASTSSA, idx->n1->semv->sym->semc[0]); circbroken++; return nl(m); } } } return nl(n); }
/* copy blocks and create definitions for the primed values as needed */ static void makenext(void) { SemBlock *b, *c; BitSet *copy; int i, j, ch; copy = bsnew(nblocks); for(i = 0; i < nblocks; i++) { b = blocks[i]; if(descendsum(b->phi, countnext) + descendsum(b->cont, countnext) > 0) bsadd(copy, i); } do { ch = 0; for(i = -1; i = bsiter(copy, i), i >= 0; ) { b = blocks[i]; for(j = 0; j < b->nto; j++) ch += bsadd(copy, b->to[j]->idx) == 0; for(j = 0; j < b->nfrom; j++) ch += bsadd(copy, b->from[j]->idx) == 0; } } while(ch != 0); dupl = emalloc(nblocks * sizeof(SemBlock *)); for(i = -1; i = bsiter(copy, i), i >= 0; ) dupl[i] = newblock(); for(i = -1; i = bsiter(copy, i), i >= 0; ) { b = blocks[i]; c = dupl[i]; c->nto = b->nto; c->to = emalloc(sizeof(SemBlock *) * c->nto); c->nfrom = b->nfrom; c->from = emalloc(sizeof(SemBlock *) * c->nfrom); for(j = 0; j < b->nto; j++) { c->to[j] = dupl[b->to[j]->idx]; assert(c->to[j] != nil); } for(j = 0; j < b->nfrom; j++) { c->from[j] = dupl[b->from[j]->idx]; assert(c->from[j] != nil); } c->phi = mkblock(descend(b->phi, nil, makenext1)); c->cont = mkblock(descend(b->cont, nil, makenext1)); c->jump = mkblock(descend(b->jump, nil, makenext1)); } for(i = 0; i < nblocks; i++) { b = blocks[i]; b->phi = mkblock(descend(b->phi, nil, deldefs)); b->cont = mkblock(descend(b->cont, nil, deldefs)); } bsfree(copy); }
static void doif(ASTNode *n, int ctxt) { BitSet *g, *k, *kp; BitSet *g1, *k1, *k1p; BitSet *g2, *k2, *k2p, *t; PipeStage *p; p = stcur; t = bsnew(p->nvars); findstages(n->n1, ctxt); g = p->gen; k = p->kill; kp = p->killp; p->gen = g1 = bsdup(g); p->kill = k1 = bsdup(k); p->killp = k1p = bsdup(kp); findstages(n->n2, ctxt); p->gen = g2 = bsdup(g); p->kill = k2 = bsdup(k); p->killp = k2p = bsdup(kp); findstages(n->n3, ctxt); bsunion(g, g1, g); bsunion(g, g2, g); bsunion(k, k1, k); bsunion(k, k2, k); bsunion(kp, k1p, kp); bsunion(kp, k2p, kp); bsminus(t, k1, k2); addeq(t, &n->n3, 0); bsunion(g, t, g); bsminus(t, k2, k1); addeq(t, &n->n2, 0); bsunion(g, t, g); bsminus(t, k1p, k2p); addeq(t, &n->n3, 1); bsunion(g, t, g); bsminus(t, k2p, k1p); addeq(t, &n->n2, 1); bsunion(g, t, g); p->gen = g; p->kill = k; p->killp = kp; bsfree(g1); bsfree(g2); bsfree(k1); bsfree(k2); bsfree(k1p); bsfree(k2p); bsfree(t); }
static void circdefs(void) { int i; BitSet *visit; visit = bsnew(nvars); for(i = 0; i < nvars; i++) { bsreset(visit); if(vars[i] == vars[i]->sym->semc[0] && findcircles(vars[i], vars[i], visit)) error(vars[i]->sym, "combinational loop involving %s", vars[i]->sym->name); bsreset(visit); if(vars[i] == vars[i]->sym->semc[1] && findcircles(vars[i], vars[i], visit)) error(vars[i]->sym, "combinational loop involving %s'", vars[i]->sym->name); } bsfree(visit); }
static Nodes * process(ASTNode *n) { Nodes *r, *s, *t; int ours; BitSet *ks; if(n == nil) return nil; switch(n->t){ case ASTPIPEL: t = nil; s = nil; for(r = n->nl; r != nil; r = r->next) if(r->n->t == ASTSTATE){ if(stcur == nil) stcur = stlist.next; else stcur = stcur->next; assert(stcur != nil && stcur->sym == r->n->sym); bsreset(killed); if(s != nil) t = nlcat(t, nl(node(ASTBLOCK, s))); s = nil; }else s = nlcat(s, process(r->n)); if(s != nil) t = nlcat(t, nl(node(ASTBLOCK, s))); return t; case ASTSYMB: if(stcur != nil && n->sym->pipeidx >= 0) if(bstest(killed, n->sym->pipeidx)) n->sym = stcur->outvars[n->sym->pipeidx]; else n->sym = stcur->invars[n->sym->pipeidx]; return nl(n); case ASTPRIME: ours = 0; return nl(lvalfix(n, 0, &ours)); case ASTASS: n = nodedup(n); n->n2 = onlyone(process(n->n2)); ours = 0; n->n1 = lvalfix(n->n1, LVAL, &ours); return nl(n); case ASTDECL: return nil; case ASTBLOCK: n = nodedup(n); s = nil; for(r = n->nl; r != nil; r = r->next) s = nlcat(s, process(r->n)); n->nl = s; return nl(n); case ASTCINT: case ASTCONST: return nl(n); case ASTOP: case ASTTERN: n = nodedup(n); n->n1 = onlyone(process(n->n1)); n->n2 = onlyone(process(n->n2)); n->n3 = onlyone(process(n->n3)); n->n4 = onlyone(process(n->n4)); return nl(n); case ASTIF: n = nodedup(n); n->n1 = onlyone(process(n->n1)); ks = killed; killed = bsdup(ks); n->n2 = onlyone(process(n->n2)); bsfree(killed); killed = ks; n->n3 = onlyone(process(n->n3)); return nl(n); default: warn(n, "process: unknown %A", n->t); } return nl(n); }