void DominatorTree::findDominanceFrontiers() { BasicBlock *bb; for (IteratorRef dtIt = iteratorDFS(false); !dtIt->end(); dtIt->next()) { EdgeIterator succIt, chldIt; bb = BasicBlock::get(reinterpret_cast<Node *>(dtIt->get())); bb->getDF().clear(); for (succIt = bb->cfg.outgoing(); !succIt.end(); succIt.next()) { BasicBlock *dfLocal = BasicBlock::get(succIt.getNode()); if (dfLocal->idom() != bb) bb->getDF().insert(dfLocal); } for (chldIt = bb->dom.outgoing(); !chldIt.end(); chldIt.next()) { BasicBlock *cb = BasicBlock::get(chldIt.getNode()); DLList::Iterator dfIt = cb->getDF().iterator(); for (; !dfIt.end(); dfIt.next()) { BasicBlock *dfUp = BasicBlock::get(dfIt); if (dfUp->idom() != bb) bb->getDF().insert(dfUp); } } } }
bool PrintPass::visit(BasicBlock *bb) { #if 0 INFO("---\n"); for (Graph::EdgeIterator ei = bb->cfg.incident(); !ei.end(); ei.next()) INFO(" <- BB:%i (%s)\n", BasicBlock::get(ei.getNode())->getId(), ei.getEdge()->typeStr()); #endif INFO("BB:%i (%u instructions) - ", bb->getId(), bb->getInsnCount()); if (bb->idom()) INFO("idom = BB:%i, ", bb->idom()->getId()); INFO("df = { "); for (DLList::Iterator df = bb->getDF().iterator(); !df.end(); df.next()) INFO("BB:%i ", BasicBlock::get(df)->getId()); INFO("}\n"); for (Graph::EdgeIterator ei = bb->cfg.outgoing(); !ei.end(); ei.next()) INFO(" -> BB:%i (%s)\n", BasicBlock::get(ei.getNode())->getId(), ei.getEdge()->typeStr()); return true; }
void DominatorTree::build() { DLList *bucket = new DLList[count]; Node *nv, *nw; int p, u, v, w; buildDFS(cfg->getRoot()); for (w = count - 1; w >= 1; --w) { nw = vert[w]; assert(nw->tag == w); for (Graph::EdgeIterator ei = nw->incident(); !ei.end(); ei.next()) { nv = ei.getNode(); v = nv->tag; u = eval(v); if (SEMI(u) < SEMI(w)) SEMI(w) = SEMI(u); } p = PARENT(w); bucket[SEMI(w)].insert(nw); link(p, w); for (DLList::Iterator it = bucket[p].iterator(); !it.end(); it.erase()) { v = reinterpret_cast<Node *>(it.get())->tag; u = eval(v); DOM(v) = (SEMI(u) < SEMI(v)) ? u : p; } } for (w = 1; w < count; ++w) { if (DOM(w) != SEMI(w)) DOM(w) = DOM(DOM(w)); } DOM(0) = 0; insert(&BasicBlock::get(cfg->getRoot())->dom); do { p = 0; for (v = 1; v < count; ++v) { nw = &BasicBlock::get(vert[DOM(v)])->dom;; nv = &BasicBlock::get(vert[v])->dom; if (nw->getGraph() && !nv->getGraph()) { ++p; nw->attach(nv, Graph::Edge::TREE); } } } while (p); delete[] bucket; }
// Efficiently Computing Static Single Assignment Form and // the Control Dependence Graph, // R. Cytron, J. Ferrante, B. K. Rosen, M. N. Wegman, F. K. Zadeck bool Function::convertToSSA() { // 0. calculate live in variables (for pruned SSA) buildLiveSets(); // 1. create the dominator tree domTree = new DominatorTree(&cfg); reinterpret_cast<DominatorTree *>(domTree)->findDominanceFrontiers(); // 2. insert PHI functions DLList workList; LValue *lval; BasicBlock *bb; int var; int iterCount = 0; int *hasAlready = new int[allBBlocks.getSize() * 2]; int *work = &hasAlready[allBBlocks.getSize()]; memset(hasAlready, 0, allBBlocks.getSize() * 2 * sizeof(int)); // for each variable for (var = 0; var < allLValues.getSize(); ++var) { if (!allLValues.get(var)) continue; lval = reinterpret_cast<Value *>(allLValues.get(var))->asLValue(); if (!lval || lval->defs.empty()) continue; ++iterCount; // TODO: don't add phi functions for values that aren't used outside // the BB they're defined in // gather blocks with assignments to lval in workList for (Value::DefIterator d = lval->defs.begin(); d != lval->defs.end(); ++d) { bb = ((*d)->getInsn() ? (*d)->getInsn()->bb : NULL); if (!bb) continue; // instruction likely been removed but not XXX deleted if (work[bb->getId()] == iterCount) continue; work[bb->getId()] = iterCount; workList.insert(bb); } // for each block in workList, insert a phi for lval in the block's // dominance frontier (if we haven't already done so) for (DLList::Iterator wI = workList.iterator(); !wI.end(); wI.erase()) { bb = BasicBlock::get(wI); DLList::Iterator dfIter = bb->getDF().iterator(); for (; !dfIter.end(); dfIter.next()) { Instruction *phi; BasicBlock *dfBB = BasicBlock::get(dfIter); if (hasAlready[dfBB->getId()] >= iterCount) continue; hasAlready[dfBB->getId()] = iterCount; // pruned SSA: don't need a phi if the value is not live-in if (!dfBB->liveSet.test(lval->id)) continue; phi = new_Instruction(this, OP_PHI, typeOfSize(lval->reg.size)); dfBB->insertTail(phi); phi->setDef(0, lval); for (int s = 0; s < dfBB->cfg.incidentCount(); ++s) phi->setSrc(s, lval); if (work[dfBB->getId()] < iterCount) { work[dfBB->getId()] = iterCount; wI.insert(dfBB); } } } } delete[] hasAlready; RenamePass rename(this); return rename.run(); }