bool DominatorTree::dominates(const BasicBlockEdge &BBE, const BasicBlock *UseBB) const { // If the BB the edge ends in doesn't dominate the use BB, then the // edge also doesn't. const BasicBlock *Start = BBE.getStart(); const BasicBlock *End = BBE.getEnd(); if (!dominates(End, UseBB)) return false; // Simple case: if the end BB has a single predecessor, the fact that it // dominates the use block implies that the edge also does. if (End->getSinglePredecessor()) return true; // The normal edge from the invoke is critical. Conceptually, what we would // like to do is split it and check if the new block dominates the use. // With X being the new block, the graph would look like: // // DefBB // /\ . . // / \ . . // / \ . . // / \ | | // A X B C // | \ | / // . \|/ // . NormalDest // . // // Given the definition of dominance, NormalDest is dominated by X iff X // dominates all of NormalDest's predecessors (X, B, C in the example). X // trivially dominates itself, so we only have to find if it dominates the // other predecessors. Since the only way out of X is via NormalDest, X can // only properly dominate a node if NormalDest dominates that node too. int IsDuplicateEdge = 0; for (const_pred_iterator PI = pred_begin(End), E = pred_end(End); PI != E; ++PI) { const BasicBlock *BB = *PI; if (BB == Start) { // If there are multiple edges between Start and End, by definition they // can't dominate anything. if (IsDuplicateEdge++) return false; continue; } if (!dominates(End, BB)) return false; } return true; }
bool DominatorTree::dominates(const BasicBlockEdge &BBE, const BasicBlock *UseBB) const { // Assert that we have a single edge. We could handle them by simply // returning false, but since isSingleEdge is linear on the number of // edges, the callers can normally handle them more efficiently. assert(BBE.isSingleEdge()); // If the BB the edge ends in doesn't dominate the use BB, then the // edge also doesn't. const BasicBlock *Start = BBE.getStart(); const BasicBlock *End = BBE.getEnd(); if (!dominates(End, UseBB)) return false; // Simple case: if the end BB has a single predecessor, the fact that it // dominates the use block implies that the edge also does. if (End->getSinglePredecessor()) return true; // The normal edge from the invoke is critical. Conceptually, what we would // like to do is split it and check if the new block dominates the use. // With X being the new block, the graph would look like: // // DefBB // /\ . . // / \ . . // / \ . . // / \ | | // A X B C // | \ | / // . \|/ // . NormalDest // . // // Given the definition of dominance, NormalDest is dominated by X iff X // dominates all of NormalDest's predecessors (X, B, C in the example). X // trivially dominates itself, so we only have to find if it dominates the // other predecessors. Since the only way out of X is via NormalDest, X can // only properly dominate a node if NormalDest dominates that node too. for (const_pred_iterator PI = pred_begin(End), E = pred_end(End); PI != E; ++PI) { const BasicBlock *BB = *PI; if (BB == Start) continue; if (!dominates(End, BB)) return false; } return true; }
bool DominatorTree::dominates(const BasicBlockEdge &BBE, const Use &U) const { Instruction *UserInst = cast<Instruction>(U.getUser()); // A PHI in the end of the edge is dominated by it. PHINode *PN = dyn_cast<PHINode>(UserInst); if (PN && PN->getParent() == BBE.getEnd() && PN->getIncomingBlock(U) == BBE.getStart()) return true; // Otherwise use the edge-dominates-block query, which // handles the crazy critical edge cases properly. const BasicBlock *UseBB; if (PN) UseBB = PN->getIncomingBlock(U); else UseBB = UserInst->getParent(); return dominates(BBE, UseBB); }
bool DominatorTree::dominates(const BasicBlockEdge &BBE, const Use &U) const { // Assert that we have a single edge. We could handle them by simply // returning false, but since isSingleEdge is linear on the number of // edges, the callers can normally handle them more efficiently. assert(BBE.isSingleEdge()); Instruction *UserInst = cast<Instruction>(U.getUser()); // A PHI in the end of the edge is dominated by it. PHINode *PN = dyn_cast<PHINode>(UserInst); if (PN && PN->getParent() == BBE.getEnd() && PN->getIncomingBlock(U) == BBE.getStart()) return true; // Otherwise use the edge-dominates-block query, which // handles the crazy critical edge cases properly. const BasicBlock *UseBB; if (PN) UseBB = PN->getIncomingBlock(U); else UseBB = UserInst->getParent(); return dominates(BBE, UseBB); }