blob: 914ec7829fdc74b4f56ebf7b501c6a557f0ebc76 [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
Justin Bogner8281c812017-02-22 07:38:17 +000026OptimizationRemarkEmitter::OptimizationRemarkEmitter(const Function *F)
Adam Nemet896c09b2016-08-10 00:44:44 +000027 : F(F), BFI(nullptr) {
Brian Gesiak44e5f6c2017-06-30 18:13:59 +000028 if (!F->getContext().getDiagnosticsHotnessRequested())
Adam Nemet896c09b2016-08-10 00:44:44 +000029 return;
30
31 // First create a dominator tree.
32 DominatorTree DT;
Justin Bogner8281c812017-02-22 07:38:17 +000033 DT.recalculate(*const_cast<Function *>(F));
Adam Nemet896c09b2016-08-10 00:44:44 +000034
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 ;
Adam Nemet0bf1b862017-02-02 05:41:51 +000096 else if (io.mapTag("!Failure", OptDiag->getKind() == DK_OptimizationFailure))
97 ;
Adam Nemeta9640662017-01-25 23:20:33 +000098 else
Adam Nemet0bf1b862017-02-02 05:41:51 +000099 llvm_unreachable("Unknown remark type");
Adam Nemeta62b7e12016-09-27 20:55:07 +0000100
Adam Nemeta9640662017-01-25 23:20:33 +0000101 // These are read-only for now.
Justin Bognerd890f952017-02-18 00:42:23 +0000102 DiagnosticLocation DL = OptDiag->getLocation();
Adam Nemeta9640662017-01-25 23:20:33 +0000103 StringRef FN =
Peter Collingbourne6f0ecca2017-05-16 00:39:01 +0000104 GlobalValue::dropLLVMManglingEscape(OptDiag->getFunction().getName());
Adam Nemeta62b7e12016-09-27 20:55:07 +0000105
Adam Nemeta9640662017-01-25 23:20:33 +0000106 StringRef PassName(OptDiag->PassName);
107 io.mapRequired("Pass", PassName);
108 io.mapRequired("Name", OptDiag->RemarkName);
Justin Bognerd890f952017-02-18 00:42:23 +0000109 if (!io.outputting() || DL.isValid())
Adam Nemeta9640662017-01-25 23:20:33 +0000110 io.mapOptional("DebugLoc", DL);
111 io.mapRequired("Function", FN);
112 io.mapOptional("Hotness", OptDiag->Hotness);
113 io.mapOptional("Args", OptDiag->Args);
114}
Adam Nemeta62b7e12016-09-27 20:55:07 +0000115
Justin Bognerd890f952017-02-18 00:42:23 +0000116template <> struct MappingTraits<DiagnosticLocation> {
117 static void mapping(IO &io, DiagnosticLocation &DL) {
Adam Nemeta62b7e12016-09-27 20:55:07 +0000118 assert(io.outputting() && "input not yet implemented");
119
Justin Bognerd890f952017-02-18 00:42:23 +0000120 StringRef File = DL.getFilename();
Adam Nemeta62b7e12016-09-27 20:55:07 +0000121 unsigned Line = DL.getLine();
Justin Bognerd890f952017-02-18 00:42:23 +0000122 unsigned Col = DL.getColumn();
Adam Nemeta62b7e12016-09-27 20:55:07 +0000123
124 io.mapRequired("File", File);
125 io.mapRequired("Line", Line);
126 io.mapRequired("Column", Col);
127 }
128
129 static const bool flow = true;
130};
131
Adam Nemet0428e932016-10-04 17:05:04 +0000132// Implement this as a mapping for now to get proper quotation for the value.
133template <> struct MappingTraits<DiagnosticInfoOptimizationBase::Argument> {
134 static void mapping(IO &io, DiagnosticInfoOptimizationBase::Argument &A) {
135 assert(io.outputting() && "input not yet implemented");
136 io.mapRequired(A.Key.data(), A.Val);
Justin Bognerd890f952017-02-18 00:42:23 +0000137 if (A.Loc.isValid())
138 io.mapOptional("DebugLoc", A.Loc);
Adam Nemeta62b7e12016-09-27 20:55:07 +0000139 }
Adam Nemeta62b7e12016-09-27 20:55:07 +0000140};
141
142} // end namespace yaml
143} // end namespace llvm
144
145LLVM_YAML_IS_SEQUENCE_VECTOR(DiagnosticInfoOptimizationBase::Argument)
146
147void OptimizationRemarkEmitter::computeHotness(
Adam Nemet484f93d2017-01-25 23:20:25 +0000148 DiagnosticInfoIROptimization &OptDiag) {
Justin Bogner8281c812017-02-22 07:38:17 +0000149 const Value *V = OptDiag.getCodeRegion();
Adam Nemeta62b7e12016-09-27 20:55:07 +0000150 if (V)
151 OptDiag.setHotness(computeHotness(V));
152}
153
Adam Nemet484f93d2017-01-25 23:20:25 +0000154void OptimizationRemarkEmitter::emit(
155 DiagnosticInfoOptimizationBase &OptDiagBase) {
156 auto &OptDiag = cast<DiagnosticInfoIROptimization>(OptDiagBase);
Adam Nemeta62b7e12016-09-27 20:55:07 +0000157 computeHotness(OptDiag);
Brian Gesiak4ef3daa2017-06-30 23:14:53 +0000158 // If a diagnostic has a hotness value, then only emit it if its hotness
159 // meets the threshold.
160 if (OptDiag.getHotness() &&
161 *OptDiag.getHotness() <
162 F->getContext().getDiagnosticsHotnessThreshold()) {
163 return;
164 }
Adam Nemeta62b7e12016-09-27 20:55:07 +0000165
166 yaml::Output *Out = F->getContext().getDiagnosticsOutputFile();
Hal Finkelbdd67352016-10-04 18:13:45 +0000167 if (Out) {
Adam Nemet4846e662017-08-28 23:00:13 +0000168 // For remarks the << operator takes a reference to a pointer.
169 auto *P = &OptDiagBase;
Adam Nemeta62b7e12016-09-27 20:55:07 +0000170 *Out << P;
171 }
Adam Nemetf31b1f32017-10-04 04:26:23 +0000172 F->getContext().diagnose(OptDiag);
Adam Nemeta62b7e12016-09-27 20:55:07 +0000173}
174
Adam Nemet79ac42a2016-07-18 16:29:21 +0000175OptimizationRemarkEmitterWrapperPass::OptimizationRemarkEmitterWrapperPass()
176 : FunctionPass(ID) {
177 initializeOptimizationRemarkEmitterWrapperPassPass(
178 *PassRegistry::getPassRegistry());
179}
180
181bool OptimizationRemarkEmitterWrapperPass::runOnFunction(Function &Fn) {
182 BlockFrequencyInfo *BFI;
Adam Nemetaad81602016-07-15 17:23:20 +0000183
Brian Gesiak44e5f6c2017-06-30 18:13:59 +0000184 if (Fn.getContext().getDiagnosticsHotnessRequested())
Adam Nemetaad81602016-07-15 17:23:20 +0000185 BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI();
186 else
187 BFI = nullptr;
188
Adam Nemet79ac42a2016-07-18 16:29:21 +0000189 ORE = llvm::make_unique<OptimizationRemarkEmitter>(&Fn, BFI);
Adam Nemetaad81602016-07-15 17:23:20 +0000190 return false;
191}
192
Adam Nemet79ac42a2016-07-18 16:29:21 +0000193void OptimizationRemarkEmitterWrapperPass::getAnalysisUsage(
194 AnalysisUsage &AU) const {
Adam Nemetaad81602016-07-15 17:23:20 +0000195 LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU);
196 AU.setPreservesAll();
197}
198
Chandler Carruthdab4eae2016-11-23 17:53:26 +0000199AnalysisKey OptimizationRemarkEmitterAnalysis::Key;
Adam Nemet79ac42a2016-07-18 16:29:21 +0000200
201OptimizationRemarkEmitter
Adam Nemet78d10912016-07-20 21:44:18 +0000202OptimizationRemarkEmitterAnalysis::run(Function &F,
Sean Silva36e0d012016-08-09 00:28:15 +0000203 FunctionAnalysisManager &AM) {
Adam Nemet79ac42a2016-07-18 16:29:21 +0000204 BlockFrequencyInfo *BFI;
205
Brian Gesiak44e5f6c2017-06-30 18:13:59 +0000206 if (F.getContext().getDiagnosticsHotnessRequested())
Adam Nemet79ac42a2016-07-18 16:29:21 +0000207 BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
208 else
209 BFI = nullptr;
210
211 return OptimizationRemarkEmitter(&F, BFI);
212}
213
214char OptimizationRemarkEmitterWrapperPass::ID = 0;
Adam Nemetaad81602016-07-15 17:23:20 +0000215static const char ore_name[] = "Optimization Remark Emitter";
216#define ORE_NAME "opt-remark-emitter"
217
Adam Nemet79ac42a2016-07-18 16:29:21 +0000218INITIALIZE_PASS_BEGIN(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
219 false, true)
Adam Nemetaad81602016-07-15 17:23:20 +0000220INITIALIZE_PASS_DEPENDENCY(LazyBFIPass)
Adam Nemet79ac42a2016-07-18 16:29:21 +0000221INITIALIZE_PASS_END(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
222 false, true)