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