• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 ///===- MachineOptimizationRemarkEmitter.h - Opt Diagnostics -*- 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 /// \file
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.
13 ///
14 ///===---------------------------------------------------------------------===//
15 
16 #ifndef LLVM_CODEGEN_MACHINEOPTIMIZATIONREMARKEMITTER_H
17 #define LLVM_CODEGEN_MACHINEOPTIMIZATIONREMARKEMITTER_H
18 
19 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
20 #include "llvm/CodeGen/MachineFunctionPass.h"
21 
22 namespace llvm {
23 class MachineBasicBlock;
24 class MachineBlockFrequencyInfo;
25 class MachineInstr;
26 
27 /// Common features for diagnostics dealing with optimization remarks
28 /// that are used by machine passes.
29 class DiagnosticInfoMIROptimization : public DiagnosticInfoOptimizationBase {
30 public:
DiagnosticInfoMIROptimization(enum DiagnosticKind Kind,const char * PassName,StringRef RemarkName,const DiagnosticLocation & Loc,const MachineBasicBlock * MBB)31   DiagnosticInfoMIROptimization(enum DiagnosticKind Kind, const char *PassName,
32                                 StringRef RemarkName,
33                                 const DiagnosticLocation &Loc,
34                                 const MachineBasicBlock *MBB)
35       : DiagnosticInfoOptimizationBase(Kind, DS_Remark, PassName, RemarkName,
36                                        MBB->getParent()->getFunction(), Loc),
37         MBB(MBB) {}
38 
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);
43   };
44 
classof(const DiagnosticInfo * DI)45   static bool classof(const DiagnosticInfo *DI) {
46     return DI->getKind() >= DK_FirstMachineRemark &&
47            DI->getKind() <= DK_LastMachineRemark;
48   }
49 
getBlock()50   const MachineBasicBlock *getBlock() const { return MBB; }
51 
52 private:
53   const MachineBasicBlock *MBB;
54 };
55 
56 /// Diagnostic information for applied optimization remarks.
57 class MachineOptimizationRemark : public DiagnosticInfoMIROptimization {
58 public:
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
63   /// operates in.
MachineOptimizationRemark(const char * PassName,StringRef RemarkName,const DiagnosticLocation & Loc,const MachineBasicBlock * MBB)64   MachineOptimizationRemark(const char *PassName, StringRef RemarkName,
65                             const DiagnosticLocation &Loc,
66                             const MachineBasicBlock *MBB)
67       : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemark, PassName,
68                                       RemarkName, Loc, MBB) {}
69 
classof(const DiagnosticInfo * DI)70   static bool classof(const DiagnosticInfo *DI) {
71     return DI->getKind() == DK_MachineOptimizationRemark;
72   }
73 
74   /// \see DiagnosticInfoOptimizationBase::isEnabled.
isEnabled()75   bool isEnabled() const override {
76     const Function &Fn = getFunction();
77     LLVMContext &Ctx = Fn.getContext();
78     return Ctx.getDiagHandlerPtr()->isPassedOptRemarkEnabled(getPassName());
79   }
80 };
81 
82 /// Diagnostic information for missed-optimization remarks.
83 class MachineOptimizationRemarkMissed : public DiagnosticInfoMIROptimization {
84 public:
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.
MachineOptimizationRemarkMissed(const char * PassName,StringRef RemarkName,const DiagnosticLocation & Loc,const MachineBasicBlock * MBB)90   MachineOptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
91                                   const DiagnosticLocation &Loc,
92                                   const MachineBasicBlock *MBB)
93       : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkMissed,
94                                       PassName, RemarkName, Loc, MBB) {}
95 
classof(const DiagnosticInfo * DI)96   static bool classof(const DiagnosticInfo *DI) {
97     return DI->getKind() == DK_MachineOptimizationRemarkMissed;
98   }
99 
100   /// \see DiagnosticInfoOptimizationBase::isEnabled.
isEnabled()101   bool isEnabled() const override {
102     const Function &Fn = getFunction();
103     LLVMContext &Ctx = Fn.getContext();
104     return Ctx.getDiagHandlerPtr()->isMissedOptRemarkEnabled(getPassName());
105   }
106 };
107 
108 /// Diagnostic information for optimization analysis remarks.
109 class MachineOptimizationRemarkAnalysis : public DiagnosticInfoMIROptimization {
110 public:
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.
MachineOptimizationRemarkAnalysis(const char * PassName,StringRef RemarkName,const DiagnosticLocation & Loc,const MachineBasicBlock * MBB)116   MachineOptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
117                                     const DiagnosticLocation &Loc,
118                                     const MachineBasicBlock *MBB)
119       : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkAnalysis,
120                                       PassName, RemarkName, Loc, MBB) {}
121 
classof(const DiagnosticInfo * DI)122   static bool classof(const DiagnosticInfo *DI) {
123     return DI->getKind() == DK_MachineOptimizationRemarkAnalysis;
124   }
125 
126   /// \see DiagnosticInfoOptimizationBase::isEnabled.
isEnabled()127   bool isEnabled() const override {
128     const Function &Fn = getFunction();
129     LLVMContext &Ctx = Fn.getContext();
130     return Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(getPassName());
131   }
132 };
133 
134 /// Extend llvm::ore:: with MI-specific helper names.
135 namespace ore {
136 using MNV = DiagnosticInfoMIROptimization::MachineArgument;
137 }
138 
139 /// The optimization diagnostic interface.
140 ///
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 {
146 public:
MachineOptimizationRemarkEmitter(MachineFunction & MF,MachineBlockFrequencyInfo * MBFI)147   MachineOptimizationRemarkEmitter(MachineFunction &MF,
148                                    MachineBlockFrequencyInfo *MBFI)
149       : MF(MF), MBFI(MBFI) {}
150 
151   /// Emit an optimization remark.
152   void emit(DiagnosticInfoOptimizationBase &OptDiag);
153 
154   /// Whether we allow for extra compile-time budget to perform more
155   /// analysis to be more informative.
156   ///
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.
allowExtraAnalysis(StringRef PassName)161   bool allowExtraAnalysis(StringRef PassName) const {
162     return (MF.getFunction().getContext().getDiagnosticsOutputFile() ||
163             MF.getFunction().getContext()
164             .getDiagHandlerPtr()->isAnyRemarkEnabled(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().getDiagnosticsOutputFile() ||
176         MF.getFunction().getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()) {
177       auto R = RemarkBuilder();
178       emit((DiagnosticInfoOptimizationBase &)R);
179     }
180   }
181 
182 private:
183   MachineFunction &MF;
184 
185   /// MBFI is only set if hotness is requested.
186   MachineBlockFrequencyInfo *MBFI;
187 
188   /// Compute hotness from IR value (currently assumed to be a block) if PGO is
189   /// available.
190   Optional<uint64_t> computeHotness(const MachineBasicBlock &MBB);
191 
192   /// Similar but use value from \p OptDiag and update hotness there.
193   void computeHotness(DiagnosticInfoMIROptimization &Remark);
194 
195   /// Only allow verbose messages if we know we're filtering by hotness
196   /// (BFI is only set in this case).
shouldEmitVerbose()197   bool shouldEmitVerbose() { return MBFI != nullptr; }
198 };
199 
200 /// The analysis pass
201 ///
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
204 /// could be freed.
205 class MachineOptimizationRemarkEmitterPass : public MachineFunctionPass {
206   std::unique_ptr<MachineOptimizationRemarkEmitter> ORE;
207 
208 public:
209   MachineOptimizationRemarkEmitterPass();
210 
211   bool runOnMachineFunction(MachineFunction &MF) override;
212 
213   void getAnalysisUsage(AnalysisUsage &AU) const override;
214 
getORE()215   MachineOptimizationRemarkEmitter &getORE() {
216     assert(ORE && "pass not run yet");
217     return *ORE;
218   }
219 
220   static char ID;
221 };
222 }
223 
224 #endif
225