blob: fa8b07d61b01e5b896206a989bd9ed06fe15a469 [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
Adam Nemetc507ac92016-09-27 23:47:03 +000062 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))
Adam Nemeta62b7e12016-09-27 20:55:07 +000069 ;
Adam Nemet2780ee02016-10-04 17:05:01 +000070 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 ;
Adam Nemeta62b7e12016-09-27 20:55:07 +000078 else
79 llvm_unreachable("todo");
80
81 // These are read-only for now.
82 DebugLoc DL = OptDiag->getDebugLoc();
Adam Nemet7da20c32016-11-10 17:47:03 +000083 StringRef FN = GlobalValue::getRealLinkageName(
84 OptDiag->getFunction().getName());
Adam Nemeta62b7e12016-09-27 20:55:07 +000085
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
97template <> 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
Adam Nemet0428e932016-10-04 17:05:04 +0000114// Implement this as a mapping for now to get proper quotation for the value.
115template <> 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);
Adam Nemetb103fc52016-11-07 22:41:13 +0000119 if (A.DLoc)
120 io.mapOptional("DebugLoc", A.DLoc);
Adam Nemeta62b7e12016-09-27 20:55:07 +0000121 }
Adam Nemeta62b7e12016-09-27 20:55:07 +0000122};
123
124} // end namespace yaml
125} // end namespace llvm
126
127LLVM_YAML_IS_SEQUENCE_VECTOR(DiagnosticInfoOptimizationBase::Argument)
128
129void OptimizationRemarkEmitter::computeHotness(
130 DiagnosticInfoOptimizationBase &OptDiag) {
131 Value *V = OptDiag.getCodeRegion();
132 if (V)
133 OptDiag.setHotness(computeHotness(V));
134}
135
136void OptimizationRemarkEmitter::emit(DiagnosticInfoOptimizationBase &OptDiag) {
137 computeHotness(OptDiag);
138
139 yaml::Output *Out = F->getContext().getDiagnosticsOutputFile();
Hal Finkelbdd67352016-10-04 18:13:45 +0000140 if (Out) {
Adam Nemeta62b7e12016-09-27 20:55:07 +0000141 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
Adam Nemet7cfd5972016-07-21 01:07:13 +0000150void OptimizationRemarkEmitter::emitOptimizationRemark(const char *PassName,
151 const DebugLoc &DLoc,
152 const Value *V,
153 const Twine &Msg) {
154 LLVMContext &Ctx = F->getContext();
Adam Nemet04758ba2016-09-27 22:19:23 +0000155 Ctx.diagnose(OptimizationRemark(PassName, *F, DLoc, Msg, computeHotness(V)));
Adam Nemet7cfd5972016-07-21 01:07:13 +0000156}
157
158void OptimizationRemarkEmitter::emitOptimizationRemark(const char *PassName,
159 Loop *L,
160 const Twine &Msg) {
161 emitOptimizationRemark(PassName, L->getStartLoc(), L->getHeader(), Msg);
162}
163
Adam Nemetaad81602016-07-15 17:23:20 +0000164void OptimizationRemarkEmitter::emitOptimizationRemarkMissed(
Adam Nemet6100d162016-07-20 21:44:22 +0000165 const char *PassName, const DebugLoc &DLoc, const Value *V,
Adam Nemetcef33142016-08-26 20:21:05 +0000166 const Twine &Msg, bool IsVerbose) {
Adam Nemetaad81602016-07-15 17:23:20 +0000167 LLVMContext &Ctx = F->getContext();
Adam Nemetcef33142016-08-26 20:21:05 +0000168 if (!IsVerbose || shouldEmitVerbose())
Adam Nemet04758ba2016-09-27 22:19:23 +0000169 Ctx.diagnose(
170 OptimizationRemarkMissed(PassName, *F, DLoc, Msg, computeHotness(V)));
Adam Nemetaad81602016-07-15 17:23:20 +0000171}
172
173void OptimizationRemarkEmitter::emitOptimizationRemarkMissed(
Adam Nemetcef33142016-08-26 20:21:05 +0000174 const char *PassName, Loop *L, const Twine &Msg, bool IsVerbose) {
175 emitOptimizationRemarkMissed(PassName, L->getStartLoc(), L->getHeader(), Msg,
176 IsVerbose);
Adam Nemetaad81602016-07-15 17:23:20 +0000177}
178
Adam Nemet5b3a5cf2016-07-20 21:44:26 +0000179void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysis(
180 const char *PassName, const DebugLoc &DLoc, const Value *V,
Adam Nemetcef33142016-08-26 20:21:05 +0000181 const Twine &Msg, bool IsVerbose) {
Adam Nemet5b3a5cf2016-07-20 21:44:26 +0000182 LLVMContext &Ctx = F->getContext();
Adam Nemetcef33142016-08-26 20:21:05 +0000183 if (!IsVerbose || shouldEmitVerbose())
Adam Nemet04758ba2016-09-27 22:19:23 +0000184 Ctx.diagnose(
185 OptimizationRemarkAnalysis(PassName, *F, DLoc, Msg, computeHotness(V)));
Adam Nemet5b3a5cf2016-07-20 21:44:26 +0000186}
187
188void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysis(
Adam Nemetcef33142016-08-26 20:21:05 +0000189 const char *PassName, Loop *L, const Twine &Msg, bool IsVerbose) {
Adam Nemet5b3a5cf2016-07-20 21:44:26 +0000190 emitOptimizationRemarkAnalysis(PassName, L->getStartLoc(), L->getHeader(),
Adam Nemetcef33142016-08-26 20:21:05 +0000191 Msg, IsVerbose);
Adam Nemet5b3a5cf2016-07-20 21:44:26 +0000192}
193
Adam Nemet0e0e2d52016-07-20 23:50:32 +0000194void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysisFPCommute(
Adam Nemetcbe2a9b2016-07-21 01:11:12 +0000195 const char *PassName, const DebugLoc &DLoc, const Value *V,
196 const Twine &Msg) {
Adam Nemet0e0e2d52016-07-20 23:50:32 +0000197 LLVMContext &Ctx = F->getContext();
Adam Nemet04758ba2016-09-27 22:19:23 +0000198 Ctx.diagnose(OptimizationRemarkAnalysisFPCommute(PassName, *F, DLoc, Msg,
199 computeHotness(V)));
Adam Nemet0e0e2d52016-07-20 23:50:32 +0000200}
201
202void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysisAliasing(
Adam Nemetcbe2a9b2016-07-21 01:11:12 +0000203 const char *PassName, const DebugLoc &DLoc, const Value *V,
204 const Twine &Msg) {
Adam Nemet0e0e2d52016-07-20 23:50:32 +0000205 LLVMContext &Ctx = F->getContext();
Adam Nemet04758ba2016-09-27 22:19:23 +0000206 Ctx.diagnose(OptimizationRemarkAnalysisAliasing(PassName, *F, DLoc, Msg,
207 computeHotness(V)));
Adam Nemet0e0e2d52016-07-20 23:50:32 +0000208}
209
210void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysisAliasing(
211 const char *PassName, Loop *L, const Twine &Msg) {
212 emitOptimizationRemarkAnalysisAliasing(PassName, L->getStartLoc(),
213 L->getHeader(), Msg);
214}
215
Adam Nemet79ac42a2016-07-18 16:29:21 +0000216OptimizationRemarkEmitterWrapperPass::OptimizationRemarkEmitterWrapperPass()
217 : FunctionPass(ID) {
218 initializeOptimizationRemarkEmitterWrapperPassPass(
219 *PassRegistry::getPassRegistry());
220}
221
222bool OptimizationRemarkEmitterWrapperPass::runOnFunction(Function &Fn) {
223 BlockFrequencyInfo *BFI;
Adam Nemetaad81602016-07-15 17:23:20 +0000224
225 if (Fn.getContext().getDiagnosticHotnessRequested())
226 BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI();
227 else
228 BFI = nullptr;
229
Adam Nemet79ac42a2016-07-18 16:29:21 +0000230 ORE = llvm::make_unique<OptimizationRemarkEmitter>(&Fn, BFI);
Adam Nemetaad81602016-07-15 17:23:20 +0000231 return false;
232}
233
Adam Nemet79ac42a2016-07-18 16:29:21 +0000234void OptimizationRemarkEmitterWrapperPass::getAnalysisUsage(
235 AnalysisUsage &AU) const {
Adam Nemetaad81602016-07-15 17:23:20 +0000236 LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU);
237 AU.setPreservesAll();
238}
239
Chandler Carruthdab4eae2016-11-23 17:53:26 +0000240AnalysisKey OptimizationRemarkEmitterAnalysis::Key;
Adam Nemet79ac42a2016-07-18 16:29:21 +0000241
242OptimizationRemarkEmitter
Adam Nemet78d10912016-07-20 21:44:18 +0000243OptimizationRemarkEmitterAnalysis::run(Function &F,
Sean Silva36e0d012016-08-09 00:28:15 +0000244 FunctionAnalysisManager &AM) {
Adam Nemet79ac42a2016-07-18 16:29:21 +0000245 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
255char OptimizationRemarkEmitterWrapperPass::ID = 0;
Adam Nemetaad81602016-07-15 17:23:20 +0000256static const char ore_name[] = "Optimization Remark Emitter";
257#define ORE_NAME "opt-remark-emitter"
258
Adam Nemet79ac42a2016-07-18 16:29:21 +0000259INITIALIZE_PASS_BEGIN(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
260 false, true)
Adam Nemetaad81602016-07-15 17:23:20 +0000261INITIALIZE_PASS_DEPENDENCY(LazyBFIPass)
Adam Nemet79ac42a2016-07-18 16:29:21 +0000262INITIALIZE_PASS_END(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
263 false, true)