MachineOptimizationRemarkEmitter.h 9.5 KB

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