/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/include/llvm/Analysis/OptimizationDiagnosticInfo.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===- OptimizationDiagnosticInfo.h - 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 | | #ifndef LLVM_IR_OPTIMIZATIONDIAGNOSTICINFO_H |
16 | | #define LLVM_IR_OPTIMIZATIONDIAGNOSTICINFO_H |
17 | | |
18 | | #include "llvm/ADT/Optional.h" |
19 | | #include "llvm/Analysis/BlockFrequencyInfo.h" |
20 | | #include "llvm/IR/DiagnosticInfo.h" |
21 | | #include "llvm/IR/Function.h" |
22 | | #include "llvm/IR/PassManager.h" |
23 | | #include "llvm/Pass.h" |
24 | | |
25 | | namespace llvm { |
26 | | class DebugLoc; |
27 | | class Loop; |
28 | | class Pass; |
29 | | class Twine; |
30 | | class Value; |
31 | | |
32 | | /// The optimization diagnostic interface. |
33 | | /// |
34 | | /// It allows reporting when optimizations are performed and when they are not |
35 | | /// along with the reasons for it. Hotness information of the corresponding |
36 | | /// code region can be included in the remark if DiagnosticsHotnessRequested is |
37 | | /// enabled in the LLVM context. |
38 | | class OptimizationRemarkEmitter { |
39 | | public: |
40 | | OptimizationRemarkEmitter(const Function *F, BlockFrequencyInfo *BFI) |
41 | 7.83M | : F(F), BFI(BFI) {} |
42 | | |
43 | | /// \brief This variant can be used to generate ORE on demand (without the |
44 | | /// analysis pass). |
45 | | /// |
46 | | /// Note that this ctor has a very different cost depending on whether |
47 | | /// F->getContext().getDiagnosticsHotnessRequested() is on or not. If it's off |
48 | | /// the operation is free. |
49 | | /// |
50 | | /// Whereas if DiagnosticsHotnessRequested is on, it is fairly expensive |
51 | | /// operation since BFI and all its required analyses are computed. This is |
52 | | /// for example useful for CGSCC passes that can't use function analyses |
53 | | /// passes in the old PM. |
54 | | OptimizationRemarkEmitter(const Function *F); |
55 | | |
56 | | OptimizationRemarkEmitter(OptimizationRemarkEmitter &&Arg) |
57 | 1.85k | : F(Arg.F), BFI(Arg.BFI) {} |
58 | | |
59 | 0 | OptimizationRemarkEmitter &operator=(OptimizationRemarkEmitter &&RHS) { |
60 | 0 | F = RHS.F; |
61 | 0 | BFI = RHS.BFI; |
62 | 0 | return *this; |
63 | 0 | } |
64 | | |
65 | | /// Handle invalidation events in the new pass manager. |
66 | | bool invalidate(Function &F, const PreservedAnalyses &PA, |
67 | | FunctionAnalysisManager::Invalidator &Inv); |
68 | | |
69 | | /// \brief Output the remark via the diagnostic handler and to the |
70 | | /// optimization record file. |
71 | | void emit(DiagnosticInfoOptimizationBase &OptDiag); |
72 | | |
73 | | /// \brief Take a lambda that returns a remark which will be emitted. Second |
74 | | /// argument is only used to restrict this to functions. |
75 | | template <typename T> |
76 | 1.81M | void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) { |
77 | 1.81M | // Avoid building the remark unless we know there are at least *some* |
78 | 1.81M | // remarks enabled. We can't currently check whether remarks are requested |
79 | 1.81M | // for the calling pass since that requires actually building the remark. |
80 | 1.81M | |
81 | 1.81M | if (F->getContext().getDiagnosticsOutputFile() || |
82 | 1.81M | F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()1.81M ) { |
83 | 57 | auto R = RemarkBuilder(); |
84 | 57 | emit((DiagnosticInfoOptimizationBase &)R); |
85 | 57 | } |
86 | 1.81M | } Inliner.cpp:void llvm::OptimizationRemarkEmitter::emit<inlineCallsImpl(llvm::CallGraphSCC&, llvm::CallGraph&, std::__1::function<llvm::AssumptionCache& (llvm::Function&)>, llvm::ProfileSummaryInfo*, llvm::TargetLibraryInfo&, bool, llvm::function_ref<llvm::InlineCost (llvm::CallSite)>, llvm::function_ref<llvm::AAResults& (llvm::Function&)>, llvm::ImportedFunctionsInliningStatistics&)::$_9>(inlineCallsImpl(llvm::CallGraphSCC&, llvm::CallGraph&, std::__1::function<llvm::AssumptionCache& (llvm::Function&)>, llvm::ProfileSummaryInfo*, llvm::TargetLibraryInfo&, bool, llvm::function_ref<llvm::InlineCost (llvm::CallSite)>, llvm::function_ref<llvm::AAResults& (llvm::Function&)>, llvm::ImportedFunctionsInliningStatistics&)::$_9, decltype(fp())*) Line | Count | Source | 76 | 191k | void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) { | 77 | 191k | // Avoid building the remark unless we know there are at least *some* | 78 | 191k | // remarks enabled. We can't currently check whether remarks are requested | 79 | 191k | // for the calling pass since that requires actually building the remark. | 80 | 191k | | 81 | 191k | if (F->getContext().getDiagnosticsOutputFile() || | 82 | 191k | F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()191k ) { | 83 | 18 | auto R = RemarkBuilder(); | 84 | 18 | emit((DiagnosticInfoOptimizationBase &)R); | 85 | 18 | } | 86 | 191k | } |
Inliner.cpp:void llvm::OptimizationRemarkEmitter::emit<shouldInline(llvm::CallSite, llvm::function_ref<llvm::InlineCost (llvm::CallSite)>, llvm::OptimizationRemarkEmitter&)::$_7>(shouldInline(llvm::CallSite, llvm::function_ref<llvm::InlineCost (llvm::CallSite)>, llvm::OptimizationRemarkEmitter&)::$_7, decltype(fp())*) Line | Count | Source | 76 | 1.52M | void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) { | 77 | 1.52M | // Avoid building the remark unless we know there are at least *some* | 78 | 1.52M | // remarks enabled. We can't currently check whether remarks are requested | 79 | 1.52M | // for the calling pass since that requires actually building the remark. | 80 | 1.52M | | 81 | 1.52M | if (F->getContext().getDiagnosticsOutputFile() || | 82 | 1.52M | F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()1.52M ) { | 83 | 30 | auto R = RemarkBuilder(); | 84 | 30 | emit((DiagnosticInfoOptimizationBase &)R); | 85 | 30 | } | 86 | 1.52M | } |
Inliner.cpp:void llvm::OptimizationRemarkEmitter::emit<shouldInline(llvm::CallSite, llvm::function_ref<llvm::InlineCost (llvm::CallSite)>, llvm::OptimizationRemarkEmitter&)::$_8>(shouldInline(llvm::CallSite, llvm::function_ref<llvm::InlineCost (llvm::CallSite)>, llvm::OptimizationRemarkEmitter&)::$_8, decltype(fp())*) Line | Count | Source | 76 | 83.3k | void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) { | 77 | 83.3k | // Avoid building the remark unless we know there are at least *some* | 78 | 83.3k | // remarks enabled. We can't currently check whether remarks are requested | 79 | 83.3k | // for the calling pass since that requires actually building the remark. | 80 | 83.3k | | 81 | 83.3k | if (F->getContext().getDiagnosticsOutputFile() || | 82 | 83.3k | F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()83.3k ) { | 83 | 0 | auto R = RemarkBuilder(); | 84 | 0 | emit((DiagnosticInfoOptimizationBase &)R); | 85 | 0 | } | 86 | 83.3k | } |
LoopUnroll.cpp:void llvm::OptimizationRemarkEmitter::emit<llvm::UnrollLoop(llvm::Loop*, unsigned int, unsigned int, bool, bool, bool, bool, bool, unsigned int, unsigned int, bool, llvm::LoopInfo*, llvm::ScalarEvolution*, llvm::DominatorTree*, llvm::AssumptionCache*, llvm::OptimizationRemarkEmitter*, bool)::$_2>(llvm::UnrollLoop(llvm::Loop*, unsigned int, unsigned int, bool, bool, bool, bool, bool, unsigned int, unsigned int, bool, llvm::LoopInfo*, llvm::ScalarEvolution*, llvm::DominatorTree*, llvm::AssumptionCache*, llvm::OptimizationRemarkEmitter*, bool)::$_2, decltype(fp())*) Line | Count | Source | 76 | 95 | void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) { | 77 | 95 | // Avoid building the remark unless we know there are at least *some* | 78 | 95 | // remarks enabled. We can't currently check whether remarks are requested | 79 | 95 | // for the calling pass since that requires actually building the remark. | 80 | 95 | | 81 | 95 | if (F->getContext().getDiagnosticsOutputFile() || | 82 | 95 | F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()95 ) { | 83 | 2 | auto R = RemarkBuilder(); | 84 | 2 | emit((DiagnosticInfoOptimizationBase &)R); | 85 | 2 | } | 86 | 95 | } |
LoopUnroll.cpp:void llvm::OptimizationRemarkEmitter::emit<llvm::UnrollLoop(llvm::Loop*, unsigned int, unsigned int, bool, bool, bool, bool, bool, unsigned int, unsigned int, bool, llvm::LoopInfo*, llvm::ScalarEvolution*, llvm::DominatorTree*, llvm::AssumptionCache*, llvm::OptimizationRemarkEmitter*, bool)::$_3>(llvm::UnrollLoop(llvm::Loop*, unsigned int, unsigned int, bool, bool, bool, bool, bool, unsigned int, unsigned int, bool, llvm::LoopInfo*, llvm::ScalarEvolution*, llvm::DominatorTree*, llvm::AssumptionCache*, llvm::OptimizationRemarkEmitter*, bool)::$_3, decltype(fp())*) Line | Count | Source | 76 | 12 | void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) { | 77 | 12 | // Avoid building the remark unless we know there are at least *some* | 78 | 12 | // remarks enabled. We can't currently check whether remarks are requested | 79 | 12 | // for the calling pass since that requires actually building the remark. | 80 | 12 | | 81 | 12 | if (F->getContext().getDiagnosticsOutputFile() || | 82 | 12 | F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()12 ) { | 83 | 0 | auto R = RemarkBuilder(); | 84 | 0 | emit((DiagnosticInfoOptimizationBase &)R); | 85 | 0 | } | 86 | 12 | } |
LoopUnroll.cpp:void llvm::OptimizationRemarkEmitter::emit<llvm::UnrollLoop(llvm::Loop*, unsigned int, unsigned int, bool, bool, bool, bool, bool, unsigned int, unsigned int, bool, llvm::LoopInfo*, llvm::ScalarEvolution*, llvm::DominatorTree*, llvm::AssumptionCache*, llvm::OptimizationRemarkEmitter*, bool)::$_4>(llvm::UnrollLoop(llvm::Loop*, unsigned int, unsigned int, bool, bool, bool, bool, bool, unsigned int, unsigned int, bool, llvm::LoopInfo*, llvm::ScalarEvolution*, llvm::DominatorTree*, llvm::AssumptionCache*, llvm::OptimizationRemarkEmitter*, bool)::$_4, decltype(fp())*) Line | Count | Source | 76 | 502 | void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) { | 77 | 502 | // Avoid building the remark unless we know there are at least *some* | 78 | 502 | // remarks enabled. We can't currently check whether remarks are requested | 79 | 502 | // for the calling pass since that requires actually building the remark. | 80 | 502 | | 81 | 502 | if (F->getContext().getDiagnosticsOutputFile() || | 82 | 502 | F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()502 ) { | 83 | 1 | auto R = RemarkBuilder(); | 84 | 1 | emit((DiagnosticInfoOptimizationBase &)R); | 85 | 1 | } | 86 | 502 | } |
LoopVectorize.cpp:void llvm::OptimizationRemarkEmitter::emit<(anonymous namespace)::LoopVectorizeHints::allowVectorization(llvm::Function*, llvm::Loop*, bool) const::'lambda'()>((anonymous namespace)::LoopVectorizeHints::allowVectorization(llvm::Function*, llvm::Loop*, bool) const::'lambda'(), decltype(fp())*) Line | Count | Source | 76 | 11.1k | void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) { | 77 | 11.1k | // Avoid building the remark unless we know there are at least *some* | 78 | 11.1k | // remarks enabled. We can't currently check whether remarks are requested | 79 | 11.1k | // for the calling pass since that requires actually building the remark. | 80 | 11.1k | | 81 | 11.1k | if (F->getContext().getDiagnosticsOutputFile() || | 82 | 11.1k | F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()11.1k ) { | 83 | 6 | auto R = RemarkBuilder(); | 84 | 6 | emit((DiagnosticInfoOptimizationBase &)R); | 85 | 6 | } | 86 | 11.1k | } |
|
87 | | |
88 | | /// \brief Whether we allow for extra compile-time budget to perform more |
89 | | /// analysis to produce fewer false positives. |
90 | | /// |
91 | | /// This is useful when reporting missed optimizations. In this case we can |
92 | | /// use the extra analysis (1) to filter trivial false positives or (2) to |
93 | | /// provide more context so that non-trivial false positives can be quickly |
94 | | /// detected by the user. |
95 | 5.08M | bool allowExtraAnalysis(StringRef PassName) const { |
96 | 5.08M | return (F->getContext().getDiagnosticsOutputFile() || |
97 | 5.08M | F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled(PassName)); |
98 | 5.08M | } |
99 | | |
100 | | private: |
101 | | const Function *F; |
102 | | |
103 | | BlockFrequencyInfo *BFI; |
104 | | |
105 | | /// If we generate BFI on demand, we need to free it when ORE is freed. |
106 | | std::unique_ptr<BlockFrequencyInfo> OwnedBFI; |
107 | | |
108 | | /// Compute hotness from IR value (currently assumed to be a block) if PGO is |
109 | | /// available. |
110 | | Optional<uint64_t> computeHotness(const Value *V); |
111 | | |
112 | | /// Similar but use value from \p OptDiag and update hotness there. |
113 | | void computeHotness(DiagnosticInfoIROptimization &OptDiag); |
114 | | |
115 | | /// \brief Only allow verbose messages if we know we're filtering by hotness |
116 | | /// (BFI is only set in this case). |
117 | 660k | bool shouldEmitVerbose() { return BFI != nullptr; } |
118 | | |
119 | | OptimizationRemarkEmitter(const OptimizationRemarkEmitter &) = delete; |
120 | | void operator=(const OptimizationRemarkEmitter &) = delete; |
121 | | }; |
122 | | |
123 | | /// \brief Add a small namespace to avoid name clashes with the classes used in |
124 | | /// the streaming interface. We want these to be short for better |
125 | | /// write/readability. |
126 | | namespace ore { |
127 | | using NV = DiagnosticInfoOptimizationBase::Argument; |
128 | | using setIsVerbose = DiagnosticInfoOptimizationBase::setIsVerbose; |
129 | | using setExtraArgs = DiagnosticInfoOptimizationBase::setExtraArgs; |
130 | | } |
131 | | |
132 | | /// OptimizationRemarkEmitter legacy analysis pass |
133 | | /// |
134 | | /// Note that this pass shouldn't generally be marked as preserved by other |
135 | | /// passes. It's holding onto BFI, so if the pass does not preserve BFI, BFI |
136 | | /// could be freed. |
137 | | class OptimizationRemarkEmitterWrapperPass : public FunctionPass { |
138 | | std::unique_ptr<OptimizationRemarkEmitter> ORE; |
139 | | |
140 | | public: |
141 | | OptimizationRemarkEmitterWrapperPass(); |
142 | | |
143 | | bool runOnFunction(Function &F) override; |
144 | | |
145 | | void getAnalysisUsage(AnalysisUsage &AU) const override; |
146 | | |
147 | 7.83M | OptimizationRemarkEmitter &getORE() { |
148 | 7.83M | assert(ORE && "pass not run yet"); |
149 | 7.83M | return *ORE; |
150 | 7.83M | } |
151 | | |
152 | | static char ID; |
153 | | }; |
154 | | |
155 | | class OptimizationRemarkEmitterAnalysis |
156 | | : public AnalysisInfoMixin<OptimizationRemarkEmitterAnalysis> { |
157 | | friend AnalysisInfoMixin<OptimizationRemarkEmitterAnalysis>; |
158 | | static AnalysisKey Key; |
159 | | |
160 | | public: |
161 | | /// \brief Provide the result typedef for this analysis pass. |
162 | | typedef OptimizationRemarkEmitter Result; |
163 | | |
164 | | /// \brief Run the analysis pass over a function and produce BFI. |
165 | | Result run(Function &F, FunctionAnalysisManager &AM); |
166 | | }; |
167 | | |
168 | | namespace yaml { |
169 | | template <> struct MappingTraits<DiagnosticInfoOptimizationBase *> { |
170 | | static void mapping(IO &io, DiagnosticInfoOptimizationBase *&OptDiag); |
171 | | }; |
172 | | } |
173 | | } |
174 | | #endif // LLVM_IR_OPTIMIZATIONDIAGNOSTICINFO_H |