MachineOptimizationRemarkEmitter.h 9.5 KB

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