]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / CodeGen / MachineOptimizationRemarkEmitter.h
1 ///===- MachineOptimizationRemarkEmitter.h - Opt Diagnostics -*- C++ -*----===//
2 ///
3 /// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 /// See https://llvm.org/LICENSE.txt for license information.
5 /// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 ///
7 ///===---------------------------------------------------------------------===//
8 /// \file
9 /// Optimization diagnostic interfaces for machine passes.  It's packaged as an
10 /// analysis pass so that by using this service passes become dependent on MBFI
11 /// as well.  MBFI is used to compute the "hotness" of the diagnostic message.
12 ///
13 ///===---------------------------------------------------------------------===//
14
15 #ifndef LLVM_CODEGEN_MACHINEOPTIMIZATIONREMARKEMITTER_H
16 #define LLVM_CODEGEN_MACHINEOPTIMIZATIONREMARKEMITTER_H
17
18 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
19 #include "llvm/CodeGen/MachineFunctionPass.h"
20
21 namespace llvm {
22 class MachineBasicBlock;
23 class MachineBlockFrequencyInfo;
24 class MachineInstr;
25
26 /// Common features for diagnostics dealing with optimization remarks
27 /// that are used by machine passes.
28 class DiagnosticInfoMIROptimization : public DiagnosticInfoOptimizationBase {
29 public:
30   DiagnosticInfoMIROptimization(enum DiagnosticKind Kind, const char *PassName,
31                                 StringRef RemarkName,
32                                 const DiagnosticLocation &Loc,
33                                 const MachineBasicBlock *MBB)
34       : DiagnosticInfoOptimizationBase(Kind, DS_Remark, PassName, RemarkName,
35                                        MBB->getParent()->getFunction(), Loc),
36         MBB(MBB) {}
37
38   /// MI-specific kinds of diagnostic Arguments.
39   struct MachineArgument : public DiagnosticInfoOptimizationBase::Argument {
40     /// Print an entire MachineInstr.
41     MachineArgument(StringRef Key, const MachineInstr &MI);
42   };
43
44   static bool classof(const DiagnosticInfo *DI) {
45     return DI->getKind() >= DK_FirstMachineRemark &&
46            DI->getKind() <= DK_LastMachineRemark;
47   }
48
49   const MachineBasicBlock *getBlock() const { return MBB; }
50
51 private:
52   const MachineBasicBlock *MBB;
53 };
54
55 /// Diagnostic information for applied optimization remarks.
56 class MachineOptimizationRemark : public DiagnosticInfoMIROptimization {
57 public:
58   /// \p PassName is the name of the pass emitting this diagnostic. If this name
59   /// matches the regular expression given in -Rpass=, then the diagnostic will
60   /// be emitted.  \p RemarkName is a textual identifier for the remark.  \p
61   /// Loc is the debug location and \p MBB is the block that the optimization
62   /// operates in.
63   MachineOptimizationRemark(const char *PassName, StringRef RemarkName,
64                             const DiagnosticLocation &Loc,
65                             const MachineBasicBlock *MBB)
66       : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemark, PassName,
67                                       RemarkName, Loc, MBB) {}
68
69   static bool classof(const DiagnosticInfo *DI) {
70     return DI->getKind() == DK_MachineOptimizationRemark;
71   }
72
73   /// \see DiagnosticInfoOptimizationBase::isEnabled.
74   bool isEnabled() const override {
75     const Function &Fn = getFunction();
76     LLVMContext &Ctx = Fn.getContext();
77     return Ctx.getDiagHandlerPtr()->isPassedOptRemarkEnabled(getPassName());
78   }
79 };
80
81 /// Diagnostic information for missed-optimization remarks.
82 class MachineOptimizationRemarkMissed : public DiagnosticInfoMIROptimization {
83 public:
84   /// \p PassName is the name of the pass emitting this diagnostic. If this name
85   /// matches the regular expression given in -Rpass-missed=, then the
86   /// diagnostic will be emitted.  \p RemarkName is a textual identifier for the
87   /// remark.  \p Loc is the debug location and \p MBB is the block that the
88   /// optimization operates in.
89   MachineOptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
90                                   const DiagnosticLocation &Loc,
91                                   const MachineBasicBlock *MBB)
92       : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkMissed,
93                                       PassName, RemarkName, Loc, MBB) {}
94
95   static bool classof(const DiagnosticInfo *DI) {
96     return DI->getKind() == DK_MachineOptimizationRemarkMissed;
97   }
98
99   /// \see DiagnosticInfoOptimizationBase::isEnabled.
100   bool isEnabled() const override {
101     const Function &Fn = getFunction();
102     LLVMContext &Ctx = Fn.getContext();
103     return Ctx.getDiagHandlerPtr()->isMissedOptRemarkEnabled(getPassName());
104   }
105 };
106
107 /// Diagnostic information for optimization analysis remarks.
108 class MachineOptimizationRemarkAnalysis : public DiagnosticInfoMIROptimization {
109 public:
110   /// \p PassName is the name of the pass emitting this diagnostic. If this name
111   /// matches the regular expression given in -Rpass-analysis=, then the
112   /// diagnostic will be emitted.  \p RemarkName is a textual identifier for the
113   /// remark.  \p Loc is the debug location and \p MBB is the block that the
114   /// optimization operates in.
115   MachineOptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
116                                     const DiagnosticLocation &Loc,
117                                     const MachineBasicBlock *MBB)
118       : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkAnalysis,
119                                       PassName, RemarkName, Loc, MBB) {}
120
121   static bool classof(const DiagnosticInfo *DI) {
122     return DI->getKind() == DK_MachineOptimizationRemarkAnalysis;
123   }
124
125   /// \see DiagnosticInfoOptimizationBase::isEnabled.
126   bool isEnabled() const override {
127     const Function &Fn = getFunction();
128     LLVMContext &Ctx = Fn.getContext();
129     return Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(getPassName());
130   }
131 };
132
133 /// Extend llvm::ore:: with MI-specific helper names.
134 namespace ore {
135 using MNV = DiagnosticInfoMIROptimization::MachineArgument;
136 }
137
138 /// The optimization diagnostic interface.
139 ///
140 /// It allows reporting when optimizations are performed and when they are not
141 /// along with the reasons for it.  Hotness information of the corresponding
142 /// code region can be included in the remark if DiagnosticsHotnessRequested is
143 /// enabled in the LLVM context.
144 class MachineOptimizationRemarkEmitter {
145 public:
146   MachineOptimizationRemarkEmitter(MachineFunction &MF,
147                                    MachineBlockFrequencyInfo *MBFI)
148       : MF(MF), MBFI(MBFI) {}
149
150   /// Emit an optimization remark.
151   void emit(DiagnosticInfoOptimizationBase &OptDiag);
152
153   /// Whether we allow for extra compile-time budget to perform more
154   /// analysis to be more informative.
155   ///
156   /// This is useful to enable additional missed optimizations to be reported
157   /// that are normally too noisy.  In this mode, we can use the extra analysis
158   /// (1) to filter trivial false positives or (2) to provide more context so
159   /// that non-trivial false positives can be quickly detected by the user.
160   bool allowExtraAnalysis(StringRef PassName) const {
161     return (
162         MF.getFunction().getContext().getRemarkStreamer() ||
163         MF.getFunction().getContext().getDiagHandlerPtr()->isAnyRemarkEnabled(
164             PassName));
165   }
166
167   /// Take a lambda that returns a remark which will be emitted.  Second
168   /// argument is only used to restrict this to functions.
169   template <typename T>
170   void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) {
171     // Avoid building the remark unless we know there are at least *some*
172     // remarks enabled. We can't currently check whether remarks are requested
173     // for the calling pass since that requires actually building the remark.
174
175     if (MF.getFunction().getContext().getRemarkStreamer() ||
176         MF.getFunction()
177             .getContext()
178             .getDiagHandlerPtr()
179             ->isAnyRemarkEnabled()) {
180       auto R = RemarkBuilder();
181       emit((DiagnosticInfoOptimizationBase &)R);
182     }
183   }
184
185 private:
186   MachineFunction &MF;
187
188   /// MBFI is only set if hotness is requested.
189   MachineBlockFrequencyInfo *MBFI;
190
191   /// Compute hotness from IR value (currently assumed to be a block) if PGO is
192   /// available.
193   Optional<uint64_t> computeHotness(const MachineBasicBlock &MBB);
194
195   /// Similar but use value from \p OptDiag and update hotness there.
196   void computeHotness(DiagnosticInfoMIROptimization &Remark);
197
198   /// Only allow verbose messages if we know we're filtering by hotness
199   /// (BFI is only set in this case).
200   bool shouldEmitVerbose() { return MBFI != nullptr; }
201 };
202
203 /// The analysis pass
204 ///
205 /// Note that this pass shouldn't generally be marked as preserved by other
206 /// passes.  It's holding onto BFI, so if the pass does not preserve BFI, BFI
207 /// could be freed.
208 class MachineOptimizationRemarkEmitterPass : public MachineFunctionPass {
209   std::unique_ptr<MachineOptimizationRemarkEmitter> ORE;
210
211 public:
212   MachineOptimizationRemarkEmitterPass();
213
214   bool runOnMachineFunction(MachineFunction &MF) override;
215
216   void getAnalysisUsage(AnalysisUsage &AU) const override;
217
218   MachineOptimizationRemarkEmitter &getORE() {
219     assert(ORE && "pass not run yet");
220     return *ORE;
221   }
222
223   static char ID;
224 };
225 }
226
227 #endif