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; }
// 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(); }