Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:31

0001 ///===- MachineOptimizationRemarkEmitter.h - Opt Diagnostics -*- C++ -*----===//
0002 ///
0003 /// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 /// See https://llvm.org/LICENSE.txt for license information.
0005 /// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 ///
0007 ///===---------------------------------------------------------------------===//
0008 /// \file
0009 /// Optimization diagnostic interfaces for machine passes.  It's packaged as an
0010 /// analysis pass so that by using this service passes become dependent on MBFI
0011 /// as well.  MBFI is used to compute the "hotness" of the diagnostic message.
0012 ///
0013 ///===---------------------------------------------------------------------===//
0014 
0015 #ifndef LLVM_CODEGEN_MACHINEOPTIMIZATIONREMARKEMITTER_H
0016 #define LLVM_CODEGEN_MACHINEOPTIMIZATIONREMARKEMITTER_H
0017 
0018 #include "llvm/CodeGen/MachineFunctionPass.h"
0019 #include "llvm/CodeGen/MachinePassManager.h"
0020 #include "llvm/IR/DiagnosticInfo.h"
0021 #include "llvm/IR/Function.h"
0022 #include <optional>
0023 
0024 namespace llvm {
0025 class MachineBasicBlock;
0026 class MachineBlockFrequencyInfo;
0027 class MachineInstr;
0028 
0029 /// Common features for diagnostics dealing with optimization remarks
0030 /// that are used by machine passes.
0031 class DiagnosticInfoMIROptimization : public DiagnosticInfoOptimizationBase {
0032 public:
0033   DiagnosticInfoMIROptimization(enum DiagnosticKind Kind, const char *PassName,
0034                                 StringRef RemarkName,
0035                                 const DiagnosticLocation &Loc,
0036                                 const MachineBasicBlock *MBB)
0037       : DiagnosticInfoOptimizationBase(Kind, DS_Remark, PassName, RemarkName,
0038                                        MBB->getParent()->getFunction(), Loc),
0039         MBB(MBB) {}
0040 
0041   /// MI-specific kinds of diagnostic Arguments.
0042   struct MachineArgument : public DiagnosticInfoOptimizationBase::Argument {
0043     /// Print an entire MachineInstr.
0044     MachineArgument(StringRef Key, const MachineInstr &MI);
0045   };
0046 
0047   static bool classof(const DiagnosticInfo *DI) {
0048     return DI->getKind() >= DK_FirstMachineRemark &&
0049            DI->getKind() <= DK_LastMachineRemark;
0050   }
0051 
0052   const MachineBasicBlock *getBlock() const { return MBB; }
0053 
0054 private:
0055   const MachineBasicBlock *MBB;
0056 };
0057 
0058 /// Diagnostic information for applied optimization remarks.
0059 class MachineOptimizationRemark : public DiagnosticInfoMIROptimization {
0060 public:
0061   /// \p PassName is the name of the pass emitting this diagnostic. If this name
0062   /// matches the regular expression given in -Rpass=, then the diagnostic will
0063   /// be emitted.  \p RemarkName is a textual identifier for the remark.  \p
0064   /// Loc is the debug location and \p MBB is the block that the optimization
0065   /// operates in.
0066   MachineOptimizationRemark(const char *PassName, StringRef RemarkName,
0067                             const DiagnosticLocation &Loc,
0068                             const MachineBasicBlock *MBB)
0069       : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemark, PassName,
0070                                       RemarkName, Loc, MBB) {}
0071 
0072   static bool classof(const DiagnosticInfo *DI) {
0073     return DI->getKind() == DK_MachineOptimizationRemark;
0074   }
0075 
0076   /// \see DiagnosticInfoOptimizationBase::isEnabled.
0077   bool isEnabled() const override {
0078     const Function &Fn = getFunction();
0079     LLVMContext &Ctx = Fn.getContext();
0080     return Ctx.getDiagHandlerPtr()->isPassedOptRemarkEnabled(getPassName());
0081   }
0082 };
0083 
0084 /// Diagnostic information for missed-optimization remarks.
0085 class MachineOptimizationRemarkMissed : public DiagnosticInfoMIROptimization {
0086 public:
0087   /// \p PassName is the name of the pass emitting this diagnostic. If this name
0088   /// matches the regular expression given in -Rpass-missed=, then the
0089   /// diagnostic will be emitted.  \p RemarkName is a textual identifier for the
0090   /// remark.  \p Loc is the debug location and \p MBB is the block that the
0091   /// optimization operates in.
0092   MachineOptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
0093                                   const DiagnosticLocation &Loc,
0094                                   const MachineBasicBlock *MBB)
0095       : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkMissed,
0096                                       PassName, RemarkName, Loc, MBB) {}
0097 
0098   static bool classof(const DiagnosticInfo *DI) {
0099     return DI->getKind() == DK_MachineOptimizationRemarkMissed;
0100   }
0101 
0102   /// \see DiagnosticInfoOptimizationBase::isEnabled.
0103   bool isEnabled() const override {
0104     const Function &Fn = getFunction();
0105     LLVMContext &Ctx = Fn.getContext();
0106     return Ctx.getDiagHandlerPtr()->isMissedOptRemarkEnabled(getPassName());
0107   }
0108 };
0109 
0110 /// Diagnostic information for optimization analysis remarks.
0111 class MachineOptimizationRemarkAnalysis : public DiagnosticInfoMIROptimization {
0112 public:
0113   /// \p PassName is the name of the pass emitting this diagnostic. If this name
0114   /// matches the regular expression given in -Rpass-analysis=, then the
0115   /// diagnostic will be emitted.  \p RemarkName is a textual identifier for the
0116   /// remark.  \p Loc is the debug location and \p MBB is the block that the
0117   /// optimization operates in.
0118   MachineOptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
0119                                     const DiagnosticLocation &Loc,
0120                                     const MachineBasicBlock *MBB)
0121       : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkAnalysis,
0122                                       PassName, RemarkName, Loc, MBB) {}
0123 
0124   MachineOptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
0125                                     const MachineInstr *MI)
0126       : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkAnalysis,
0127                                       PassName, RemarkName, MI->getDebugLoc(),
0128                                       MI->getParent()) {}
0129 
0130   static bool classof(const DiagnosticInfo *DI) {
0131     return DI->getKind() == DK_MachineOptimizationRemarkAnalysis;
0132   }
0133 
0134   /// \see DiagnosticInfoOptimizationBase::isEnabled.
0135   bool isEnabled() const override {
0136     const Function &Fn = getFunction();
0137     LLVMContext &Ctx = Fn.getContext();
0138     return Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(getPassName());
0139   }
0140 };
0141 
0142 /// Extend llvm::ore:: with MI-specific helper names.
0143 namespace ore {
0144 using MNV = DiagnosticInfoMIROptimization::MachineArgument;
0145 }
0146 
0147 /// The optimization diagnostic interface.
0148 ///
0149 /// It allows reporting when optimizations are performed and when they are not
0150 /// along with the reasons for it.  Hotness information of the corresponding
0151 /// code region can be included in the remark if DiagnosticsHotnessRequested is
0152 /// enabled in the LLVM context.
0153 class MachineOptimizationRemarkEmitter {
0154 public:
0155   MachineOptimizationRemarkEmitter(MachineFunction &MF,
0156                                    MachineBlockFrequencyInfo *MBFI)
0157       : MF(MF), MBFI(MBFI) {}
0158 
0159   MachineOptimizationRemarkEmitter(MachineOptimizationRemarkEmitter &&) =
0160       default;
0161 
0162   /// Handle invalidation events in the new pass manager.
0163   bool invalidate(MachineFunction &MF, const PreservedAnalyses &PA,
0164                   MachineFunctionAnalysisManager::Invalidator &Inv);
0165 
0166   /// Emit an optimization remark.
0167   void emit(DiagnosticInfoOptimizationBase &OptDiag);
0168 
0169   /// Whether we allow for extra compile-time budget to perform more
0170   /// analysis to be more informative.
0171   ///
0172   /// This is useful to enable additional missed optimizations to be reported
0173   /// that are normally too noisy.  In this mode, we can use the extra analysis
0174   /// (1) to filter trivial false positives or (2) to provide more context so
0175   /// that non-trivial false positives can be quickly detected by the user.
0176   bool allowExtraAnalysis(StringRef PassName) const {
0177     return (
0178         MF.getFunction().getContext().getLLVMRemarkStreamer() ||
0179         MF.getFunction().getContext().getDiagHandlerPtr()->isAnyRemarkEnabled(
0180             PassName));
0181   }
0182 
0183   /// Take a lambda that returns a remark which will be emitted.  Second
0184   /// argument is only used to restrict this to functions.
0185   template <typename T>
0186   void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) {
0187     // Avoid building the remark unless we know there are at least *some*
0188     // remarks enabled. We can't currently check whether remarks are requested
0189     // for the calling pass since that requires actually building the remark.
0190 
0191     if (MF.getFunction().getContext().getLLVMRemarkStreamer() ||
0192         MF.getFunction()
0193             .getContext()
0194             .getDiagHandlerPtr()
0195             ->isAnyRemarkEnabled()) {
0196       auto R = RemarkBuilder();
0197       emit((DiagnosticInfoOptimizationBase &)R);
0198     }
0199   }
0200 
0201   MachineBlockFrequencyInfo *getBFI() {
0202     return MBFI;
0203   }
0204 
0205 private:
0206   MachineFunction &MF;
0207 
0208   /// MBFI is only set if hotness is requested.
0209   MachineBlockFrequencyInfo *MBFI;
0210 
0211   /// Compute hotness from IR value (currently assumed to be a block) if PGO is
0212   /// available.
0213   std::optional<uint64_t> computeHotness(const MachineBasicBlock &MBB);
0214 
0215   /// Similar but use value from \p OptDiag and update hotness there.
0216   void computeHotness(DiagnosticInfoMIROptimization &Remark);
0217 
0218   /// Only allow verbose messages if we know we're filtering by hotness
0219   /// (BFI is only set in this case).
0220   bool shouldEmitVerbose() { return MBFI != nullptr; }
0221 };
0222 
0223 /// The analysis pass
0224 class MachineOptimizationRemarkEmitterAnalysis
0225     : public AnalysisInfoMixin<MachineOptimizationRemarkEmitterAnalysis> {
0226   friend AnalysisInfoMixin<MachineOptimizationRemarkEmitterAnalysis>;
0227   static AnalysisKey Key;
0228 
0229 public:
0230   using Result = MachineOptimizationRemarkEmitter;
0231   Result run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM);
0232 };
0233 
0234 /// The analysis pass
0235 ///
0236 /// Note that this pass shouldn't generally be marked as preserved by other
0237 /// passes.  It's holding onto BFI, so if the pass does not preserve BFI, BFI
0238 /// could be freed.
0239 class MachineOptimizationRemarkEmitterPass : public MachineFunctionPass {
0240   std::unique_ptr<MachineOptimizationRemarkEmitter> ORE;
0241 
0242 public:
0243   MachineOptimizationRemarkEmitterPass();
0244 
0245   bool runOnMachineFunction(MachineFunction &MF) override;
0246 
0247   void getAnalysisUsage(AnalysisUsage &AU) const override;
0248 
0249   MachineOptimizationRemarkEmitter &getORE() {
0250     assert(ORE && "pass not run yet");
0251     return *ORE;
0252   }
0253 
0254   static char ID;
0255 };
0256 }
0257 
0258 #endif