diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Transforms/Scalar/CallSiteSplitting.cpp | 39 |
1 files changed, 26 insertions, 13 deletions
diff --git a/llvm/lib/Transforms/Scalar/CallSiteSplitting.cpp b/llvm/lib/Transforms/Scalar/CallSiteSplitting.cpp index fc7450a7d9c..2be41605c98 100644 --- a/llvm/lib/Transforms/Scalar/CallSiteSplitting.cpp +++ b/llvm/lib/Transforms/Scalar/CallSiteSplitting.cpp @@ -149,14 +149,14 @@ static void recordCondition(CallSite CS, BasicBlock *From, BasicBlock *To, /// Record ICmp conditions relevant to any argument in CS following Pred's /// single predecessors. If there are conflicting conditions along a path, like -/// x == 1 and x == 0, the first condition will be used. +/// x == 1 and x == 0, the first condition will be used. We stop once we reach +/// an edge to StopAt. static void recordConditions(CallSite CS, BasicBlock *Pred, - ConditionsTy &Conditions) { - recordCondition(CS, Pred, CS.getInstruction()->getParent(), Conditions); + ConditionsTy &Conditions, BasicBlock *StopAt) { BasicBlock *From = Pred; BasicBlock *To = Pred; SmallPtrSet<BasicBlock *, 4> Visited; - while (!Visited.count(From->getSinglePredecessor()) && + while (To != StopAt && !Visited.count(From->getSinglePredecessor()) && (From = From->getSinglePredecessor())) { recordCondition(CS, From, To, Conditions); Visited.insert(From); @@ -453,15 +453,27 @@ static PredsWithCondsTy shouldSplitOnPHIPredicatedArgument(CallSite CS) { // Checks if any of the arguments in CS are predicated in a predecessor and // returns a list of predecessors with the conditions that hold on their edges // to CS. -static PredsWithCondsTy shouldSplitOnPredicatedArgument(CallSite CS) { +static PredsWithCondsTy shouldSplitOnPredicatedArgument(CallSite CS, + DomTreeUpdater &DTU) { auto Preds = getTwoPredecessors(CS.getInstruction()->getParent()); if (Preds[0] == Preds[1]) return {}; + // We can stop recording conditions once we reached the immediate dominator + // for the block containing the call site. Conditions in predecessors of the + // that node will be the same for all paths to the call site and splitting + // is not beneficial. + assert(DTU.hasDomTree() && "We need a DTU with a valid DT!"); + auto *CSDTNode = DTU.getDomTree().getNode(CS.getInstruction()->getParent()); + BasicBlock *StopAt = CSDTNode ? CSDTNode->getIDom()->getBlock() : nullptr; + SmallVector<std::pair<BasicBlock *, ConditionsTy>, 2> PredsCS; for (auto *Pred : make_range(Preds.rbegin(), Preds.rend())) { ConditionsTy Conditions; - recordConditions(CS, Pred, Conditions); + // Record condition on edge BB(CS) <- Pred + recordCondition(CS, Pred, CS.getInstruction()->getParent(), Conditions); + // Record conditions following Pred's single predecessors. + recordConditions(CS, Pred, Conditions, StopAt); PredsCS.push_back({Pred, Conditions}); } @@ -479,7 +491,7 @@ static bool tryToSplitCallSite(CallSite CS, TargetTransformInfo &TTI, if (!CS.arg_size() || !canSplitCallSite(CS, TTI)) return false; - auto PredsWithConds = shouldSplitOnPredicatedArgument(CS); + auto PredsWithConds = shouldSplitOnPredicatedArgument(CS, DTU); if (PredsWithConds.empty()) PredsWithConds = shouldSplitOnPHIPredicatedArgument(CS); if (PredsWithConds.empty()) @@ -490,9 +502,9 @@ static bool tryToSplitCallSite(CallSite CS, TargetTransformInfo &TTI, } static bool doCallSiteSplitting(Function &F, TargetLibraryInfo &TLI, - TargetTransformInfo &TTI, DominatorTree *DT) { + TargetTransformInfo &TTI, DominatorTree &DT) { - DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy); + DomTreeUpdater DTU(&DT, DomTreeUpdater::UpdateStrategy::Lazy); bool Changed = false; for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE;) { BasicBlock &BB = *BI++; @@ -537,6 +549,7 @@ struct CallSiteSplittingLegacyPass : public FunctionPass { void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired<TargetLibraryInfoWrapperPass>(); AU.addRequired<TargetTransformInfoWrapperPass>(); + AU.addRequired<DominatorTreeWrapperPass>(); AU.addPreserved<DominatorTreeWrapperPass>(); FunctionPass::getAnalysisUsage(AU); } @@ -547,9 +560,8 @@ struct CallSiteSplittingLegacyPass : public FunctionPass { auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(); auto &TTI = getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F); - auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>(); - return doCallSiteSplitting(F, TLI, TTI, - DTWP ? &DTWP->getDomTree() : nullptr); + auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); + return doCallSiteSplitting(F, TLI, TTI, DT); } }; } // namespace @@ -559,6 +571,7 @@ INITIALIZE_PASS_BEGIN(CallSiteSplittingLegacyPass, "callsite-splitting", "Call-site splitting", false, false) INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) +INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_END(CallSiteSplittingLegacyPass, "callsite-splitting", "Call-site splitting", false, false) FunctionPass *llvm::createCallSiteSplittingPass() { @@ -569,7 +582,7 @@ PreservedAnalyses CallSiteSplittingPass::run(Function &F, FunctionAnalysisManager &AM) { auto &TLI = AM.getResult<TargetLibraryAnalysis>(F); auto &TTI = AM.getResult<TargetIRAnalysis>(F); - auto *DT = AM.getCachedResult<DominatorTreeAnalysis>(F); + auto &DT = AM.getResult<DominatorTreeAnalysis>(F); if (!doCallSiteSplitting(F, TLI, TTI, DT)) return PreservedAnalyses::all(); |