blob: 50159edf0aecd388dfa5d36aa53d758e5b6da3ef [file] [log] [blame]
Adam Nemetaad81602016-07-15 17:23:20 +00001//===- 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"
Adam Nemet896c09b2016-08-10 00:44:44 +000016#include "llvm/Analysis/BranchProbabilityInfo.h"
Adam Nemetaad81602016-07-15 17:23:20 +000017#include "llvm/Analysis/LazyBlockFrequencyInfo.h"
18#include "llvm/Analysis/LoopInfo.h"
Adam Nemeta62b7e12016-09-27 20:55:07 +000019#include "llvm/IR/DebugInfo.h"
Adam Nemetaad81602016-07-15 17:23:20 +000020#include "llvm/IR/DiagnosticInfo.h"
Adam Nemet896c09b2016-08-10 00:44:44 +000021#include "llvm/IR/Dominators.h"
Adam Nemetaad81602016-07-15 17:23:20 +000022#include "llvm/IR/LLVMContext.h"
23
24using namespace llvm;
25
Adam Nemet896c09b2016-08-10 00:44:44 +000026OptimizationRemarkEmitter::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
Adam Nemet6100d162016-07-20 21:44:22 +000048Optional<uint64_t> OptimizationRemarkEmitter::computeHotness(const Value *V) {
Adam Nemetaad81602016-07-15 17:23:20 +000049 if (!BFI)
50 return None;
51
52 return BFI->getBlockProfileCount(cast<BasicBlock>(V));
53}
54
Adam Nemeta62b7e12016-09-27 20:55:07 +000055namespace llvm {
56namespace yaml {
57
58template <> struct MappingTraits<DiagnosticInfoOptimizationBase *> {
59 static void mapping(IO &io, DiagnosticInfoOptimizationBase *&OptDiag) {
60 assert(io.outputting() && "input not yet implemented");
61
62 if (io.mapTag("!Missed", OptDiag->getKind() == DK_OptimizationRemarkMissed))
63 ;
64 else
65 llvm_unreachable("todo");
66
67 // These are read-only for now.
68 DebugLoc DL = OptDiag->getDebugLoc();
69 StringRef FN = OptDiag->getFunction().getName();
70
71 StringRef PassName(OptDiag->PassName);
72 io.mapRequired("Pass", PassName);
73 io.mapRequired("Name", OptDiag->RemarkName);
74 if (!io.outputting() || DL)
75 io.mapOptional("DebugLoc", DL);
76 io.mapRequired("Function", FN);
77 io.mapOptional("Hotness", OptDiag->Hotness);
78 io.mapOptional("Args", OptDiag->Args);
79 }
80};
81
82template <> struct MappingTraits<DebugLoc> {
83 static void mapping(IO &io, DebugLoc &DL) {
84 assert(io.outputting() && "input not yet implemented");
85
86 auto *Scope = cast<DIScope>(DL.getScope());
87 StringRef File = Scope->getFilename();
88 unsigned Line = DL.getLine();
89 unsigned Col = DL.getCol();
90
91 io.mapRequired("File", File);
92 io.mapRequired("Line", Line);
93 io.mapRequired("Column", Col);
94 }
95
96 static const bool flow = true;
97};
98
99template <> struct ScalarTraits<DiagnosticInfoOptimizationBase::Argument> {
100 static void output(const DiagnosticInfoOptimizationBase::Argument &Arg,
101 void *, llvm::raw_ostream &out) {
102 out << Arg.Key << ": " << Arg.Val;
103 }
104
105 static StringRef input(StringRef scalar, void *,
106 DiagnosticInfoOptimizationBase::Argument &Arg) {
107 llvm_unreachable("input not yet implemented");
108 }
109
110 static bool mustQuote(StringRef) { return false; }
111};
112
113} // end namespace yaml
114} // end namespace llvm
115
116LLVM_YAML_IS_SEQUENCE_VECTOR(DiagnosticInfoOptimizationBase::Argument)
117
118void OptimizationRemarkEmitter::computeHotness(
119 DiagnosticInfoOptimizationBase &OptDiag) {
120 Value *V = OptDiag.getCodeRegion();
121 if (V)
122 OptDiag.setHotness(computeHotness(V));
123}
124
125void OptimizationRemarkEmitter::emit(DiagnosticInfoOptimizationBase &OptDiag) {
126 computeHotness(OptDiag);
127
128 yaml::Output *Out = F->getContext().getDiagnosticsOutputFile();
129 if (Out && OptDiag.isEnabled()) {
130 auto *P = &const_cast<DiagnosticInfoOptimizationBase &>(OptDiag);
131 *Out << P;
132 }
133 // FIXME: now that IsVerbose is part of DI, filtering for this will be moved
134 // from here to clang.
135 if (!OptDiag.isVerbose() || shouldEmitVerbose())
136 F->getContext().diagnose(OptDiag);
137}
138
Adam Nemet7cfd5972016-07-21 01:07:13 +0000139void OptimizationRemarkEmitter::emitOptimizationRemark(const char *PassName,
140 const DebugLoc &DLoc,
141 const Value *V,
142 const Twine &Msg) {
143 LLVMContext &Ctx = F->getContext();
144 Ctx.diagnose(DiagnosticInfoOptimizationRemark(PassName, *F, DLoc, Msg,
145 computeHotness(V)));
146}
147
148void OptimizationRemarkEmitter::emitOptimizationRemark(const char *PassName,
149 Loop *L,
150 const Twine &Msg) {
151 emitOptimizationRemark(PassName, L->getStartLoc(), L->getHeader(), Msg);
152}
153
Adam Nemetaad81602016-07-15 17:23:20 +0000154void OptimizationRemarkEmitter::emitOptimizationRemarkMissed(
Adam Nemet6100d162016-07-20 21:44:22 +0000155 const char *PassName, const DebugLoc &DLoc, const Value *V,
Adam Nemetcef33142016-08-26 20:21:05 +0000156 const Twine &Msg, bool IsVerbose) {
Adam Nemetaad81602016-07-15 17:23:20 +0000157 LLVMContext &Ctx = F->getContext();
Adam Nemetcef33142016-08-26 20:21:05 +0000158 if (!IsVerbose || shouldEmitVerbose())
159 Ctx.diagnose(DiagnosticInfoOptimizationRemarkMissed(PassName, *F, DLoc, Msg,
160 computeHotness(V)));
Adam Nemetaad81602016-07-15 17:23:20 +0000161}
162
163void OptimizationRemarkEmitter::emitOptimizationRemarkMissed(
Adam Nemetcef33142016-08-26 20:21:05 +0000164 const char *PassName, Loop *L, const Twine &Msg, bool IsVerbose) {
165 emitOptimizationRemarkMissed(PassName, L->getStartLoc(), L->getHeader(), Msg,
166 IsVerbose);
Adam Nemetaad81602016-07-15 17:23:20 +0000167}
168
Adam Nemet5b3a5cf2016-07-20 21:44:26 +0000169void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysis(
170 const char *PassName, const DebugLoc &DLoc, const Value *V,
Adam Nemetcef33142016-08-26 20:21:05 +0000171 const Twine &Msg, bool IsVerbose) {
Adam Nemet5b3a5cf2016-07-20 21:44:26 +0000172 LLVMContext &Ctx = F->getContext();
Adam Nemetcef33142016-08-26 20:21:05 +0000173 if (!IsVerbose || shouldEmitVerbose())
174 Ctx.diagnose(DiagnosticInfoOptimizationRemarkAnalysis(
175 PassName, *F, DLoc, Msg, computeHotness(V)));
Adam Nemet5b3a5cf2016-07-20 21:44:26 +0000176}
177
178void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysis(
Adam Nemetcef33142016-08-26 20:21:05 +0000179 const char *PassName, Loop *L, const Twine &Msg, bool IsVerbose) {
Adam Nemet5b3a5cf2016-07-20 21:44:26 +0000180 emitOptimizationRemarkAnalysis(PassName, L->getStartLoc(), L->getHeader(),
Adam Nemetcef33142016-08-26 20:21:05 +0000181 Msg, IsVerbose);
Adam Nemet5b3a5cf2016-07-20 21:44:26 +0000182}
183
Adam Nemet0e0e2d52016-07-20 23:50:32 +0000184void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysisFPCommute(
Adam Nemetcbe2a9b2016-07-21 01:11:12 +0000185 const char *PassName, const DebugLoc &DLoc, const Value *V,
186 const Twine &Msg) {
Adam Nemet0e0e2d52016-07-20 23:50:32 +0000187 LLVMContext &Ctx = F->getContext();
188 Ctx.diagnose(DiagnosticInfoOptimizationRemarkAnalysisFPCommute(
189 PassName, *F, DLoc, Msg, computeHotness(V)));
190}
191
192void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysisAliasing(
Adam Nemetcbe2a9b2016-07-21 01:11:12 +0000193 const char *PassName, const DebugLoc &DLoc, const Value *V,
194 const Twine &Msg) {
Adam Nemet0e0e2d52016-07-20 23:50:32 +0000195 LLVMContext &Ctx = F->getContext();
196 Ctx.diagnose(DiagnosticInfoOptimizationRemarkAnalysisAliasing(
197 PassName, *F, DLoc, Msg, computeHotness(V)));
198}
199
200void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysisAliasing(
201 const char *PassName, Loop *L, const Twine &Msg) {
202 emitOptimizationRemarkAnalysisAliasing(PassName, L->getStartLoc(),
203 L->getHeader(), Msg);
204}
205
Adam Nemet79ac42a2016-07-18 16:29:21 +0000206OptimizationRemarkEmitterWrapperPass::OptimizationRemarkEmitterWrapperPass()
207 : FunctionPass(ID) {
208 initializeOptimizationRemarkEmitterWrapperPassPass(
209 *PassRegistry::getPassRegistry());
210}
211
212bool OptimizationRemarkEmitterWrapperPass::runOnFunction(Function &Fn) {
213 BlockFrequencyInfo *BFI;
Adam Nemetaad81602016-07-15 17:23:20 +0000214
215 if (Fn.getContext().getDiagnosticHotnessRequested())
216 BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI();
217 else
218 BFI = nullptr;
219
Adam Nemet79ac42a2016-07-18 16:29:21 +0000220 ORE = llvm::make_unique<OptimizationRemarkEmitter>(&Fn, BFI);
Adam Nemetaad81602016-07-15 17:23:20 +0000221 return false;
222}
223
Adam Nemet79ac42a2016-07-18 16:29:21 +0000224void OptimizationRemarkEmitterWrapperPass::getAnalysisUsage(
225 AnalysisUsage &AU) const {
Adam Nemetaad81602016-07-15 17:23:20 +0000226 LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU);
227 AU.setPreservesAll();
228}
229
Adam Nemet79ac42a2016-07-18 16:29:21 +0000230char OptimizationRemarkEmitterAnalysis::PassID;
231
232OptimizationRemarkEmitter
Adam Nemet78d10912016-07-20 21:44:18 +0000233OptimizationRemarkEmitterAnalysis::run(Function &F,
Sean Silva36e0d012016-08-09 00:28:15 +0000234 FunctionAnalysisManager &AM) {
Adam Nemet79ac42a2016-07-18 16:29:21 +0000235 BlockFrequencyInfo *BFI;
236
237 if (F.getContext().getDiagnosticHotnessRequested())
238 BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
239 else
240 BFI = nullptr;
241
242 return OptimizationRemarkEmitter(&F, BFI);
243}
244
245char OptimizationRemarkEmitterWrapperPass::ID = 0;
Adam Nemetaad81602016-07-15 17:23:20 +0000246static const char ore_name[] = "Optimization Remark Emitter";
247#define ORE_NAME "opt-remark-emitter"
248
Adam Nemet79ac42a2016-07-18 16:29:21 +0000249INITIALIZE_PASS_BEGIN(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
250 false, true)
Adam Nemetaad81602016-07-15 17:23:20 +0000251INITIALIZE_PASS_DEPENDENCY(LazyBFIPass)
Adam Nemet79ac42a2016-07-18 16:29:21 +0000252INITIALIZE_PASS_END(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
253 false, true)