Index: llvm/trunk/include/llvm/Analysis/LazyBlockFrequencyInfo.h =================================================================== --- llvm/trunk/include/llvm/Analysis/LazyBlockFrequencyInfo.h +++ llvm/trunk/include/llvm/Analysis/LazyBlockFrequencyInfo.h @@ -18,6 +18,7 @@ #define LLVM_ANALYSIS_LAZYBLOCKFREQUENCYINFO_H #include "llvm/Analysis/BlockFrequencyInfo.h" +#include "llvm/Analysis/LazyBranchProbabilityInfo.h" #include "llvm/Pass.h" namespace llvm { @@ -57,21 +58,21 @@ class LazyBlockFrequencyInfo { public: LazyBlockFrequencyInfo() - : Calculated(false), F(nullptr), BPI(nullptr), LI(nullptr) {} + : Calculated(false), F(nullptr), BPIPass(nullptr), LI(nullptr) {} /// Set up the per-function input. - void setAnalysis(const Function *F, const BranchProbabilityInfo *BPI, + void setAnalysis(const Function *F, LazyBranchProbabilityInfoPass *BPIPass, const LoopInfo *LI) { this->F = F; - this->BPI = BPI; + this->BPIPass = BPIPass; 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); + assert(F && BPIPass && LI && "call setAnalysis"); + BFI.calculate(*F, BPIPass->getBPI(), *LI); Calculated = true; } return BFI; @@ -91,7 +92,7 @@ BlockFrequencyInfo BFI; bool Calculated; const Function *F; - const BranchProbabilityInfo *BPI; + LazyBranchProbabilityInfoPass *BPIPass; const LoopInfo *LI; }; Index: llvm/trunk/include/llvm/Analysis/LazyBranchProbabilityInfo.h =================================================================== --- llvm/trunk/include/llvm/Analysis/LazyBranchProbabilityInfo.h +++ llvm/trunk/include/llvm/Analysis/LazyBranchProbabilityInfo.h @@ -0,0 +1,109 @@ +//===- LazyBranchProbabilityInfo.h - Lazy Branch Probability ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is an alternative analysis pass to BranchProbabilityInfoWrapperPass. +// The difference is that with this pass the branch probabilities are not +// computed when the analysis pass is executed but rather when the BPI results +// is explicitly requested by the analysis client. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LAZYBRANCHPROBABILITYINFO_H +#define LLVM_ANALYSIS_LAZYBRANCHPROBABILITYINFO_H + +#include "llvm/Analysis/BranchProbabilityInfo.h" +#include "llvm/Pass.h" + +namespace llvm { +class AnalysisUsage; +class Function; +class LoopInfo; + +/// \brief This is an alternative analysis pass to +/// BranchProbabilityInfoWrapperPass. The difference is that with this pass the +/// branch probabilities are not computed when the analysis pass is executed but +/// rather when the BPI results is explicitly requested by the analysis client. +/// +/// There are some additional requirements for any client pass that wants to use +/// the analysis: +/// +/// 1. The pass needs to initialize dependent passes with: +/// +/// INITIALIZE_PASS_DEPENDENCY(LazyBPIPass) +/// +/// 2. Similarly, getAnalysisUsage should call: +/// +/// LazyBranchProbabilityInfoPass::getLazyBPIAnalysisUsage(AU) +/// +/// 3. The computed BPI should be requested with +/// getAnalysis().getBPI() before LoopInfo +/// could be invalidated for example by changing the CFG. +/// +/// Note that it is expected that we wouldn't need this functionality for the +/// new PM since with the new PM, analyses are executed on demand. +class LazyBranchProbabilityInfoPass : public FunctionPass { + + /// Wraps a BPI to allow lazy computation of the branch probabilities. + /// + /// A pass that only conditionally uses BPI can uncondtionally require the + /// analysis without paying for the overhead if BPI doesn't end up being used. + class LazyBranchProbabilityInfo { + public: + LazyBranchProbabilityInfo(const Function *F, const LoopInfo *LI) + : Calculated(false), F(F), LI(LI) {} + + /// Retrieve the BPI with the branch probabilities computed. + BranchProbabilityInfo &getCalculated() { + if (!Calculated) { + assert(F && LI && "call setAnalysis"); + BPI.calculate(*F, *LI); + Calculated = true; + } + return BPI; + } + + const BranchProbabilityInfo &getCalculated() const { + return const_cast(this)->getCalculated(); + } + + private: + BranchProbabilityInfo BPI; + bool Calculated; + const Function *F; + const LoopInfo *LI; + }; + + std::unique_ptr LBPI; + +public: + static char ID; + + LazyBranchProbabilityInfoPass(); + + /// \brief Compute and return the branch probabilities. + BranchProbabilityInfo &getBPI() { return LBPI->getCalculated(); } + + /// \brief Compute and return the branch probabilities. + const BranchProbabilityInfo &getBPI() const { return LBPI->getCalculated(); } + + void getAnalysisUsage(AnalysisUsage &AU) const override; + + /// Helper for client passes to set up the analysis usage on behalf of this + /// pass. + static void getLazyBPIAnalysisUsage(AnalysisUsage &AU); + + bool runOnFunction(Function &F) override; + void releaseMemory() override; + void print(raw_ostream &OS, const Module *M) const override; +}; + +/// \brief Helper for client passes to initialize dependent passes for LBPI. +void initializeLazyBPIPassPass(PassRegistry &Registry); +} +#endif Index: llvm/trunk/include/llvm/InitializePasses.h =================================================================== --- llvm/trunk/include/llvm/InitializePasses.h +++ llvm/trunk/include/llvm/InitializePasses.h @@ -165,6 +165,7 @@ void initializeJumpThreadingPass(PassRegistry&); void initializeLCSSAWrapperPassPass(PassRegistry &); void initializeLegacyLICMPassPass(PassRegistry&); +void initializeLazyBranchProbabilityInfoPassPass(PassRegistry&); void initializeLazyBlockFrequencyInfoPassPass(PassRegistry&); void initializeLazyValueInfoWrapperPassPass(PassRegistry&); void initializeLintPass(PassRegistry&); Index: llvm/trunk/lib/Analysis/Analysis.cpp =================================================================== --- llvm/trunk/lib/Analysis/Analysis.cpp +++ llvm/trunk/lib/Analysis/Analysis.cpp @@ -54,6 +54,7 @@ initializeIVUsersWrapperPassPass(Registry); initializeInstCountPass(Registry); initializeIntervalPartitionPass(Registry); + initializeLazyBranchProbabilityInfoPassPass(Registry); initializeLazyBlockFrequencyInfoPassPass(Registry); initializeLazyValueInfoWrapperPassPass(Registry); initializeLintPass(Registry); Index: llvm/trunk/lib/Analysis/CMakeLists.txt =================================================================== --- llvm/trunk/lib/Analysis/CMakeLists.txt +++ llvm/trunk/lib/Analysis/CMakeLists.txt @@ -37,6 +37,7 @@ Interval.cpp IntervalPartition.cpp IteratedDominanceFrontier.cpp + LazyBranchProbabilityInfo.cpp LazyBlockFrequencyInfo.cpp LazyCallGraph.cpp LazyValueInfo.cpp Index: llvm/trunk/lib/Analysis/LazyBlockFrequencyInfo.cpp =================================================================== --- llvm/trunk/lib/Analysis/LazyBlockFrequencyInfo.cpp +++ llvm/trunk/lib/Analysis/LazyBlockFrequencyInfo.cpp @@ -15,7 +15,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/LazyBlockFrequencyInfo.h" -#include "llvm/Analysis/BranchProbabilityInfo.h" +#include "llvm/Analysis/LazyBranchProbabilityInfo.h" #include "llvm/Analysis/LoopInfo.h" using namespace llvm; @@ -24,7 +24,7 @@ INITIALIZE_PASS_BEGIN(LazyBlockFrequencyInfoPass, DEBUG_TYPE, "Lazy Block Frequency Analysis", true, true) -INITIALIZE_PASS_DEPENDENCY(BranchProbabilityInfoWrapperPass) +INITIALIZE_PASS_DEPENDENCY(LazyBPIPass) INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) INITIALIZE_PASS_END(LazyBlockFrequencyInfoPass, DEBUG_TYPE, "Lazy Block Frequency Analysis", true, true) @@ -40,7 +40,7 @@ } void LazyBlockFrequencyInfoPass::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); + LazyBranchProbabilityInfoPass::getLazyBPIAnalysisUsage(AU); AU.addRequired(); AU.setPreservesAll(); } @@ -48,21 +48,20 @@ void LazyBlockFrequencyInfoPass::releaseMemory() { LBFI.releaseMemory(); } bool LazyBlockFrequencyInfoPass::runOnFunction(Function &F) { - BranchProbabilityInfo &BPI = - getAnalysis().getBPI(); + auto &BPIPass = getAnalysis(); LoopInfo &LI = getAnalysis().getLoopInfo(); - LBFI.setAnalysis(&F, &BPI, &LI); + LBFI.setAnalysis(&F, &BPIPass, &LI); return false; } void LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AnalysisUsage &AU) { - AU.addRequired(); + LazyBranchProbabilityInfoPass::getLazyBPIAnalysisUsage(AU); AU.addRequired(); AU.addRequired(); } void llvm::initializeLazyBFIPassPass(PassRegistry &Registry) { - INITIALIZE_PASS_DEPENDENCY(BranchProbabilityInfoWrapperPass); + initializeLazyBPIPassPass(Registry); INITIALIZE_PASS_DEPENDENCY(LazyBlockFrequencyInfoPass); INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass); } Index: llvm/trunk/lib/Analysis/LazyBranchProbabilityInfo.cpp =================================================================== --- llvm/trunk/lib/Analysis/LazyBranchProbabilityInfo.cpp +++ llvm/trunk/lib/Analysis/LazyBranchProbabilityInfo.cpp @@ -0,0 +1,63 @@ +//===- LazyBranchProbabilityInfo.cpp - Lazy Branch Probability Analysis ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is an alternative analysis pass to BranchProbabilityInfoWrapperPass. +// The difference is that with this pass the branch probabilities are not +// computed when the analysis pass is executed but rather when the BPI results +// is explicitly requested by the analysis client. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/LazyBranchProbabilityInfo.h" +#include "llvm/Analysis/LoopInfo.h" + +using namespace llvm; + +#define DEBUG_TYPE "lazy-branch-prob" + +INITIALIZE_PASS_BEGIN(LazyBranchProbabilityInfoPass, DEBUG_TYPE, + "Lazy Branch Probability Analysis", true, true) +INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) +INITIALIZE_PASS_END(LazyBranchProbabilityInfoPass, DEBUG_TYPE, + "Lazy Branch Probability Analysis", true, true) + +char LazyBranchProbabilityInfoPass::ID = 0; + +LazyBranchProbabilityInfoPass::LazyBranchProbabilityInfoPass() + : FunctionPass(ID) { + initializeLazyBranchProbabilityInfoPassPass(*PassRegistry::getPassRegistry()); +} + +void LazyBranchProbabilityInfoPass::print(raw_ostream &OS, + const Module *) const { + LBPI->getCalculated().print(OS); +} + +void LazyBranchProbabilityInfoPass::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.setPreservesAll(); +} + +void LazyBranchProbabilityInfoPass::releaseMemory() { LBPI.reset(); } + +bool LazyBranchProbabilityInfoPass::runOnFunction(Function &F) { + LoopInfo &LI = getAnalysis().getLoopInfo(); + LBPI = llvm::make_unique(&F, &LI); + return false; +} + +void LazyBranchProbabilityInfoPass::getLazyBPIAnalysisUsage(AnalysisUsage &AU) { + AU.addRequired(); + AU.addRequired(); +} + +void llvm::initializeLazyBPIPassPass(PassRegistry &Registry) { + INITIALIZE_PASS_DEPENDENCY(LazyBranchProbabilityInfoPass); + INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass); +} Index: llvm/trunk/test/Analysis/BranchProbabilityInfo/basic.ll =================================================================== --- llvm/trunk/test/Analysis/BranchProbabilityInfo/basic.ll +++ llvm/trunk/test/Analysis/BranchProbabilityInfo/basic.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -analyze -branch-prob | FileCheck %s +; RUN: opt < %s -analyze -lazy-branch-prob | FileCheck %s ; RUN: opt < %s -passes='print' -disable-output 2>&1 | FileCheck %s define i32 @test1(i32 %i, i32* %a) { Index: llvm/trunk/test/Transforms/LoopDistribute/diagnostics-with-hotness-lazy-BFI.ll =================================================================== --- llvm/trunk/test/Transforms/LoopDistribute/diagnostics-with-hotness-lazy-BFI.ll +++ llvm/trunk/test/Transforms/LoopDistribute/diagnostics-with-hotness-lazy-BFI.ll @@ -1,18 +1,24 @@ ; Check that BFI is not computed when -pass-remarks-with-hotness is off ; RUN: opt -loop-distribute -S -pass-remarks-missed=loop-distribute \ -; RUN: -debug-only=block-freq -pass-remarks-with-hotness < %s 2>&1 | FileCheck %s --check-prefix=HOTNESS +; RUN: -debug-only=block-freq,branch-prob -pass-remarks-with-hotness \ +; RUN: < %s 2>&1 | FileCheck %s --check-prefix=HOTNESS ; RUN: opt -loop-distribute -S -pass-remarks-missed=loop-distribute \ -; RUN: -debug-only=block-freq < %s 2>&1 | FileCheck %s --check-prefix=NO_HOTNESS +; RUN: -debug-only=block-freq,branch-prob \ +; RUN: < %s 2>&1 | FileCheck %s --check-prefix=NO_HOTNESS ; RUN: opt -passes='require,loop-distribute' -S -pass-remarks-missed=loop-distribute \ -; RUN: -debug-only=block-freq -pass-remarks-with-hotness < %s 2>&1 | FileCheck %s --check-prefix=HOTNESS +; RUN: -debug-only=block-freq,branch-prob -pass-remarks-with-hotness \ +; RUN: < %s 2>&1 | FileCheck %s --check-prefix=HOTNESS ; RUN: opt -passes='require,loop-distribute' -S -pass-remarks-missed=loop-distribute \ -; RUN: -debug-only=block-freq < %s 2>&1 | FileCheck %s --check-prefix=NO_HOTNESS +; RUN: -debug-only=block-freq,branch-prob \ +; RUN: < %s 2>&1 | FileCheck %s --check-prefix=NO_HOTNESS ; REQUIRES: asserts +; HOTNESS: Branch Probability Info : forced ; HOTNESS: block-frequency: forced +; NO_HOTNESS-NOT: Branch Probability Info : forced ; NO_HOTNESS-NOT: block-frequency: forced ; This is the input program: