Index: include/llvm/Analysis/BlockFrequencyInfo.h =================================================================== --- include/llvm/Analysis/BlockFrequencyInfo.h +++ include/llvm/Analysis/BlockFrequencyInfo.h @@ -43,6 +43,8 @@ BlockFrequencyInfo &operator=(BlockFrequencyInfo &&RHS); + ~BlockFrequencyInfo(); + const Function *getFunction() const; const BranchProbabilityInfo *getBPI() const; void view() const; @@ -79,6 +81,53 @@ void print(raw_ostream &OS) const; }; +/// Wraps a BFI to allow lazy computation of the block frequencies. +/// +/// A pass that only conditionally uses BFI can uncondtionally require the +/// analysis without paying for the overhead if BFI doesn't end up being used. +class LazyBlockFrequencyInfo { +public: + LazyBlockFrequencyInfo() + : Calculated(false), F(nullptr), BPI(nullptr), LI(nullptr) {} + + LazyBlockFrequencyInfo(LazyBlockFrequencyInfo &&Arg); + + /// Set up the per-function input. + void setAnalysis(const Function *F, const BranchProbabilityInfo *BPI, + const LoopInfo *LI) { + this->F = F; + this->BPI = BPI; + this->LI = LI; + } + + /// Retrieve the BFI with the block frequencies computed. + BlockFrequencyInfo &getCalculated() { + if (!Calculated) { + assert(F && BPI && LI && "call setAnalysis"); + BFI.calculate(*F, *BPI, *LI); + Calculated = true; + } + return BFI; + } + + const BlockFrequencyInfo &getCalculated() const { + return const_cast(this)->getCalculated(); + } + + void releaseMemory() { + BFI.releaseMemory(); + Calculated = false; + setAnalysis(nullptr, nullptr, nullptr); + } + +private: + BlockFrequencyInfo BFI; + bool Calculated; + const Function *F; + const BranchProbabilityInfo *BPI; + const LoopInfo *LI; +}; + /// \brief Analysis pass which computes \c BlockFrequencyInfo. class BlockFrequencyAnalysis : public AnalysisInfoMixin { @@ -87,7 +136,7 @@ public: /// \brief Provide the result typedef for this analysis pass. - typedef BlockFrequencyInfo Result; + typedef LazyBlockFrequencyInfo Result; /// \brief Run the analysis pass over a function and produce BFI. Result run(Function &F, AnalysisManager &AM); @@ -105,7 +154,7 @@ /// \brief Legacy analysis pass which computes \c BlockFrequencyInfo. class BlockFrequencyInfoWrapperPass : public FunctionPass { - BlockFrequencyInfo BFI; + LazyBlockFrequencyInfo LBFI; public: static char ID; @@ -113,8 +162,8 @@ BlockFrequencyInfoWrapperPass(); ~BlockFrequencyInfoWrapperPass() override; - BlockFrequencyInfo &getBFI() { return BFI; } - const BlockFrequencyInfo &getBFI() const { return BFI; } + BlockFrequencyInfo &getBFI() { return LBFI.getCalculated(); } + const BlockFrequencyInfo &getBFI() const { return LBFI.getCalculated(); } void getAnalysisUsage(AnalysisUsage &AU) const override; @@ -122,7 +171,6 @@ void releaseMemory() override; void print(raw_ostream &OS, const Module *M) const override; }; - } #endif Index: lib/Analysis/BlockFrequencyInfo.cpp =================================================================== --- lib/Analysis/BlockFrequencyInfo.cpp +++ lib/Analysis/BlockFrequencyInfo.cpp @@ -129,6 +129,13 @@ return *this; } +// Explicitly define the default constructor otherwise it would be implicitly +// defined at the first ODR-use which is the BFI member in +// LazyBlockFrequencyInfo in the header. The dtor needs the +// BlockFrequencyInfoImpl template instantiated which is not available in the +// header. +BlockFrequencyInfo::~BlockFrequencyInfo() {} + void BlockFrequencyInfo::calculate(const Function &F, const BranchProbabilityInfo &BPI, const LoopInfo &LI) { @@ -203,6 +210,9 @@ BFI->print(OS); } +LazyBlockFrequencyInfo::LazyBlockFrequencyInfo(LazyBlockFrequencyInfo &&Arg) + : BFI(std::move(Arg.BFI)), Calculated(Arg.Calculated), F(Arg.F), + BPI(Arg.BPI), LI(Arg.LI) {} INITIALIZE_PASS_BEGIN(BlockFrequencyInfoWrapperPass, "block-freq", "Block Frequency Analysis", true, true) @@ -223,7 +233,7 @@ void BlockFrequencyInfoWrapperPass::print(raw_ostream &OS, const Module *) const { - BFI.print(OS); + LBFI.getCalculated().print(OS); } void BlockFrequencyInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { @@ -232,23 +242,24 @@ AU.setPreservesAll(); } -void BlockFrequencyInfoWrapperPass::releaseMemory() { BFI.releaseMemory(); } +void BlockFrequencyInfoWrapperPass::releaseMemory() { LBFI.releaseMemory(); } bool BlockFrequencyInfoWrapperPass::runOnFunction(Function &F) { BranchProbabilityInfo &BPI = getAnalysis().getBPI(); LoopInfo &LI = getAnalysis().getLoopInfo(); - BFI.calculate(F, BPI, LI); + LBFI.setAnalysis(&F, &BPI, &LI); return false; } char BlockFrequencyAnalysis::PassID; -BlockFrequencyInfo BlockFrequencyAnalysis::run(Function &F, - AnalysisManager &AM) { - BlockFrequencyInfo BFI; - BFI.calculate(F, AM.getResult(F), - AM.getResult(F)); - return BFI; + +LazyBlockFrequencyInfo +BlockFrequencyAnalysis::run(Function &F, AnalysisManager &AM) { + LazyBlockFrequencyInfo LBFI; + LBFI.setAnalysis(&F, &AM.getResult(F), + &AM.getResult(F)); + return LBFI; } PreservedAnalyses @@ -256,6 +267,6 @@ OS << "Printing analysis results of BFI for function " << "'" << F.getName() << "':" << "\n"; - AM.getResult(F).print(OS); + AM.getResult(F).getCalculated().print(OS); return PreservedAnalyses::all(); } Index: lib/Transforms/Instrumentation/PGOInstrumentation.cpp =================================================================== --- lib/Transforms/Instrumentation/PGOInstrumentation.cpp +++ lib/Transforms/Instrumentation/PGOInstrumentation.cpp @@ -838,7 +838,7 @@ }; auto LookupBFI = [&FAM](Function &F) { - return &FAM.getResult(F); + return &FAM.getResult(F).getCalculated(); }; if (!InstrumentAllFunctions(M, LookupBPI, LookupBFI)) @@ -929,7 +929,7 @@ }; auto LookupBFI = [&FAM](Function &F) { - return &FAM.getResult(F); + return &FAM.getResult(F).getCalculated(); }; if (!annotateAllFunctions(M, ProfileFileName, LookupBPI, LookupBFI))