1 //===- OptimizationDiagnosticInfo.cpp - Optimization Diagnostic -*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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 //===----------------------------------------------------------------------===//
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"
26 OptimizationRemarkEmitter::OptimizationRemarkEmitter(Function *F)
27 : F(F), BFI(nullptr) {
28 if (!F->getContext().getDiagnosticHotnessRequested())
31 // First create a dominator tree.
35 // Generate LoopInfo from it.
39 // Then compute BranchProbabilityInfo.
40 BranchProbabilityInfo BPI;
41 BPI.calculate(*F, LI);
43 // Finally compute BFI.
44 OwnedBFI = llvm::make_unique<BlockFrequencyInfo>(*F, BPI, LI);
48 Optional<uint64_t> OptimizationRemarkEmitter::computeHotness(const Value *V) {
52 return BFI->getBlockProfileCount(cast<BasicBlock>(V));
58 template <> struct MappingTraits<DiagnosticInfoOptimizationBase *> {
59 static void mapping(IO &io, DiagnosticInfoOptimizationBase *&OptDiag) {
60 assert(io.outputting() && "input not yet implemented");
62 if (io.mapTag("!Passed", OptDiag->getKind() == DK_OptimizationRemark))
64 else if (io.mapTag("!Missed",
65 OptDiag->getKind() == DK_OptimizationRemarkMissed))
67 else if (io.mapTag("!Analysis",
68 OptDiag->getKind() == DK_OptimizationRemarkAnalysis))
70 else if (io.mapTag("!AnalysisFPCommute",
72 DK_OptimizationRemarkAnalysisFPCommute))
74 else if (io.mapTag("!AnalysisAliasing",
76 DK_OptimizationRemarkAnalysisAliasing))
79 llvm_unreachable("todo");
81 // These are read-only for now.
82 DebugLoc DL = OptDiag->getDebugLoc();
83 StringRef FN = GlobalValue::getRealLinkageName(
84 OptDiag->getFunction().getName());
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);
97 template <> struct MappingTraits<DebugLoc> {
98 static void mapping(IO &io, DebugLoc &DL) {
99 assert(io.outputting() && "input not yet implemented");
101 auto *Scope = cast<DIScope>(DL.getScope());
102 StringRef File = Scope->getFilename();
103 unsigned Line = DL.getLine();
104 unsigned Col = DL.getCol();
106 io.mapRequired("File", File);
107 io.mapRequired("Line", Line);
108 io.mapRequired("Column", Col);
111 static const bool flow = true;
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);
120 io.mapOptional("DebugLoc", A.DLoc);
124 } // end namespace yaml
125 } // end namespace llvm
127 LLVM_YAML_IS_SEQUENCE_VECTOR(DiagnosticInfoOptimizationBase::Argument)
129 void OptimizationRemarkEmitter::computeHotness(
130 DiagnosticInfoOptimizationBase &OptDiag) {
131 Value *V = OptDiag.getCodeRegion();
133 OptDiag.setHotness(computeHotness(V));
136 void OptimizationRemarkEmitter::emit(DiagnosticInfoOptimizationBase &OptDiag) {
137 computeHotness(OptDiag);
139 yaml::Output *Out = F->getContext().getDiagnosticsOutputFile();
141 auto *P = &const_cast<DiagnosticInfoOptimizationBase &>(OptDiag);
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);
150 void OptimizationRemarkEmitter::emitOptimizationRemark(const char *PassName,
151 const DebugLoc &DLoc,
154 LLVMContext &Ctx = F->getContext();
155 Ctx.diagnose(OptimizationRemark(PassName, *F, DLoc, Msg, computeHotness(V)));
158 void OptimizationRemarkEmitter::emitOptimizationRemark(const char *PassName,
161 emitOptimizationRemark(PassName, L->getStartLoc(), L->getHeader(), Msg);
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())
170 OptimizationRemarkMissed(PassName, *F, DLoc, Msg, computeHotness(V)));
173 void OptimizationRemarkEmitter::emitOptimizationRemarkMissed(
174 const char *PassName, Loop *L, const Twine &Msg, bool IsVerbose) {
175 emitOptimizationRemarkMissed(PassName, L->getStartLoc(), L->getHeader(), Msg,
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())
185 OptimizationRemarkAnalysis(PassName, *F, DLoc, Msg, computeHotness(V)));
188 void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysis(
189 const char *PassName, Loop *L, const Twine &Msg, bool IsVerbose) {
190 emitOptimizationRemarkAnalysis(PassName, L->getStartLoc(), L->getHeader(),
194 void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysisFPCommute(
195 const char *PassName, const DebugLoc &DLoc, const Value *V,
197 LLVMContext &Ctx = F->getContext();
198 Ctx.diagnose(OptimizationRemarkAnalysisFPCommute(PassName, *F, DLoc, Msg,
202 void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysisAliasing(
203 const char *PassName, const DebugLoc &DLoc, const Value *V,
205 LLVMContext &Ctx = F->getContext();
206 Ctx.diagnose(OptimizationRemarkAnalysisAliasing(PassName, *F, DLoc, Msg,
210 void OptimizationRemarkEmitter::emitOptimizationRemarkAnalysisAliasing(
211 const char *PassName, Loop *L, const Twine &Msg) {
212 emitOptimizationRemarkAnalysisAliasing(PassName, L->getStartLoc(),
213 L->getHeader(), Msg);
216 OptimizationRemarkEmitterWrapperPass::OptimizationRemarkEmitterWrapperPass()
218 initializeOptimizationRemarkEmitterWrapperPassPass(
219 *PassRegistry::getPassRegistry());
222 bool OptimizationRemarkEmitterWrapperPass::runOnFunction(Function &Fn) {
223 BlockFrequencyInfo *BFI;
225 if (Fn.getContext().getDiagnosticHotnessRequested())
226 BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI();
230 ORE = llvm::make_unique<OptimizationRemarkEmitter>(&Fn, BFI);
234 void OptimizationRemarkEmitterWrapperPass::getAnalysisUsage(
235 AnalysisUsage &AU) const {
236 LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU);
237 AU.setPreservesAll();
240 AnalysisKey OptimizationRemarkEmitterAnalysis::Key;
242 OptimizationRemarkEmitter
243 OptimizationRemarkEmitterAnalysis::run(Function &F,
244 FunctionAnalysisManager &AM) {
245 BlockFrequencyInfo *BFI;
247 if (F.getContext().getDiagnosticHotnessRequested())
248 BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
252 return OptimizationRemarkEmitter(&F, BFI);
255 char OptimizationRemarkEmitterWrapperPass::ID = 0;
256 static const char ore_name[] = "Optimization Remark Emitter";
257 #define ORE_NAME "opt-remark-emitter"
259 INITIALIZE_PASS_BEGIN(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
261 INITIALIZE_PASS_DEPENDENCY(LazyBFIPass)
262 INITIALIZE_PASS_END(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,