]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Analysis/OptimizationDiagnosticInfo.cpp
MFV r316124: Fix build when WITHOUT_INET6.
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Analysis / OptimizationDiagnosticInfo.cpp
1 //===- OptimizationDiagnosticInfo.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/OptimizationDiagnosticInfo.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(Function *F)
27     : F(F), BFI(nullptr) {
28   if (!F->getContext().getDiagnosticHotnessRequested())
29     return;
30
31   // First create a dominator tree.
32   DominatorTree DT;
33   DT.recalculate(*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 Optional<uint64_t> OptimizationRemarkEmitter::computeHotness(const Value *V) {
49   if (!BFI)
50     return None;
51
52   return BFI->getBlockProfileCount(cast<BasicBlock>(V));
53 }
54
55 namespace llvm {
56 namespace yaml {
57
58 template <> struct MappingTraits<DiagnosticInfoOptimizationBase *> {
59   static void mapping(IO &io, DiagnosticInfoOptimizationBase *&OptDiag) {
60     assert(io.outputting() && "input not yet implemented");
61
62     if (io.mapTag("!Passed", OptDiag->getKind() == DK_OptimizationRemark))
63       ;
64     else if (io.mapTag("!Missed",
65                        OptDiag->getKind() == DK_OptimizationRemarkMissed))
66       ;
67     else if (io.mapTag("!Analysis",
68                        OptDiag->getKind() == DK_OptimizationRemarkAnalysis))
69       ;
70     else if (io.mapTag("!AnalysisFPCommute",
71                        OptDiag->getKind() ==
72                            DK_OptimizationRemarkAnalysisFPCommute))
73       ;
74     else if (io.mapTag("!AnalysisAliasing",
75                        OptDiag->getKind() ==
76                            DK_OptimizationRemarkAnalysisAliasing))
77       ;
78     else
79       llvm_unreachable("todo");
80
81     // These are read-only for now.
82     DebugLoc DL = OptDiag->getDebugLoc();
83     StringRef FN = GlobalValue::getRealLinkageName(
84         OptDiag->getFunction().getName());
85
86     StringRef PassName(OptDiag->PassName);
87     io.mapRequired("Pass", PassName);
88     io.mapRequired("Name", OptDiag->RemarkName);
89     if (!io.outputting() || DL)
90       io.mapOptional("DebugLoc", DL);
91     io.mapRequired("Function", FN);
92     io.mapOptional("Hotness", OptDiag->Hotness);
93     io.mapOptional("Args", OptDiag->Args);
94   }
95 };
96
97 template <> struct MappingTraits<DebugLoc> {
98   static void mapping(IO &io, DebugLoc &DL) {
99     assert(io.outputting() && "input not yet implemented");
100
101     auto *Scope = cast<DIScope>(DL.getScope());
102     StringRef File = Scope->getFilename();
103     unsigned Line = DL.getLine();
104     unsigned Col = DL.getCol();
105
106     io.mapRequired("File", File);
107     io.mapRequired("Line", Line);
108     io.mapRequired("Column", Col);
109   }
110
111   static const bool flow = true;
112 };
113
114 // Implement this as a mapping for now to get proper quotation for the value.
115 template <> struct MappingTraits<DiagnosticInfoOptimizationBase::Argument> {
116   static void mapping(IO &io, DiagnosticInfoOptimizationBase::Argument &A) {
117     assert(io.outputting() && "input not yet implemented");
118     io.mapRequired(A.Key.data(), A.Val);
119     if (A.DLoc)
120       io.mapOptional("DebugLoc", A.DLoc);
121   }
122 };
123
124 } // end namespace yaml
125 } // end namespace llvm
126
127 LLVM_YAML_IS_SEQUENCE_VECTOR(DiagnosticInfoOptimizationBase::Argument)
128
129 void OptimizationRemarkEmitter::computeHotness(
130     DiagnosticInfoOptimizationBase &OptDiag) {
131   Value *V = OptDiag.getCodeRegion();
132   if (V)
133     OptDiag.setHotness(computeHotness(V));
134 }
135
136 void OptimizationRemarkEmitter::emit(DiagnosticInfoOptimizationBase &OptDiag) {
137   computeHotness(OptDiag);
138
139   yaml::Output *Out = F->getContext().getDiagnosticsOutputFile();
140   if (Out) {
141     auto *P = &const_cast<DiagnosticInfoOptimizationBase &>(OptDiag);
142     *Out << P;
143   }
144   // FIXME: now that IsVerbose is part of DI, filtering for this will be moved
145   // from here to clang.
146   if (!OptDiag.isVerbose() || shouldEmitVerbose())
147     F->getContext().diagnose(OptDiag);
148 }
149
150 void OptimizationRemarkEmitter::emitOptimizationRemark(const char *PassName,
151                                                        const DebugLoc &DLoc,
152                                                        const Value *V,
153                                                        const Twine &Msg) {
154   LLVMContext &Ctx = F->getContext();
155   Ctx.diagnose(OptimizationRemark(PassName, *F, DLoc, Msg, computeHotness(V)));
156 }
157
158 void OptimizationRemarkEmitter::emitOptimizationRemark(const char *PassName,
159                                                        Loop *L,
160                                                        const Twine &Msg) {
161   emitOptimizationRemark(PassName, L->getStartLoc(), L->getHeader(), Msg);
162 }
163
164 void OptimizationRemarkEmitter::emitOptimizationRemarkMissed(
165     const char *PassName, const DebugLoc &DLoc, const Value *V,
166     const Twine &Msg, bool IsVerbose) {
167   LLVMContext &Ctx = F->getContext();
168   if (!IsVerbose || shouldEmitVerbose())
169     Ctx.diagnose(
170         OptimizationRemarkMissed(PassName, *F, DLoc, Msg, computeHotness(V)));
171 }
172
173 void OptimizationRemarkEmitter::emitOptimizationRemarkMissed(
174     const char *PassName, Loop *L, const Twine &Msg, bool IsVerbose) {
175   emitOptimizationRemarkMissed(PassName, L->getStartLoc(), L->getHeader(), Msg,
176                                IsVerbose);
177 }
178
179 void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysis(
180     const char *PassName, const DebugLoc &DLoc, const Value *V,
181     const Twine &Msg, bool IsVerbose) {
182   LLVMContext &Ctx = F->getContext();
183   if (!IsVerbose || shouldEmitVerbose())
184     Ctx.diagnose(
185         OptimizationRemarkAnalysis(PassName, *F, DLoc, Msg, computeHotness(V)));
186 }
187
188 void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysis(
189     const char *PassName, Loop *L, const Twine &Msg, bool IsVerbose) {
190   emitOptimizationRemarkAnalysis(PassName, L->getStartLoc(), L->getHeader(),
191                                  Msg, IsVerbose);
192 }
193
194 void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysisFPCommute(
195     const char *PassName, const DebugLoc &DLoc, const Value *V,
196     const Twine &Msg) {
197   LLVMContext &Ctx = F->getContext();
198   Ctx.diagnose(OptimizationRemarkAnalysisFPCommute(PassName, *F, DLoc, Msg,
199                                                    computeHotness(V)));
200 }
201
202 void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysisAliasing(
203     const char *PassName, const DebugLoc &DLoc, const Value *V,
204     const Twine &Msg) {
205   LLVMContext &Ctx = F->getContext();
206   Ctx.diagnose(OptimizationRemarkAnalysisAliasing(PassName, *F, DLoc, Msg,
207                                                   computeHotness(V)));
208 }
209
210 void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysisAliasing(
211     const char *PassName, Loop *L, const Twine &Msg) {
212   emitOptimizationRemarkAnalysisAliasing(PassName, L->getStartLoc(),
213                                          L->getHeader(), Msg);
214 }
215
216 OptimizationRemarkEmitterWrapperPass::OptimizationRemarkEmitterWrapperPass()
217     : FunctionPass(ID) {
218   initializeOptimizationRemarkEmitterWrapperPassPass(
219       *PassRegistry::getPassRegistry());
220 }
221
222 bool OptimizationRemarkEmitterWrapperPass::runOnFunction(Function &Fn) {
223   BlockFrequencyInfo *BFI;
224
225   if (Fn.getContext().getDiagnosticHotnessRequested())
226     BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI();
227   else
228     BFI = nullptr;
229
230   ORE = llvm::make_unique<OptimizationRemarkEmitter>(&Fn, BFI);
231   return false;
232 }
233
234 void OptimizationRemarkEmitterWrapperPass::getAnalysisUsage(
235     AnalysisUsage &AU) const {
236   LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU);
237   AU.setPreservesAll();
238 }
239
240 AnalysisKey OptimizationRemarkEmitterAnalysis::Key;
241
242 OptimizationRemarkEmitter
243 OptimizationRemarkEmitterAnalysis::run(Function &F,
244                                        FunctionAnalysisManager &AM) {
245   BlockFrequencyInfo *BFI;
246
247   if (F.getContext().getDiagnosticHotnessRequested())
248     BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
249   else
250     BFI = nullptr;
251
252   return OptimizationRemarkEmitter(&F, BFI);
253 }
254
255 char OptimizationRemarkEmitterWrapperPass::ID = 0;
256 static const char ore_name[] = "Optimization Remark Emitter";
257 #define ORE_NAME "opt-remark-emitter"
258
259 INITIALIZE_PASS_BEGIN(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
260                       false, true)
261 INITIALIZE_PASS_DEPENDENCY(LazyBFIPass)
262 INITIALIZE_PASS_END(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
263                     false, true)