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   // If a diagnostic has a hotness value, then only emit it if its hotness
79   // meets the threshold.
80   if (OptDiag.getHotness() &&
81       *OptDiag.getHotness() <
82           F->getContext().getDiagnosticsHotnessThreshold()) {
83     return;
84   }
85 
86   F->getContext().diagnose(OptDiag);
87 }
88 
89 OptimizationRemarkEmitterWrapperPass::OptimizationRemarkEmitterWrapperPass()
90     : FunctionPass(ID) {
91   initializeOptimizationRemarkEmitterWrapperPassPass(
92       *PassRegistry::getPassRegistry());
93 }
94 
95 bool OptimizationRemarkEmitterWrapperPass::runOnFunction(Function &Fn) {
96   BlockFrequencyInfo *BFI;
97 
98   if (Fn.getContext().getDiagnosticsHotnessRequested())
99     BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI();
100   else
101     BFI = nullptr;
102 
103   ORE = llvm::make_unique<OptimizationRemarkEmitter>(&Fn, BFI);
104   return false;
105 }
106 
107 void OptimizationRemarkEmitterWrapperPass::getAnalysisUsage(
108     AnalysisUsage &AU) const {
109   LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU);
110   AU.setPreservesAll();
111 }
112 
113 AnalysisKey OptimizationRemarkEmitterAnalysis::Key;
114 
115 OptimizationRemarkEmitter
116 OptimizationRemarkEmitterAnalysis::run(Function &F,
117                                        FunctionAnalysisManager &AM) {
118   BlockFrequencyInfo *BFI;
119 
120   if (F.getContext().getDiagnosticsHotnessRequested())
121     BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
122   else
123     BFI = nullptr;
124 
125   return OptimizationRemarkEmitter(&F, BFI);
126 }
127 
128 char OptimizationRemarkEmitterWrapperPass::ID = 0;
129 static const char ore_name[] = "Optimization Remark Emitter";
130 #define ORE_NAME "opt-remark-emitter"
131 
132 INITIALIZE_PASS_BEGIN(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
133                       false, true)
134 INITIALIZE_PASS_DEPENDENCY(LazyBFIPass)
135 INITIALIZE_PASS_END(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
136                     false, true)
137