blob: a104a786afdc38f1d31d26911590fb3bc4710156 [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
Chandler Carruth1ae34c32017-01-15 08:20:50 +000048bool 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
Adam Nemet6100d162016-07-20 21:44:22 +000060Optional<uint64_t> OptimizationRemarkEmitter::computeHotness(const Value *V) {
Adam Nemetaad81602016-07-15 17:23:20 +000061 if (!BFI)
62 return None;
63
64 return BFI->getBlockProfileCount(cast<BasicBlock>(V));
65}
66
Adam Nemeta62b7e12016-09-27 20:55:07 +000067namespace llvm {
68namespace yaml {
69
Adam Nemeta9640662017-01-25 23:20:33 +000070void MappingTraits<DiagnosticInfoOptimizationBase *>::mapping(
71 IO &io, DiagnosticInfoOptimizationBase *&OptDiag) {
72 assert(io.outputting() && "input not yet implemented");
Adam Nemeta62b7e12016-09-27 20:55:07 +000073
Adam Nemet916923e2017-01-26 00:39:51 +000074 if (io.mapTag("!Passed",
75 (OptDiag->getKind() == DK_OptimizationRemark ||
76 OptDiag->getKind() == DK_MachineOptimizationRemark)))
Adam Nemeta9640662017-01-25 23:20:33 +000077 ;
Adam Nemet916923e2017-01-26 00:39:51 +000078 else if (io.mapTag(
79 "!Missed",
80 (OptDiag->getKind() == DK_OptimizationRemarkMissed ||
81 OptDiag->getKind() == DK_MachineOptimizationRemarkMissed)))
Adam Nemeta9640662017-01-25 23:20:33 +000082 ;
Adam Nemet916923e2017-01-26 00:39:51 +000083 else if (io.mapTag(
84 "!Analysis",
85 (OptDiag->getKind() == DK_OptimizationRemarkAnalysis ||
86 OptDiag->getKind() == DK_MachineOptimizationRemarkAnalysis)))
Adam Nemeta9640662017-01-25 23:20:33 +000087 ;
88 else if (io.mapTag("!AnalysisFPCommute",
89 OptDiag->getKind() ==
90 DK_OptimizationRemarkAnalysisFPCommute))
91 ;
92 else if (io.mapTag("!AnalysisAliasing",
93 OptDiag->getKind() ==
94 DK_OptimizationRemarkAnalysisAliasing))
95 ;
96 else
97 llvm_unreachable("todo");
Adam Nemeta62b7e12016-09-27 20:55:07 +000098
Adam Nemeta9640662017-01-25 23:20:33 +000099 // These are read-only for now.
100 DebugLoc DL = OptDiag->getDebugLoc();
101 StringRef FN =
102 GlobalValue::getRealLinkageName(OptDiag->getFunction().getName());
Adam Nemeta62b7e12016-09-27 20:55:07 +0000103
Adam Nemeta9640662017-01-25 23:20:33 +0000104 StringRef PassName(OptDiag->PassName);
105 io.mapRequired("Pass", PassName);
106 io.mapRequired("Name", OptDiag->RemarkName);
107 if (!io.outputting() || DL)
108 io.mapOptional("DebugLoc", DL);
109 io.mapRequired("Function", FN);
110 io.mapOptional("Hotness", OptDiag->Hotness);
111 io.mapOptional("Args", OptDiag->Args);
112}
Adam Nemeta62b7e12016-09-27 20:55:07 +0000113
114template <> struct MappingTraits<DebugLoc> {
115 static void mapping(IO &io, DebugLoc &DL) {
116 assert(io.outputting() && "input not yet implemented");
117
118 auto *Scope = cast<DIScope>(DL.getScope());
119 StringRef File = Scope->getFilename();
120 unsigned Line = DL.getLine();
121 unsigned Col = DL.getCol();
122
123 io.mapRequired("File", File);
124 io.mapRequired("Line", Line);
125 io.mapRequired("Column", Col);
126 }
127
128 static const bool flow = true;
129};
130
Adam Nemet0428e932016-10-04 17:05:04 +0000131// Implement this as a mapping for now to get proper quotation for the value.
132template <> struct MappingTraits<DiagnosticInfoOptimizationBase::Argument> {
133 static void mapping(IO &io, DiagnosticInfoOptimizationBase::Argument &A) {
134 assert(io.outputting() && "input not yet implemented");
135 io.mapRequired(A.Key.data(), A.Val);
Adam Nemetb103fc52016-11-07 22:41:13 +0000136 if (A.DLoc)
137 io.mapOptional("DebugLoc", A.DLoc);
Adam Nemeta62b7e12016-09-27 20:55:07 +0000138 }
Adam Nemeta62b7e12016-09-27 20:55:07 +0000139};
140
141} // end namespace yaml
142} // end namespace llvm
143
144LLVM_YAML_IS_SEQUENCE_VECTOR(DiagnosticInfoOptimizationBase::Argument)
145
146void OptimizationRemarkEmitter::computeHotness(
Adam Nemet484f93d2017-01-25 23:20:25 +0000147 DiagnosticInfoIROptimization &OptDiag) {
Adam Nemeta62b7e12016-09-27 20:55:07 +0000148 Value *V = OptDiag.getCodeRegion();
149 if (V)
150 OptDiag.setHotness(computeHotness(V));
151}
152
Adam Nemet484f93d2017-01-25 23:20:25 +0000153void OptimizationRemarkEmitter::emit(
154 DiagnosticInfoOptimizationBase &OptDiagBase) {
155 auto &OptDiag = cast<DiagnosticInfoIROptimization>(OptDiagBase);
Adam Nemeta62b7e12016-09-27 20:55:07 +0000156 computeHotness(OptDiag);
157
158 yaml::Output *Out = F->getContext().getDiagnosticsOutputFile();
Hal Finkelbdd67352016-10-04 18:13:45 +0000159 if (Out) {
Adam Nemet484f93d2017-01-25 23:20:25 +0000160 auto *P = const_cast<DiagnosticInfoOptimizationBase *>(&OptDiagBase);
Adam Nemeta62b7e12016-09-27 20:55:07 +0000161 *Out << P;
162 }
163 // FIXME: now that IsVerbose is part of DI, filtering for this will be moved
164 // from here to clang.
165 if (!OptDiag.isVerbose() || shouldEmitVerbose())
166 F->getContext().diagnose(OptDiag);
167}
168
Adam Nemet7cfd5972016-07-21 01:07:13 +0000169void OptimizationRemarkEmitter::emitOptimizationRemark(const char *PassName,
170 const DebugLoc &DLoc,
171 const Value *V,
172 const Twine &Msg) {
173 LLVMContext &Ctx = F->getContext();
Adam Nemet04758ba2016-09-27 22:19:23 +0000174 Ctx.diagnose(OptimizationRemark(PassName, *F, DLoc, Msg, computeHotness(V)));
Adam Nemet7cfd5972016-07-21 01:07:13 +0000175}
176
177void OptimizationRemarkEmitter::emitOptimizationRemark(const char *PassName,
178 Loop *L,
179 const Twine &Msg) {
180 emitOptimizationRemark(PassName, L->getStartLoc(), L->getHeader(), Msg);
181}
182
Adam Nemetaad81602016-07-15 17:23:20 +0000183void OptimizationRemarkEmitter::emitOptimizationRemarkMissed(
Adam Nemet6100d162016-07-20 21:44:22 +0000184 const char *PassName, const DebugLoc &DLoc, const Value *V,
Adam Nemetcef33142016-08-26 20:21:05 +0000185 const Twine &Msg, bool IsVerbose) {
Adam Nemetaad81602016-07-15 17:23:20 +0000186 LLVMContext &Ctx = F->getContext();
Adam Nemetcef33142016-08-26 20:21:05 +0000187 if (!IsVerbose || shouldEmitVerbose())
Adam Nemet04758ba2016-09-27 22:19:23 +0000188 Ctx.diagnose(
189 OptimizationRemarkMissed(PassName, *F, DLoc, Msg, computeHotness(V)));
Adam Nemetaad81602016-07-15 17:23:20 +0000190}
191
192void OptimizationRemarkEmitter::emitOptimizationRemarkMissed(
Adam Nemetcef33142016-08-26 20:21:05 +0000193 const char *PassName, Loop *L, const Twine &Msg, bool IsVerbose) {
194 emitOptimizationRemarkMissed(PassName, L->getStartLoc(), L->getHeader(), Msg,
195 IsVerbose);
Adam Nemetaad81602016-07-15 17:23:20 +0000196}
197
Adam Nemet5b3a5cf2016-07-20 21:44:26 +0000198void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysis(
199 const char *PassName, const DebugLoc &DLoc, const Value *V,
Adam Nemetcef33142016-08-26 20:21:05 +0000200 const Twine &Msg, bool IsVerbose) {
Adam Nemet5b3a5cf2016-07-20 21:44:26 +0000201 LLVMContext &Ctx = F->getContext();
Adam Nemetcef33142016-08-26 20:21:05 +0000202 if (!IsVerbose || shouldEmitVerbose())
Adam Nemet04758ba2016-09-27 22:19:23 +0000203 Ctx.diagnose(
204 OptimizationRemarkAnalysis(PassName, *F, DLoc, Msg, computeHotness(V)));
Adam Nemet5b3a5cf2016-07-20 21:44:26 +0000205}
206
207void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysis(
Adam Nemetcef33142016-08-26 20:21:05 +0000208 const char *PassName, Loop *L, const Twine &Msg, bool IsVerbose) {
Adam Nemet5b3a5cf2016-07-20 21:44:26 +0000209 emitOptimizationRemarkAnalysis(PassName, L->getStartLoc(), L->getHeader(),
Adam Nemetcef33142016-08-26 20:21:05 +0000210 Msg, IsVerbose);
Adam Nemet5b3a5cf2016-07-20 21:44:26 +0000211}
212
Adam Nemet0e0e2d52016-07-20 23:50:32 +0000213void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysisFPCommute(
Adam Nemetcbe2a9b2016-07-21 01:11:12 +0000214 const char *PassName, const DebugLoc &DLoc, const Value *V,
215 const Twine &Msg) {
Adam Nemet0e0e2d52016-07-20 23:50:32 +0000216 LLVMContext &Ctx = F->getContext();
Adam Nemet04758ba2016-09-27 22:19:23 +0000217 Ctx.diagnose(OptimizationRemarkAnalysisFPCommute(PassName, *F, DLoc, Msg,
218 computeHotness(V)));
Adam Nemet0e0e2d52016-07-20 23:50:32 +0000219}
220
221void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysisAliasing(
Adam Nemetcbe2a9b2016-07-21 01:11:12 +0000222 const char *PassName, const DebugLoc &DLoc, const Value *V,
223 const Twine &Msg) {
Adam Nemet0e0e2d52016-07-20 23:50:32 +0000224 LLVMContext &Ctx = F->getContext();
Adam Nemet04758ba2016-09-27 22:19:23 +0000225 Ctx.diagnose(OptimizationRemarkAnalysisAliasing(PassName, *F, DLoc, Msg,
226 computeHotness(V)));
Adam Nemet0e0e2d52016-07-20 23:50:32 +0000227}
228
229void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysisAliasing(
230 const char *PassName, Loop *L, const Twine &Msg) {
231 emitOptimizationRemarkAnalysisAliasing(PassName, L->getStartLoc(),
232 L->getHeader(), Msg);
233}
234
Adam Nemet79ac42a2016-07-18 16:29:21 +0000235OptimizationRemarkEmitterWrapperPass::OptimizationRemarkEmitterWrapperPass()
236 : FunctionPass(ID) {
237 initializeOptimizationRemarkEmitterWrapperPassPass(
238 *PassRegistry::getPassRegistry());
239}
240
241bool OptimizationRemarkEmitterWrapperPass::runOnFunction(Function &Fn) {
242 BlockFrequencyInfo *BFI;
Adam Nemetaad81602016-07-15 17:23:20 +0000243
244 if (Fn.getContext().getDiagnosticHotnessRequested())
245 BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI();
246 else
247 BFI = nullptr;
248
Adam Nemet79ac42a2016-07-18 16:29:21 +0000249 ORE = llvm::make_unique<OptimizationRemarkEmitter>(&Fn, BFI);
Adam Nemetaad81602016-07-15 17:23:20 +0000250 return false;
251}
252
Adam Nemet79ac42a2016-07-18 16:29:21 +0000253void OptimizationRemarkEmitterWrapperPass::getAnalysisUsage(
254 AnalysisUsage &AU) const {
Adam Nemetaad81602016-07-15 17:23:20 +0000255 LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU);
256 AU.setPreservesAll();
257}
258
Chandler Carruthdab4eae2016-11-23 17:53:26 +0000259AnalysisKey OptimizationRemarkEmitterAnalysis::Key;
Adam Nemet79ac42a2016-07-18 16:29:21 +0000260
261OptimizationRemarkEmitter
Adam Nemet78d10912016-07-20 21:44:18 +0000262OptimizationRemarkEmitterAnalysis::run(Function &F,
Sean Silva36e0d012016-08-09 00:28:15 +0000263 FunctionAnalysisManager &AM) {
Adam Nemet79ac42a2016-07-18 16:29:21 +0000264 BlockFrequencyInfo *BFI;
265
266 if (F.getContext().getDiagnosticHotnessRequested())
267 BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
268 else
269 BFI = nullptr;
270
271 return OptimizationRemarkEmitter(&F, BFI);
272}
273
274char OptimizationRemarkEmitterWrapperPass::ID = 0;
Adam Nemetaad81602016-07-15 17:23:20 +0000275static const char ore_name[] = "Optimization Remark Emitter";
276#define ORE_NAME "opt-remark-emitter"
277
Adam Nemet79ac42a2016-07-18 16:29:21 +0000278INITIALIZE_PASS_BEGIN(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
279 false, true)
Adam Nemetaad81602016-07-15 17:23:20 +0000280INITIALIZE_PASS_DEPENDENCY(LazyBFIPass)
Adam Nemet79ac42a2016-07-18 16:29:21 +0000281INITIALIZE_PASS_END(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
282 false, true)