Index: include/llvm/Analysis/BranchProbabilityInfo.h =================================================================== --- include/llvm/Analysis/BranchProbabilityInfo.h +++ include/llvm/Analysis/BranchProbabilityInfo.h @@ -17,6 +17,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/CFG.h" +#include "llvm/IR/PassManager.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" #include "llvm/Support/BranchProbability.h" @@ -44,6 +45,19 @@ calculate(F, LI); } + BranchProbabilityInfo(BranchProbabilityInfo &&Arg) + : Probs(std::move(Arg.Probs)), LastF(Arg.LastF), + PostDominatedByUnreachable(std::move(Arg.PostDominatedByUnreachable)), + PostDominatedByColdCall(std::move(Arg.PostDominatedByColdCall)) {} + + BranchProbabilityInfo &operator=(BranchProbabilityInfo &&RHS) { + releaseMemory(); + Probs = std::move(RHS.Probs); + PostDominatedByColdCall = std::move(RHS.PostDominatedByColdCall); + PostDominatedByUnreachable = std::move(RHS.PostDominatedByUnreachable); + return *this; + } + void releaseMemory(); void print(raw_ostream &OS) const; @@ -103,6 +117,9 @@ void calculate(const Function &F, const LoopInfo &LI); private: + void operator=(const BranchProbabilityInfo &) = delete; + BranchProbabilityInfo(const BranchProbabilityInfo &) = delete; + // Since we allow duplicate edges from one basic block to another, we use // a pair (PredBlock and an index in the successors) to specify an edge. typedef std::pair Edge; @@ -136,6 +153,30 @@ bool calcInvokeHeuristics(const BasicBlock *BB); }; +/// \brief Analysis pass which computes \c BranchProbabilityInfo. +class BranchProbabilityAnalysis + : public AnalysisInfoMixin { + friend AnalysisInfoMixin; + static char PassID; + +public: + /// \brief Provide the result typedef for this analysis pass. + typedef BranchProbabilityInfo Result; + + /// \brief Run the analysis pass over a function and produce BPI. + BranchProbabilityInfo run(Function &F, AnalysisManager &AM); +}; + +/// \brief Printer pass for the \c BranchProbabilityAnalysis results. +class BranchProbabilityPrinterPass + : public PassInfoMixin { + raw_ostream &OS; + +public: + explicit BranchProbabilityPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Function &F, AnalysisManager &AM); +}; + /// \brief Legacy analysis pass which computes \c BranchProbabilityInfo. class BranchProbabilityInfoWrapperPass : public FunctionPass { BranchProbabilityInfo BPI; Index: lib/Analysis/BranchProbabilityInfo.cpp =================================================================== --- lib/Analysis/BranchProbabilityInfo.cpp +++ lib/Analysis/BranchProbabilityInfo.cpp @@ -689,3 +689,20 @@ const Module *) const { BPI.print(OS); } + +char BranchProbabilityAnalysis::PassID; +BranchProbabilityInfo +BranchProbabilityAnalysis::run(Function &F, AnalysisManager &AM) { + BranchProbabilityInfo BPI; + BPI.calculate(F, AM.getResult(F)); + return BPI; +} + +PreservedAnalyses +BranchProbabilityPrinterPass::run(Function &F, AnalysisManager &AM) { + OS << "Printing analysis results of BPI for function " + << "'" << F.getName() << "':" + << "\n"; + AM.getResult(F).print(OS); + return PreservedAnalyses::all(); +} Index: lib/Passes/PassBuilder.cpp =================================================================== --- lib/Passes/PassBuilder.cpp +++ lib/Passes/PassBuilder.cpp @@ -21,6 +21,7 @@ #include "llvm/Analysis/AliasAnalysisEvaluator.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/BasicAliasAnalysis.h" +#include "llvm/Analysis/BranchProbabilityInfo.h" #include "llvm/Analysis/CFLAliasAnalysis.h" #include "llvm/Analysis/CGSCCPassManager.h" #include "llvm/Analysis/CallGraph.h" Index: lib/Passes/PassRegistry.def =================================================================== --- lib/Passes/PassRegistry.def +++ lib/Passes/PassRegistry.def @@ -68,6 +68,7 @@ #endif FUNCTION_ANALYSIS("aa", AAManager()) FUNCTION_ANALYSIS("assumptions", AssumptionAnalysis()) +FUNCTION_ANALYSIS("branch-prob", BranchProbabilityAnalysis()) FUNCTION_ANALYSIS("domtree", DominatorTreeAnalysis()) FUNCTION_ANALYSIS("postdomtree", PostDominatorTreeAnalysis()) FUNCTION_ANALYSIS("demanded-bits", DemandedBitsAnalysis()) @@ -107,6 +108,7 @@ FUNCTION_PASS("gvn", GVN()) FUNCTION_PASS("print", PrintFunctionPass(dbgs())) FUNCTION_PASS("print", AssumptionPrinterPass(dbgs())) +FUNCTION_PASS("print", BranchProbabilityPrinterPass(dbgs())) FUNCTION_PASS("print", DominatorTreePrinterPass(dbgs())) FUNCTION_PASS("print", PostDominatorTreePrinterPass(dbgs())) FUNCTION_PASS("print", DemandedBitsPrinterPass(dbgs())) Index: test/Analysis/BranchProbabilityInfo/basic.ll =================================================================== --- test/Analysis/BranchProbabilityInfo/basic.ll +++ test/Analysis/BranchProbabilityInfo/basic.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -analyze -branch-prob | FileCheck %s +; RUN: opt < %s -passes='print' -disable-output 2>&1 | FileCheck %s define i32 @test1(i32 %i, i32* %a) { ; CHECK: Printing analysis {{.*}} for function 'test1' Index: test/Analysis/BranchProbabilityInfo/deopt-intrinsic.ll =================================================================== --- test/Analysis/BranchProbabilityInfo/deopt-intrinsic.ll +++ test/Analysis/BranchProbabilityInfo/deopt-intrinsic.ll @@ -1,9 +1,10 @@ ; RUN: opt -analyze -branch-prob < %s | FileCheck %s +; RUN: opt < %s -passes='print' -disable-output 2>&1 | FileCheck %s declare i32 @llvm.experimental.deoptimize.i32(...) define i32 @test1(i32 %a, i32 %b) { -; CHECK-LABEL: Printing analysis 'Branch Probability Analysis' for function 'test1': +; CHECK-LABEL: Printing analysis {{.*}} for function 'test1': entry: %cond = icmp eq i32 %a, 42 br i1 %cond, label %exit, label %deopt Index: test/Analysis/BranchProbabilityInfo/loop.ll =================================================================== --- test/Analysis/BranchProbabilityInfo/loop.ll +++ test/Analysis/BranchProbabilityInfo/loop.ll @@ -1,5 +1,6 @@ ; Test the static branch probability heuristics for no-return functions. ; RUN: opt < %s -analyze -branch-prob | FileCheck %s +; RUN: opt < %s -passes='print' --disable-output 2>&1 | FileCheck %s declare void @g1() declare void @g2() Index: test/Analysis/BranchProbabilityInfo/noreturn.ll =================================================================== --- test/Analysis/BranchProbabilityInfo/noreturn.ll +++ test/Analysis/BranchProbabilityInfo/noreturn.ll @@ -1,5 +1,6 @@ ; Test the static branch probability heuristics for no-return functions. ; RUN: opt < %s -analyze -branch-prob | FileCheck %s +; RUN: opt < %s -passes='print' -disable-output 2>&1 | FileCheck %s declare void @abort() noreturn Index: test/Analysis/BranchProbabilityInfo/pr18705.ll =================================================================== --- test/Analysis/BranchProbabilityInfo/pr18705.ll +++ test/Analysis/BranchProbabilityInfo/pr18705.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -analyze -branch-prob | FileCheck %s +; RUN: opt < %s -passes='print' -disable-output 2>&1 | FileCheck %s ; Since neither of while.body's out-edges is an exit or a back edge, ; calcLoopBranchHeuristics should return early without setting the weights. Index: test/Analysis/BranchProbabilityInfo/pr22718.ll =================================================================== --- test/Analysis/BranchProbabilityInfo/pr22718.ll +++ test/Analysis/BranchProbabilityInfo/pr22718.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -analyze -branch-prob | FileCheck %s +; RUN: opt < %s -passes='print' -disable-output 2>&1 | FileCheck %s ; In this test, the else clause is taken about 90% of the time. This was not ; reflected in the probability computation because the weight is larger than