Line data Source code
1 : //===- 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"
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"
23 :
24 : using namespace llvm;
25 :
26 1084419 : OptimizationRemarkEmitter::OptimizationRemarkEmitter(const Function *F)
27 2168838 : : F(F), BFI(nullptr) {
28 1084419 : if (!F->getContext().getDiagnosticsHotnessRequested())
29 1084296 : return;
30 :
31 : // First create a dominator tree.
32 246 : DominatorTree DT;
33 123 : DT.recalculate(*const_cast<Function *>(F));
34 :
35 : // Generate LoopInfo from it.
36 246 : LoopInfo LI;
37 123 : LI.analyze(DT);
38 :
39 : // Then compute BranchProbabilityInfo.
40 246 : BranchProbabilityInfo BPI;
41 123 : BPI.calculate(*F, LI);
42 :
43 : // Finally compute BFI.
44 123 : OwnedBFI = llvm::make_unique<BlockFrequencyInfo>(*F, BPI, LI);
45 246 : BFI = OwnedBFI.get();
46 : }
47 :
48 1142 : bool 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 1160 : if (BFI && Inv.invalidate<BlockFrequencyAnalysis>(F, PA))
54 : return true;
55 :
56 : // Otherwise this analysis result remains valid.
57 : return false;
58 : }
59 :
60 746466 : Optional<uint64_t> OptimizationRemarkEmitter::computeHotness(const Value *V) {
61 746466 : if (!BFI)
62 : return None;
63 :
64 174 : return BFI->getBlockProfileCount(cast<BasicBlock>(V));
65 : }
66 :
67 : namespace llvm {
68 : namespace yaml {
69 :
70 223 : void MappingTraits<DiagnosticInfoOptimizationBase *>::mapping(
71 : IO &io, DiagnosticInfoOptimizationBase *&OptDiag) {
72 : assert(io.outputting() && "input not yet implemented");
73 :
74 446 : if (io.mapTag("!Passed",
75 383 : (OptDiag->getKind() == DK_OptimizationRemark ||
76 383 : OptDiag->getKind() == DK_MachineOptimizationRemark)))
77 : ;
78 320 : else if (io.mapTag(
79 : "!Missed",
80 273 : (OptDiag->getKind() == DK_OptimizationRemarkMissed ||
81 273 : OptDiag->getKind() == DK_MachineOptimizationRemarkMissed)))
82 : ;
83 214 : else if (io.mapTag(
84 : "!Analysis",
85 184 : (OptDiag->getKind() == DK_OptimizationRemarkAnalysis ||
86 184 : OptDiag->getKind() == DK_MachineOptimizationRemarkAnalysis)))
87 : ;
88 6 : else if (io.mapTag("!AnalysisFPCommute",
89 3 : OptDiag->getKind() ==
90 3 : DK_OptimizationRemarkAnalysisFPCommute))
91 : ;
92 6 : else if (io.mapTag("!AnalysisAliasing",
93 3 : OptDiag->getKind() ==
94 3 : DK_OptimizationRemarkAnalysisAliasing))
95 : ;
96 4 : else if (io.mapTag("!Failure", OptDiag->getKind() == DK_OptimizationFailure))
97 : ;
98 : else
99 0 : llvm_unreachable("Unknown remark type");
100 :
101 : // These are read-only for now.
102 446 : DiagnosticLocation DL = OptDiag->getLocation();
103 : StringRef FN =
104 223 : GlobalValue::dropLLVMManglingEscape(OptDiag->getFunction().getName());
105 :
106 446 : StringRef PassName(OptDiag->PassName);
107 223 : io.mapRequired("Pass", PassName);
108 446 : io.mapRequired("Name", OptDiag->RemarkName);
109 446 : if (!io.outputting() || DL.isValid())
110 : io.mapOptional("DebugLoc", DL);
111 223 : io.mapRequired("Function", FN);
112 446 : io.mapOptional("Hotness", OptDiag->Hotness);
113 446 : io.mapOptional("Args", OptDiag->Args);
114 223 : }
115 :
116 : template <> struct MappingTraits<DiagnosticLocation> {
117 117 : static void mapping(IO &io, DiagnosticLocation &DL) {
118 : assert(io.outputting() && "input not yet implemented");
119 :
120 117 : StringRef File = DL.getFilename();
121 117 : unsigned Line = DL.getLine();
122 117 : unsigned Col = DL.getColumn();
123 :
124 117 : io.mapRequired("File", File);
125 117 : io.mapRequired("Line", Line);
126 117 : io.mapRequired("Column", Col);
127 117 : }
128 :
129 : static const bool flow = true;
130 : };
131 :
132 : // Implement this as a mapping for now to get proper quotation for the value.
133 : template <> struct MappingTraits<DiagnosticInfoOptimizationBase::Argument> {
134 706 : static void mapping(IO &io, DiagnosticInfoOptimizationBase::Argument &A) {
135 : assert(io.outputting() && "input not yet implemented");
136 2118 : io.mapRequired(A.Key.data(), A.Val);
137 1412 : if (A.Loc.isValid())
138 25 : io.mapOptional("DebugLoc", A.Loc);
139 706 : }
140 : };
141 :
142 : } // end namespace yaml
143 : } // end namespace llvm
144 :
145 : LLVM_YAML_IS_SEQUENCE_VECTOR(DiagnosticInfoOptimizationBase::Argument)
146 :
147 746466 : void OptimizationRemarkEmitter::computeHotness(
148 : DiagnosticInfoIROptimization &OptDiag) {
149 746466 : const Value *V = OptDiag.getCodeRegion();
150 746466 : if (V)
151 2239398 : OptDiag.setHotness(computeHotness(V));
152 746466 : }
153 :
154 746466 : void OptimizationRemarkEmitter::emit(
155 : DiagnosticInfoOptimizationBase &OptDiagBase) {
156 746466 : auto &OptDiag = cast<DiagnosticInfoIROptimization>(OptDiagBase);
157 746466 : computeHotness(OptDiag);
158 : // If a diagnostic has a hotness value, then only emit it if its hotness
159 : // meets the threshold.
160 2985988 : if (OptDiag.getHotness() &&
161 746646 : *OptDiag.getHotness() <
162 746528 : F->getContext().getDiagnosticsHotnessThreshold()) {
163 : return;
164 : }
165 :
166 746460 : yaml::Output *Out = F->getContext().getDiagnosticsOutputFile();
167 746460 : if (Out) {
168 : // For remarks the << operator takes a reference to a pointer.
169 143 : auto *P = &OptDiagBase;
170 143 : *Out << P;
171 : }
172 : // FIXME: now that IsVerbose is part of DI, filtering for this will be moved
173 : // from here to clang.
174 746460 : if (!OptDiag.isVerbose() || shouldEmitVerbose())
175 651116 : F->getContext().diagnose(OptDiag);
176 : }
177 :
178 20245 : OptimizationRemarkEmitterWrapperPass::OptimizationRemarkEmitterWrapperPass()
179 60735 : : FunctionPass(ID) {
180 20245 : initializeOptimizationRemarkEmitterWrapperPassPass(
181 20245 : *PassRegistry::getPassRegistry());
182 20245 : }
183 :
184 374810 : bool OptimizationRemarkEmitterWrapperPass::runOnFunction(Function &Fn) {
185 : BlockFrequencyInfo *BFI;
186 :
187 374810 : if (Fn.getContext().getDiagnosticsHotnessRequested())
188 276 : BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI();
189 : else
190 : BFI = nullptr;
191 :
192 749620 : ORE = llvm::make_unique<OptimizationRemarkEmitter>(&Fn, BFI);
193 374810 : return false;
194 : }
195 :
196 20248 : void OptimizationRemarkEmitterWrapperPass::getAnalysisUsage(
197 : AnalysisUsage &AU) const {
198 20248 : LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU);
199 20248 : AU.setPreservesAll();
200 20248 : }
201 :
202 : AnalysisKey OptimizationRemarkEmitterAnalysis::Key;
203 :
204 : OptimizationRemarkEmitter
205 928 : OptimizationRemarkEmitterAnalysis::run(Function &F,
206 : FunctionAnalysisManager &AM) {
207 : BlockFrequencyInfo *BFI;
208 :
209 928 : if (F.getContext().getDiagnosticsHotnessRequested())
210 18 : BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
211 : else
212 : BFI = nullptr;
213 :
214 928 : return OptimizationRemarkEmitter(&F, BFI);
215 : }
216 :
217 : char OptimizationRemarkEmitterWrapperPass::ID = 0;
218 : static const char ore_name[] = "Optimization Remark Emitter";
219 : #define ORE_NAME "opt-remark-emitter"
220 :
221 41843 : INITIALIZE_PASS_BEGIN(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
222 : false, true)
223 41843 : INITIALIZE_PASS_DEPENDENCY(LazyBFIPass)
224 931171 : INITIALIZE_PASS_END(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
225 : false, true)
|