Home | History | Annotate | Download | only in CodeGen
      1 ///===- MachineOptimizationRemarkEmitter.h - Opt Diagnostics -*- C++ -*----===//
      2 ///
      3 ///                     The LLVM Compiler Infrastructure
      4 ///
      5 /// This file is distributed under the University of Illinois Open Source
      6 /// License. See LICENSE.TXT for details.
      7 ///
      8 ///===---------------------------------------------------------------------===//
      9 /// \file
     10 /// Optimization diagnostic interfaces for machine passes.  It's packaged as an
     11 /// analysis pass so that by using this service passes become dependent on MBFI
     12 /// as well.  MBFI is used to compute the "hotness" of the diagnostic message.
     13 ///
     14 ///===---------------------------------------------------------------------===//
     15 
     16 #ifndef LLVM_CODEGEN_MACHINEOPTIMIZATIONREMARKEMITTER_H
     17 #define LLVM_CODEGEN_MACHINEOPTIMIZATIONREMARKEMITTER_H
     18 
     19 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
     20 #include "llvm/CodeGen/MachineFunctionPass.h"
     21 
     22 namespace llvm {
     23 class MachineBasicBlock;
     24 class MachineBlockFrequencyInfo;
     25 class MachineInstr;
     26 
     27 /// \brief 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 
     39   /// MI-specific kinds of diagnostic Arguments.
     40   struct MachineArgument : public DiagnosticInfoOptimizationBase::Argument {
     41     /// Print an entire MachineInstr.
     42     MachineArgument(StringRef Key, const MachineInstr &MI);
     43   };
     44 
     45   static bool classof(const DiagnosticInfo *DI) {
     46     return DI->getKind() >= DK_FirstMachineRemark &&
     47            DI->getKind() <= DK_LastMachineRemark;
     48   }
     49 
     50   const MachineBasicBlock *getBlock() const { return MBB; }
     51 
     52 private:
     53   const MachineBasicBlock *MBB;
     54 };
     55 
     56 /// Diagnostic information for applied optimization remarks.
     57 class MachineOptimizationRemark : public DiagnosticInfoMIROptimization {
     58 public:
     59   /// \p PassName is the name of the pass emitting this diagnostic. If this name
     60   /// matches the regular expression given in -Rpass=, then the diagnostic will
     61   /// be emitted.  \p RemarkName is a textual identifier for the remark.  \p
     62   /// Loc is the debug location and \p MBB is the block that the optimization
     63   /// operates in.
     64   MachineOptimizationRemark(const char *PassName, StringRef RemarkName,
     65                             const DiagnosticLocation &Loc,
     66                             const MachineBasicBlock *MBB)
     67       : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemark, PassName,
     68                                       RemarkName, Loc, MBB) {}
     69 
     70   static bool classof(const DiagnosticInfo *DI) {
     71     return DI->getKind() == DK_MachineOptimizationRemark;
     72   }
     73 
     74   /// \see DiagnosticInfoOptimizationBase::isEnabled.
     75   bool isEnabled() const override {
     76     const Function &Fn = getFunction();
     77     LLVMContext &Ctx = Fn.getContext();
     78     return Ctx.getDiagHandlerPtr()->isPassedOptRemarkEnabled(getPassName());
     79   }
     80 };
     81 
     82 /// Diagnostic information for missed-optimization remarks.
     83 class MachineOptimizationRemarkMissed : public DiagnosticInfoMIROptimization {
     84 public:
     85   /// \p PassName is the name of the pass emitting this diagnostic. If this name
     86   /// matches the regular expression given in -Rpass-missed=, then the
     87   /// diagnostic will be emitted.  \p RemarkName is a textual identifier for the
     88   /// remark.  \p Loc is the debug location and \p MBB is the block that the
     89   /// optimization operates in.
     90   MachineOptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
     91                                   const DiagnosticLocation &Loc,
     92                                   const MachineBasicBlock *MBB)
     93       : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkMissed,
     94                                       PassName, RemarkName, Loc, MBB) {}
     95 
     96   static bool classof(const DiagnosticInfo *DI) {
     97     return DI->getKind() == DK_MachineOptimizationRemarkMissed;
     98   }
     99 
    100   /// \see DiagnosticInfoOptimizationBase::isEnabled.
    101   bool isEnabled() const override {
    102     const Function &Fn = getFunction();
    103     LLVMContext &Ctx = Fn.getContext();
    104     return Ctx.getDiagHandlerPtr()->isMissedOptRemarkEnabled(getPassName());
    105   }
    106 };
    107 
    108 /// Diagnostic information for optimization analysis remarks.
    109 class MachineOptimizationRemarkAnalysis : public DiagnosticInfoMIROptimization {
    110 public:
    111   /// \p PassName is the name of the pass emitting this diagnostic. If this name
    112   /// matches the regular expression given in -Rpass-analysis=, then the
    113   /// diagnostic will be emitted.  \p RemarkName is a textual identifier for the
    114   /// remark.  \p Loc is the debug location and \p MBB is the block that the
    115   /// optimization operates in.
    116   MachineOptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
    117                                     const DiagnosticLocation &Loc,
    118                                     const MachineBasicBlock *MBB)
    119       : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkAnalysis,
    120                                       PassName, RemarkName, Loc, MBB) {}
    121 
    122   static bool classof(const DiagnosticInfo *DI) {
    123     return DI->getKind() == DK_MachineOptimizationRemarkAnalysis;
    124   }
    125 
    126   /// \see DiagnosticInfoOptimizationBase::isEnabled.
    127   bool isEnabled() const override {
    128     const Function &Fn = getFunction();
    129     LLVMContext &Ctx = Fn.getContext();
    130     return Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(getPassName());
    131   }
    132 };
    133 
    134 /// Extend llvm::ore:: with MI-specific helper names.
    135 namespace ore {
    136 using MNV = DiagnosticInfoMIROptimization::MachineArgument;
    137 }
    138 
    139 /// The optimization diagnostic interface.
    140 ///
    141 /// It allows reporting when optimizations are performed and when they are not
    142 /// along with the reasons for it.  Hotness information of the corresponding
    143 /// code region can be included in the remark if DiagnosticsHotnessRequested is
    144 /// enabled in the LLVM context.
    145 class MachineOptimizationRemarkEmitter {
    146 public:
    147   MachineOptimizationRemarkEmitter(MachineFunction &MF,
    148                                    MachineBlockFrequencyInfo *MBFI)
    149       : MF(MF), MBFI(MBFI) {}
    150 
    151   /// Emit an optimization remark.
    152   void emit(DiagnosticInfoOptimizationBase &OptDiag);
    153 
    154   /// \brief Whether we allow for extra compile-time budget to perform more
    155   /// analysis to be more informative.
    156   ///
    157   /// This is useful to enable additional missed optimizations to be reported
    158   /// that are normally too noisy.  In this mode, we can use the extra analysis
    159   /// (1) to filter trivial false positives or (2) to provide more context so
    160   /// that non-trivial false positives can be quickly detected by the user.
    161   bool allowExtraAnalysis(StringRef PassName) const {
    162     return (MF.getFunction()->getContext().getDiagnosticsOutputFile() ||
    163             MF.getFunction()->getContext()
    164             .getDiagHandlerPtr()->isAnyRemarkEnabled(PassName));
    165   }
    166 
    167   /// \brief 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().getDiagnosticsOutputFile() ||
    176         MF.getFunction()->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()) {
    177       auto R = RemarkBuilder();
    178       emit((DiagnosticInfoOptimizationBase &)R);
    179     }
    180   }
    181 
    182 private:
    183   MachineFunction &MF;
    184 
    185   /// MBFI is only set if hotness is requested.
    186   MachineBlockFrequencyInfo *MBFI;
    187 
    188   /// Compute hotness from IR value (currently assumed to be a block) if PGO is
    189   /// available.
    190   Optional<uint64_t> computeHotness(const MachineBasicBlock &MBB);
    191 
    192   /// Similar but use value from \p OptDiag and update hotness there.
    193   void computeHotness(DiagnosticInfoMIROptimization &Remark);
    194 
    195   /// \brief Only allow verbose messages if we know we're filtering by hotness
    196   /// (BFI is only set in this case).
    197   bool shouldEmitVerbose() { return MBFI != nullptr; }
    198 };
    199 
    200 /// The analysis pass
    201 ///
    202 /// Note that this pass shouldn't generally be marked as preserved by other
    203 /// passes.  It's holding onto BFI, so if the pass does not preserve BFI, BFI
    204 /// could be freed.
    205 class MachineOptimizationRemarkEmitterPass : public MachineFunctionPass {
    206   std::unique_ptr<MachineOptimizationRemarkEmitter> ORE;
    207 
    208 public:
    209   MachineOptimizationRemarkEmitterPass();
    210 
    211   bool runOnMachineFunction(MachineFunction &MF) override;
    212 
    213   void getAnalysisUsage(AnalysisUsage &AU) const override;
    214 
    215   MachineOptimizationRemarkEmitter &getORE() {
    216     assert(ORE && "pass not run yet");
    217     return *ORE;
    218   }
    219 
    220   static char ID;
    221 };
    222 }
    223 
    224 #endif
    225