/// Checks whether there are checks in the preheader's predecessor that ensure /// that "Start < End". static bool isRangeChecked(SILValue Start, SILValue End, SILBasicBlock *Preheader, DominanceInfo *DT) { // Check two constants. if (isLessThan(Start, End)) return true; // Look for a branch on EQ around the Preheader. auto *PreheaderPred = Preheader->getSinglePredecessor(); if (!PreheaderPred) return false; auto *CondBr = dyn_cast<CondBranchInst>(PreheaderPred->getTerminator()); if (!CondBr) return false; if (isLessThanCheck(Start, End, CondBr, Preheader)) return true; // Walk up the dominator tree looking for a range check ("SLE Start, End"). DominanceInfoNode *CurDTNode = DT->getNode(PreheaderPred); while (CurDTNode) { if (isSignedLessEqual(Start, End, *CurDTNode->getBlock())) return true; CurDTNode = CurDTNode->getIDom(); } return false; }
/// Find a nearest common dominator for a given set of basic blocks. static DominanceInfoNode *findCommonDominator(ArrayRef<SILBasicBlock *> BBs, DominanceInfo *DT) { DominanceInfoNode *CommonDom = nullptr; for (auto *BB : BBs) { if (!CommonDom) { CommonDom = DT->getNode(BB); } else { CommonDom = DT->getNode( DT->findNearestCommonDominator(CommonDom->getBlock(), BB)); } } return CommonDom; }
/// Update the SSA form after all changes. void CheckedCastBrJumpThreading::updateDominatorTree() { // Update the dominator tree. // If BB was IDom of something, then PredCBBI becomes the IDOM // of this after jump-threading. auto *BBDomNode = DT->getNode(BB); auto &Children = BBDomNode->getChildren(); if (Children.size() > 1) { SmallVector<DominanceInfoNode *, 16> ChildrenCopy; std::copy(Children.begin(), Children.end(), std::back_inserter(ChildrenCopy)); for (auto *Child : ChildrenCopy) { DT->changeImmediateDominator(Child, Node); } } DominanceInfoNode *CommonDom; // Find a common dominator for all unknown preds. if (!UnknownPreds.empty()) { // Find a new IDom for FailureBB CommonDom = findCommonDominator(FailureBB, DT); if (CommonDom) DT->changeImmediateDominator(FailureBB, CommonDom->getBlock()); CommonDom = findCommonDominator(UnknownPreds, DT); // This common dominator dominates the BB now. if (CommonDom) { DT->changeImmediateDominator(BB, CommonDom->getBlock()); } } // Find a common dominator for all failure preds. CommonDom = findCommonDominator(FailurePreds, DT); // This common dominator dominates the TargetFailureBB now. if (CommonDom) { DT->addNewBlock(TargetFailureBB, CommonDom->getBlock()); // Find a new IDom for FailureBB CommonDom = findCommonDominator(FailureBB, DT); if (CommonDom) DT->changeImmediateDominator(FailureBB, CommonDom->getBlock()); } // Find a common dominator for all success preds. CommonDom = findCommonDominator(SuccessPreds, DT); // This common dominator of all success preds dominates the BB now. if (CommonDom) { if (TargetSuccessBB) { DT->addNewBlock(TargetSuccessBB, CommonDom->getBlock()); } else { DT->changeImmediateDominator(BB, CommonDom->getBlock()); } CommonDom = findCommonDominator(SuccessBB, DT); if (CommonDom) DT->changeImmediateDominator(SuccessBB, CommonDom->getBlock()); } // End of dominator tree update. }
bool CSE::processFunction(SILFunction &Fm, DominanceInfo *DT) { std::vector<StackNode *> nodesToProcess; // Tables that the pass uses when walking the domtree. ScopedHTType AVTable; AvailableValues = &AVTable; bool Changed = false; // Process the root node. nodesToProcess.push_back(new StackNode(AvailableValues, DT->getRootNode(), DT->getRootNode()->begin(), DT->getRootNode()->end())); // Process the stack. while (!nodesToProcess.empty()) { // Grab the first item off the stack. Set the current generation, remove // the node from the stack, and process it. StackNode *NodeToProcess = nodesToProcess.back(); // Check if the node needs to be processed. if (!NodeToProcess->isProcessed()) { // Process the node. Changed |= processNode(NodeToProcess->node()); NodeToProcess->process(); } else if (NodeToProcess->childIter() != NodeToProcess->end()) { // Push the next child onto the stack. DominanceInfoNode *child = NodeToProcess->nextChild(); nodesToProcess.push_back( new StackNode(AvailableValues, child, child->begin(), child->end())); } else { // It has been processed, and there are no more children to process, // so delete it and pop it off the stack. delete NodeToProcess; nodesToProcess.pop_back(); } } // while (!nodes...) return Changed; }