diff --git a/llvm/include/llvm/Transforms/IPO/FunctionSpecialization.h b/llvm/include/llvm/Transforms/IPO/FunctionSpecialization.h --- a/llvm/include/llvm/Transforms/IPO/FunctionSpecialization.h +++ b/llvm/include/llvm/Transforms/IPO/FunctionSpecialization.h @@ -51,6 +51,7 @@ #include "llvm/Analysis/BlockFrequencyInfo.h" #include "llvm/Analysis/CodeMetrics.h" #include "llvm/Analysis/InlineCost.h" +#include "llvm/Analysis/PostDominators.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/InstVisitor.h" #include "llvm/Transforms/Scalar/SCCP.h" @@ -171,6 +172,7 @@ SmallPtrSet Specializations; SmallPtrSet FullySpecialized; DenseMap FunctionMetrics; + DenseSet HasRunBFI; public: FunctionSpecializer( @@ -184,7 +186,17 @@ ~FunctionSpecializer(); - bool isClonedFunction(Function *F) { return Specializations.count(F); } + DomTreeUpdater getDTU(Function &F) { + // We don't have analyses for newly created functions. + if (Specializations.count(&F)) + return DomTreeUpdater(DomTreeUpdater::UpdateStrategy::Lazy); + + DominatorTree &DT = FAM->getResult(F); + PostDominatorTree *PDT = HasRunBFI.contains(&F) ? + &FAM->getResult(F) + : FAM->getCachedResult(F); + return {&DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy}; + } bool run(); diff --git a/llvm/include/llvm/Transforms/Utils/SCCPSolver.h b/llvm/include/llvm/Transforms/Utils/SCCPSolver.h --- a/llvm/include/llvm/Transforms/Utils/SCCPSolver.h +++ b/llvm/include/llvm/Transforms/Utils/SCCPSolver.h @@ -39,13 +39,6 @@ class Value; class ValueLatticeElement; -/// Helper struct for bundling up the analysis results per function for IPSCCP. -struct AnalysisResultsForFn { - std::unique_ptr PredInfo; - DominatorTree *DT; - PostDominatorTree *PDT; -}; - /// Helper struct shared between Function Specialization and SCCP Solver. struct ArgInfo { Argument *Formal; // The Formal argument being analysed. @@ -81,7 +74,7 @@ ~SCCPSolver(); - void addAnalysis(Function &F, AnalysisResultsForFn A); + void addPredicateInfo(Function &F, DominatorTree &DT, AssumptionCache &AC); /// markBlockExecutable - This method can be used by clients to mark all of /// the blocks that are known to be intrinsically live in the processed unit. @@ -90,8 +83,6 @@ const PredicateBase *getPredicateInfoFor(Instruction *I); - DomTreeUpdater getDTU(Function &F); - /// trackValueOfGlobalVariable - Clients can use this method to /// inform the SCCPSolver that it should track loads and stores to the /// specified global variable if it can. This is only legal to call if diff --git a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp --- a/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp +++ b/llvm/lib/Transforms/IPO/FunctionSpecialization.cpp @@ -708,6 +708,7 @@ // there are Specialization candidates, otherwise we are adding unnecessary // overhead. if (!HasCheckedEntryFreq) { + HasRunBFI.insert(F); // Reject cold functions (for some definition of 'cold'). uint64_t EntryFreq = (GetBFI)(*F).getEntryFreq(); if (!ForceSpecialization && EntryFreq < MinEntryFreq) diff --git a/llvm/lib/Transforms/IPO/SCCP.cpp b/llvm/lib/Transforms/IPO/SCCP.cpp --- a/llvm/lib/Transforms/IPO/SCCP.cpp +++ b/llvm/lib/Transforms/IPO/SCCP.cpp @@ -111,7 +111,7 @@ std::function GetTLI, std::function GetTTI, std::function GetAC, - function_ref getAnalysis, + std::function GetDT, bool IsFuncSpecEnabled) { SCCPSolver Solver(DL, GetTLI, M.getContext()); FunctionSpecializer Specializer(Solver, M, FAM, GetBFI, GetTLI, GetTTI, @@ -123,7 +123,7 @@ if (F.isDeclaration()) continue; - Solver.addAnalysis(F, getAnalysis(F)); + Solver.addPredicateInfo(F, GetDT(F), GetAC(F)); // Determine if we can track the function's return values. If so, add the // function to the solver's set of return-tracked functions. @@ -224,10 +224,7 @@ BB, InsertedValues, NumInstRemoved, NumInstReplaced); } - DomTreeUpdater DTU = IsFuncSpecEnabled && Specializer.isClonedFunction(&F) - ? DomTreeUpdater(DomTreeUpdater::UpdateStrategy::Lazy) - : Solver.getDTU(F); - + DomTreeUpdater DTU = Specializer.getDTU(F); // Change dead blocks to unreachable. We do it after replacing constants // in all executable blocks, because changeToUnreachable may remove PHI // nodes in executable blocks we found values for. The function's entry @@ -392,14 +389,11 @@ auto GetAC = [&FAM](Function &F) -> AssumptionCache & { return FAM.getResult(F); }; - auto getAnalysis = [&FAM](Function &F) -> AnalysisResultsForFn { - DominatorTree &DT = FAM.getResult(F); - return { - std::make_unique(F, DT, FAM.getResult(F)), - &DT, FAM.getCachedResult(F) }; + auto GetDT = [&FAM](Function &F) -> DominatorTree & { + return FAM.getResult(F); }; - if (!runIPSCCP(M, DL, &FAM, GetBFI, GetTLI, GetTTI, GetAC, getAnalysis, + if (!runIPSCCP(M, DL, &FAM, GetBFI, GetTLI, GetTTI, GetAC, GetDT, isFuncSpecEnabled())) return PreservedAnalyses::all(); diff --git a/llvm/lib/Transforms/Utils/SCCPSolver.cpp b/llvm/lib/Transforms/Utils/SCCPSolver.cpp --- a/llvm/lib/Transforms/Utils/SCCPSolver.cpp +++ b/llvm/lib/Transforms/Utils/SCCPSolver.cpp @@ -386,7 +386,7 @@ using Edge = std::pair; DenseSet KnownFeasibleEdges; - DenseMap AnalysisResults; + DenseMap> PredInfo; DenseMap> AdditionalUsers; LLVMContext &Ctx; @@ -649,8 +649,8 @@ void visitInstruction(Instruction &I); public: - void addAnalysis(Function &F, AnalysisResultsForFn A) { - AnalysisResults.insert({&F, std::move(A)}); + void addPredicateInfo(Function &F, DominatorTree &DT, AssumptionCache &AC) { + PredInfo.insert({&F, std::make_unique(F, DT, AC)}); } void visitCallInst(CallInst &I) { visitCallBase(I); } @@ -658,16 +658,10 @@ bool markBlockExecutable(BasicBlock *BB); const PredicateBase *getPredicateInfoFor(Instruction *I) { - auto A = AnalysisResults.find(I->getParent()->getParent()); - if (A == AnalysisResults.end()) + auto It = PredInfo.find(I->getParent()->getParent()); + if (It == PredInfo.end()) return nullptr; - return A->second.PredInfo->getPredicateInfoFor(I); - } - - DomTreeUpdater getDTU(Function &F) { - auto A = AnalysisResults.find(&F); - assert(A != AnalysisResults.end() && "Need analysis results for function."); - return {A->second.DT, A->second.PDT, DomTreeUpdater::UpdateStrategy::Lazy}; + return It->second->getPredicateInfoFor(I); } SCCPInstVisitor(const DataLayout &DL, @@ -1943,8 +1937,9 @@ SCCPSolver::~SCCPSolver() = default; -void SCCPSolver::addAnalysis(Function &F, AnalysisResultsForFn A) { - return Visitor->addAnalysis(F, std::move(A)); +void SCCPSolver::addPredicateInfo(Function &F, DominatorTree &DT, + AssumptionCache &AC) { + return Visitor->addPredicateInfo(F, DT, AC); } bool SCCPSolver::markBlockExecutable(BasicBlock *BB) { @@ -1955,8 +1950,6 @@ return Visitor->getPredicateInfoFor(I); } -DomTreeUpdater SCCPSolver::getDTU(Function &F) { return Visitor->getDTU(F); } - void SCCPSolver::trackValueOfGlobalVariable(GlobalVariable *GV) { Visitor->trackValueOfGlobalVariable(GV); } diff --git a/llvm/unittests/Transforms/IPO/FunctionSpecializationTest.cpp b/llvm/unittests/Transforms/IPO/FunctionSpecializationTest.cpp --- a/llvm/unittests/Transforms/IPO/FunctionSpecializationTest.cpp +++ b/llvm/unittests/Transforms/IPO/FunctionSpecializationTest.cpp @@ -62,16 +62,13 @@ auto GetAC = [this](Function &F) -> AssumptionCache & { return FAM.getResult(F); }; - auto GetAnalysis = [this](Function &F) -> AnalysisResultsForFn { - DominatorTree &DT = FAM.getResult(F); - return { std::make_unique(F, DT, - FAM.getResult(F)), - &DT, FAM.getCachedResult(F) }; + auto GetDT = [this](Function &F) -> DominatorTree & { + return FAM.getResult(F); }; Solver = std::make_unique(M->getDataLayout(), GetTLI, Ctx); - Solver->addAnalysis(*F, GetAnalysis(*F)); + Solver->addPredicateInfo(*F, GetDT(*F), GetAC(*F)); Solver->markBlockExecutable(&F->front()); for (Argument &Arg : F->args()) Solver->markOverdefined(&Arg);