MachineOptimizationRemarkEmitter.h 9.0 KB

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