MachineOptimizationRemarkEmitter.h revision 360784
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 21namespace llvm { 22class MachineBasicBlock; 23class MachineBlockFrequencyInfo; 24class MachineInstr; 25 26/// Common features for diagnostics dealing with optimization remarks 27/// that are used by machine passes. 28class DiagnosticInfoMIROptimization : public DiagnosticInfoOptimizationBase { 29public: 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 51private: 52 const MachineBasicBlock *MBB; 53}; 54 55/// Diagnostic information for applied optimization remarks. 56class MachineOptimizationRemark : public DiagnosticInfoMIROptimization { 57public: 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. 82class MachineOptimizationRemarkMissed : public DiagnosticInfoMIROptimization { 83public: 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. 108class MachineOptimizationRemarkAnalysis : public DiagnosticInfoMIROptimization { 109public: 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. 134namespace ore { 135using 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. 144class MachineOptimizationRemarkEmitter { 145public: 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 MachineBlockFrequencyInfo *getBFI() { 186 return MBFI; 187 } 188 189private: 190 MachineFunction &MF; 191 192 /// MBFI is only set if hotness is requested. 193 MachineBlockFrequencyInfo *MBFI; 194 195 /// Compute hotness from IR value (currently assumed to be a block) if PGO is 196 /// available. 197 Optional<uint64_t> computeHotness(const MachineBasicBlock &MBB); 198 199 /// Similar but use value from \p OptDiag and update hotness there. 200 void computeHotness(DiagnosticInfoMIROptimization &Remark); 201 202 /// Only allow verbose messages if we know we're filtering by hotness 203 /// (BFI is only set in this case). 204 bool shouldEmitVerbose() { return MBFI != nullptr; } 205}; 206 207/// The analysis pass 208/// 209/// Note that this pass shouldn't generally be marked as preserved by other 210/// passes. It's holding onto BFI, so if the pass does not preserve BFI, BFI 211/// could be freed. 212class MachineOptimizationRemarkEmitterPass : public MachineFunctionPass { 213 std::unique_ptr<MachineOptimizationRemarkEmitter> ORE; 214 215public: 216 MachineOptimizationRemarkEmitterPass(); 217 218 bool runOnMachineFunction(MachineFunction &MF) override; 219 220 void getAnalysisUsage(AnalysisUsage &AU) const override; 221 222 MachineOptimizationRemarkEmitter &getORE() { 223 assert(ORE && "pass not run yet"); 224 return *ORE; 225 } 226 227 static char ID; 228}; 229} 230 231#endif 232