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