1 //===- OptimizationRemarkEmitter.cpp - Optimization Diagnostic --*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Optimization diagnostic interfaces.  It's packaged as an analysis pass so
11 // that by using this service passes become dependent on BFI as well.  BFI is
12 // used to compute the "hotness" of the diagnostic message.
13 //===----------------------------------------------------------------------===//
14 
15 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
16 #include "llvm/Analysis/BranchProbabilityInfo.h"
17 #include "llvm/Analysis/LazyBlockFrequencyInfo.h"
18 #include "llvm/Analysis/LoopInfo.h"
19 #include "llvm/IR/DebugInfo.h"
20 #include "llvm/IR/DiagnosticInfo.h"
21 #include "llvm/IR/Dominators.h"
22 #include "llvm/IR/LLVMContext.h"
23 
24 using namespace llvm;
25 
26 OptimizationRemarkEmitter::OptimizationRemarkEmitter(const Function *F)
27     : F(F), BFI(nullptr) {
28   if (!F->getContext().getDiagnosticsHotnessRequested())
29     return;
30 
31   // First create a dominator tree.
32   DominatorTree DT;
33   DT.recalculate(*const_cast<Function *>(F));
34 
35   // Generate LoopInfo from it.
36   LoopInfo LI;
37   LI.analyze(DT);
38 
39   // Then compute BranchProbabilityInfo.
40   BranchProbabilityInfo BPI;
41   BPI.calculate(*F, LI);
42 
43   // Finally compute BFI.
44   OwnedBFI = llvm::make_unique<BlockFrequencyInfo>(*F, BPI, LI);
45   BFI = OwnedBFI.get();
46 }
47 
48 bool OptimizationRemarkEmitter::invalidate(
49     Function &F, const PreservedAnalyses &PA,
50     FunctionAnalysisManager::Invalidator &Inv) {
51   // This analysis has no state and so can be trivially preserved but it needs
52   // a fresh view of BFI if it was constructed with one.
53   if (BFI && Inv.invalidate<BlockFrequencyAnalysis>(F, PA))
54     return true;
55 
56   // Otherwise this analysis result remains valid.
57   return false;
58 }
59 
60 Optional<uint64_t> OptimizationRemarkEmitter::computeHotness(const Value *V) {
61   if (!BFI)
62     return None;
63 
64   return BFI->getBlockProfileCount(cast<BasicBlock>(V));
65 }
66 
67 void OptimizationRemarkEmitter::computeHotness(
68     DiagnosticInfoIROptimization &OptDiag) {
69   const Value *V = OptDiag.getCodeRegion();
70   if (V)
71     OptDiag.setHotness(computeHotness(V));
72 }
73 
74 void OptimizationRemarkEmitter::emit(
75     DiagnosticInfoOptimizationBase &OptDiagBase) {
76   auto &OptDiag = cast<DiagnosticInfoIROptimization>(OptDiagBase);
77   computeHotness(OptDiag);
78 
79   // Only emit it if its hotness meets the threshold.
80   if (OptDiag.getHotness().getValueOr(0) <
81       F->getContext().getDiagnosticsHotnessThreshold()) {
82     return;
83   }
84 
85   F->getContext().diagnose(OptDiag);
86 }
87 
88 OptimizationRemarkEmitterWrapperPass::OptimizationRemarkEmitterWrapperPass()
89     : FunctionPass(ID) {
90   initializeOptimizationRemarkEmitterWrapperPassPass(
91       *PassRegistry::getPassRegistry());
92 }
93 
94 bool OptimizationRemarkEmitterWrapperPass::runOnFunction(Function &Fn) {
95   BlockFrequencyInfo *BFI;
96 
97   if (Fn.getContext().getDiagnosticsHotnessRequested())
98     BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI();
99   else
100     BFI = nullptr;
101 
102   ORE = llvm::make_unique<OptimizationRemarkEmitter>(&Fn, BFI);
103   return false;
104 }
105 
106 void OptimizationRemarkEmitterWrapperPass::getAnalysisUsage(
107     AnalysisUsage &AU) const {
108   LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU);
109   AU.setPreservesAll();
110 }
111 
112 AnalysisKey OptimizationRemarkEmitterAnalysis::Key;
113 
114 OptimizationRemarkEmitter
115 OptimizationRemarkEmitterAnalysis::run(Function &F,
116                                        FunctionAnalysisManager &AM) {
117   BlockFrequencyInfo *BFI;
118 
119   if (F.getContext().getDiagnosticsHotnessRequested())
120     BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
121   else
122     BFI = nullptr;
123 
124   return OptimizationRemarkEmitter(&F, BFI);
125 }
126 
127 char OptimizationRemarkEmitterWrapperPass::ID = 0;
128 static const char ore_name[] = "Optimization Remark Emitter";
129 #define ORE_NAME "opt-remark-emitter"
130 
131 INITIALIZE_PASS_BEGIN(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
132                       false, true)
133 INITIALIZE_PASS_DEPENDENCY(LazyBFIPass)
134 INITIALIZE_PASS_END(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
135                     false, true)
136