1 ///===- MachineOptimizationRemarkEmitter.h - Opt Diagnostics -*- C++ -*----===//
3 /// The LLVM Compiler Infrastructure
5 /// This file is distributed under the University of Illinois Open Source
6 /// License. See LICENSE.TXT for details.
8 ///===---------------------------------------------------------------------===//
10 /// Optimization diagnostic interfaces for machine passes. It's packaged as an
11 /// analysis pass so that by using this service passes become dependent on MBFI
12 /// as well. MBFI is used to compute the "hotness" of the diagnostic message.
14 ///===---------------------------------------------------------------------===//
16 #ifndef LLVM_CODEGEN_MACHINEOPTIMIZATIONREMARKEMITTER_H
17 #define LLVM_CODEGEN_MACHINEOPTIMIZATIONREMARKEMITTER_H
19 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
20 #include "llvm/CodeGen/MachineFunctionPass.h"
23 class MachineBasicBlock;
24 class MachineBlockFrequencyInfo;
27 /// Common features for diagnostics dealing with optimization remarks
28 /// that are used by machine passes.
29 class DiagnosticInfoMIROptimization : public DiagnosticInfoOptimizationBase {
31 DiagnosticInfoMIROptimization(enum DiagnosticKind Kind, const char *PassName,
33 const DiagnosticLocation &Loc,
34 const MachineBasicBlock *MBB)
35 : DiagnosticInfoOptimizationBase(Kind, DS_Remark, PassName, RemarkName,
36 MBB->getParent()->getFunction(), Loc),
39 /// MI-specific kinds of diagnostic Arguments.
40 struct MachineArgument : public DiagnosticInfoOptimizationBase::Argument {
41 /// Print an entire MachineInstr.
42 MachineArgument(StringRef Key, const MachineInstr &MI);
45 static bool classof(const DiagnosticInfo *DI) {
46 return DI->getKind() >= DK_FirstMachineRemark &&
47 DI->getKind() <= DK_LastMachineRemark;
50 const MachineBasicBlock *getBlock() const { return MBB; }
53 const MachineBasicBlock *MBB;
56 /// Diagnostic information for applied optimization remarks.
57 class MachineOptimizationRemark : public DiagnosticInfoMIROptimization {
59 /// \p PassName is the name of the pass emitting this diagnostic. If this name
60 /// matches the regular expression given in -Rpass=, then the diagnostic will
61 /// be emitted. \p RemarkName is a textual identifier for the remark. \p
62 /// Loc is the debug location and \p MBB is the block that the optimization
64 MachineOptimizationRemark(const char *PassName, StringRef RemarkName,
65 const DiagnosticLocation &Loc,
66 const MachineBasicBlock *MBB)
67 : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemark, PassName,
68 RemarkName, Loc, MBB) {}
70 static bool classof(const DiagnosticInfo *DI) {
71 return DI->getKind() == DK_MachineOptimizationRemark;
74 /// \see DiagnosticInfoOptimizationBase::isEnabled.
75 bool isEnabled() const override {
76 const Function &Fn = getFunction();
77 LLVMContext &Ctx = Fn.getContext();
78 return Ctx.getDiagHandlerPtr()->isPassedOptRemarkEnabled(getPassName());
82 /// Diagnostic information for missed-optimization remarks.
83 class MachineOptimizationRemarkMissed : public DiagnosticInfoMIROptimization {
85 /// \p PassName is the name of the pass emitting this diagnostic. If this name
86 /// matches the regular expression given in -Rpass-missed=, then the
87 /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
88 /// remark. \p Loc is the debug location and \p MBB is the block that the
89 /// optimization operates in.
90 MachineOptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
91 const DiagnosticLocation &Loc,
92 const MachineBasicBlock *MBB)
93 : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkMissed,
94 PassName, RemarkName, Loc, MBB) {}
96 static bool classof(const DiagnosticInfo *DI) {
97 return DI->getKind() == DK_MachineOptimizationRemarkMissed;
100 /// \see DiagnosticInfoOptimizationBase::isEnabled.
101 bool isEnabled() const override {
102 const Function &Fn = getFunction();
103 LLVMContext &Ctx = Fn.getContext();
104 return Ctx.getDiagHandlerPtr()->isMissedOptRemarkEnabled(getPassName());
108 /// Diagnostic information for optimization analysis remarks.
109 class MachineOptimizationRemarkAnalysis : public DiagnosticInfoMIROptimization {
111 /// \p PassName is the name of the pass emitting this diagnostic. If this name
112 /// matches the regular expression given in -Rpass-analysis=, then the
113 /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
114 /// remark. \p Loc is the debug location and \p MBB is the block that the
115 /// optimization operates in.
116 MachineOptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
117 const DiagnosticLocation &Loc,
118 const MachineBasicBlock *MBB)
119 : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkAnalysis,
120 PassName, RemarkName, Loc, MBB) {}
122 static bool classof(const DiagnosticInfo *DI) {
123 return DI->getKind() == DK_MachineOptimizationRemarkAnalysis;
126 /// \see DiagnosticInfoOptimizationBase::isEnabled.
127 bool isEnabled() const override {
128 const Function &Fn = getFunction();
129 LLVMContext &Ctx = Fn.getContext();
130 return Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(getPassName());
134 /// Extend llvm::ore:: with MI-specific helper names.
136 using MNV = DiagnosticInfoMIROptimization::MachineArgument;
139 /// The optimization diagnostic interface.
141 /// It allows reporting when optimizations are performed and when they are not
142 /// along with the reasons for it. Hotness information of the corresponding
143 /// code region can be included in the remark if DiagnosticsHotnessRequested is
144 /// enabled in the LLVM context.
145 class MachineOptimizationRemarkEmitter {
147 MachineOptimizationRemarkEmitter(MachineFunction &MF,
148 MachineBlockFrequencyInfo *MBFI)
149 : MF(MF), MBFI(MBFI) {}
151 /// Emit an optimization remark.
152 void emit(DiagnosticInfoOptimizationBase &OptDiag);
154 /// Whether we allow for extra compile-time budget to perform more
155 /// analysis to be more informative.
157 /// This is useful to enable additional missed optimizations to be reported
158 /// that are normally too noisy. In this mode, we can use the extra analysis
159 /// (1) to filter trivial false positives or (2) to provide more context so
160 /// that non-trivial false positives can be quickly detected by the user.
161 bool allowExtraAnalysis(StringRef PassName) const {
162 return (MF.getFunction().getContext().getDiagnosticsOutputFile() ||
163 MF.getFunction().getContext()
164 .getDiagHandlerPtr()->isAnyRemarkEnabled(PassName));
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.
175 if (MF.getFunction().getContext().getDiagnosticsOutputFile() ||
176 MF.getFunction().getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()) {
177 auto R = RemarkBuilder();
178 emit((DiagnosticInfoOptimizationBase &)R);
185 /// MBFI is only set if hotness is requested.
186 MachineBlockFrequencyInfo *MBFI;
188 /// Compute hotness from IR value (currently assumed to be a block) if PGO is
190 Optional<uint64_t> computeHotness(const MachineBasicBlock &MBB);
192 /// Similar but use value from \p OptDiag and update hotness there.
193 void computeHotness(DiagnosticInfoMIROptimization &Remark);
195 /// Only allow verbose messages if we know we're filtering by hotness
196 /// (BFI is only set in this case).
197 bool shouldEmitVerbose() { return MBFI != nullptr; }
200 /// The analysis pass
202 /// Note that this pass shouldn't generally be marked as preserved by other
203 /// passes. It's holding onto BFI, so if the pass does not preserve BFI, BFI
205 class MachineOptimizationRemarkEmitterPass : public MachineFunctionPass {
206 std::unique_ptr<MachineOptimizationRemarkEmitter> ORE;
209 MachineOptimizationRemarkEmitterPass();
211 bool runOnMachineFunction(MachineFunction &MF) override;
213 void getAnalysisUsage(AnalysisUsage &AU) const override;
215 MachineOptimizationRemarkEmitter &getORE() {
216 assert(ORE && "pass not run yet");