Home | History | Annotate | Line # | Download | only in CodeGen
      1 //===- llvm/CodeGen/TargetSchedule.h - Sched Machine Model ------*- 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 //
      9 // This file defines a wrapper around MCSchedModel that allows the interface to
     10 // benefit from information currently only available in TargetInstrInfo.
     11 // Ideally, the scheduling interface would be fully defined in the MC layer.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef LLVM_CODEGEN_TARGETSCHEDULE_H
     16 #define LLVM_CODEGEN_TARGETSCHEDULE_H
     17 
     18 #include "llvm/ADT/Optional.h"
     19 #include "llvm/ADT/SmallVector.h"
     20 #include "llvm/CodeGen/TargetSubtargetInfo.h"
     21 #include "llvm/Config/llvm-config.h"
     22 #include "llvm/MC/MCInstrItineraries.h"
     23 #include "llvm/MC/MCSchedule.h"
     24 
     25 namespace llvm {
     26 
     27 class MachineInstr;
     28 class TargetInstrInfo;
     29 
     30 /// Provide an instruction scheduling machine model to CodeGen passes.
     31 class TargetSchedModel {
     32   // For efficiency, hold a copy of the statically defined MCSchedModel for this
     33   // processor.
     34   MCSchedModel SchedModel;
     35   InstrItineraryData InstrItins;
     36   const TargetSubtargetInfo *STI = nullptr;
     37   const TargetInstrInfo *TII = nullptr;
     38 
     39   SmallVector<unsigned, 16> ResourceFactors;
     40 
     41   // Multiply to normalize microops to resource units.
     42   unsigned MicroOpFactor = 0;
     43 
     44   // Resource units per cycle. Latency normalization factor.
     45   unsigned ResourceLCM = 0;
     46 
     47   unsigned computeInstrLatency(const MCSchedClassDesc &SCDesc) const;
     48 
     49 public:
     50   TargetSchedModel() : SchedModel(MCSchedModel::GetDefaultSchedModel()) {}
     51 
     52   /// Initialize the machine model for instruction scheduling.
     53   ///
     54   /// The machine model API keeps a copy of the top-level MCSchedModel table
     55   /// indices and may query TargetSubtargetInfo and TargetInstrInfo to resolve
     56   /// dynamic properties.
     57   void init(const TargetSubtargetInfo *TSInfo);
     58 
     59   /// Return the MCSchedClassDesc for this instruction.
     60   const MCSchedClassDesc *resolveSchedClass(const MachineInstr *MI) const;
     61 
     62   /// TargetSubtargetInfo getter.
     63   const TargetSubtargetInfo *getSubtargetInfo() const { return STI; }
     64 
     65   /// TargetInstrInfo getter.
     66   const TargetInstrInfo *getInstrInfo() const { return TII; }
     67 
     68   /// Return true if this machine model includes an instruction-level
     69   /// scheduling model.
     70   ///
     71   /// This is more detailed than the course grain IssueWidth and default
     72   /// latency properties, but separate from the per-cycle itinerary data.
     73   bool hasInstrSchedModel() const;
     74 
     75   const MCSchedModel *getMCSchedModel() const { return &SchedModel; }
     76 
     77   /// Return true if this machine model includes cycle-to-cycle itinerary
     78   /// data.
     79   ///
     80   /// This models scheduling at each stage in the processor pipeline.
     81   bool hasInstrItineraries() const;
     82 
     83   const InstrItineraryData *getInstrItineraries() const {
     84     if (hasInstrItineraries())
     85       return &InstrItins;
     86     return nullptr;
     87   }
     88 
     89   /// Return true if this machine model includes an instruction-level
     90   /// scheduling model or cycle-to-cycle itinerary data.
     91   bool hasInstrSchedModelOrItineraries() const {
     92     return hasInstrSchedModel() || hasInstrItineraries();
     93   }
     94 
     95   /// Identify the processor corresponding to the current subtarget.
     96   unsigned getProcessorID() const { return SchedModel.getProcessorID(); }
     97 
     98   /// Maximum number of micro-ops that may be scheduled per cycle.
     99   unsigned getIssueWidth() const { return SchedModel.IssueWidth; }
    100 
    101   /// Return true if new group must begin.
    102   bool mustBeginGroup(const MachineInstr *MI,
    103                           const MCSchedClassDesc *SC = nullptr) const;
    104   /// Return true if current group must end.
    105   bool mustEndGroup(const MachineInstr *MI,
    106                           const MCSchedClassDesc *SC = nullptr) const;
    107 
    108   /// Return the number of issue slots required for this MI.
    109   unsigned getNumMicroOps(const MachineInstr *MI,
    110                           const MCSchedClassDesc *SC = nullptr) const;
    111 
    112   /// Get the number of kinds of resources for this target.
    113   unsigned getNumProcResourceKinds() const {
    114     return SchedModel.getNumProcResourceKinds();
    115   }
    116 
    117   /// Get a processor resource by ID for convenience.
    118   const MCProcResourceDesc *getProcResource(unsigned PIdx) const {
    119     return SchedModel.getProcResource(PIdx);
    120   }
    121 
    122 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
    123   const char *getResourceName(unsigned PIdx) const {
    124     if (!PIdx)
    125       return "MOps";
    126     return SchedModel.getProcResource(PIdx)->Name;
    127   }
    128 #endif
    129 
    130   using ProcResIter = const MCWriteProcResEntry *;
    131 
    132   // Get an iterator into the processor resources consumed by this
    133   // scheduling class.
    134   ProcResIter getWriteProcResBegin(const MCSchedClassDesc *SC) const {
    135     // The subtarget holds a single resource table for all processors.
    136     return STI->getWriteProcResBegin(SC);
    137   }
    138   ProcResIter getWriteProcResEnd(const MCSchedClassDesc *SC) const {
    139     return STI->getWriteProcResEnd(SC);
    140   }
    141 
    142   /// Multiply the number of units consumed for a resource by this factor
    143   /// to normalize it relative to other resources.
    144   unsigned getResourceFactor(unsigned ResIdx) const {
    145     return ResourceFactors[ResIdx];
    146   }
    147 
    148   /// Multiply number of micro-ops by this factor to normalize it
    149   /// relative to other resources.
    150   unsigned getMicroOpFactor() const {
    151     return MicroOpFactor;
    152   }
    153 
    154   /// Multiply cycle count by this factor to normalize it relative to
    155   /// other resources. This is the number of resource units per cycle.
    156   unsigned getLatencyFactor() const {
    157     return ResourceLCM;
    158   }
    159 
    160   /// Number of micro-ops that may be buffered for OOO execution.
    161   unsigned getMicroOpBufferSize() const { return SchedModel.MicroOpBufferSize; }
    162 
    163   /// Number of resource units that may be buffered for OOO execution.
    164   /// \return The buffer size in resource units or -1 for unlimited.
    165   int getResourceBufferSize(unsigned PIdx) const {
    166     return SchedModel.getProcResource(PIdx)->BufferSize;
    167   }
    168 
    169   /// Compute operand latency based on the available machine model.
    170   ///
    171   /// Compute and return the latency of the given data dependent def and use
    172   /// when the operand indices are already known. UseMI may be NULL for an
    173   /// unknown user.
    174   unsigned computeOperandLatency(const MachineInstr *DefMI, unsigned DefOperIdx,
    175                                  const MachineInstr *UseMI, unsigned UseOperIdx)
    176     const;
    177 
    178   /// Compute the instruction latency based on the available machine
    179   /// model.
    180   ///
    181   /// Compute and return the expected latency of this instruction independent of
    182   /// a particular use. computeOperandLatency is the preferred API, but this is
    183   /// occasionally useful to help estimate instruction cost.
    184   ///
    185   /// If UseDefaultDefLatency is false and no new machine sched model is
    186   /// present this method falls back to TII->getInstrLatency with an empty
    187   /// instruction itinerary (this is so we preserve the previous behavior of the
    188   /// if converter after moving it to TargetSchedModel).
    189   unsigned computeInstrLatency(const MachineInstr *MI,
    190                                bool UseDefaultDefLatency = true) const;
    191   unsigned computeInstrLatency(const MCInst &Inst) const;
    192   unsigned computeInstrLatency(unsigned Opcode) const;
    193 
    194 
    195   /// Output dependency latency of a pair of defs of the same register.
    196   ///
    197   /// This is typically one cycle.
    198   unsigned computeOutputLatency(const MachineInstr *DefMI, unsigned DefOperIdx,
    199                                 const MachineInstr *DepMI) const;
    200 
    201   /// Compute the reciprocal throughput of the given instruction.
    202   double computeReciprocalThroughput(const MachineInstr *MI) const;
    203   double computeReciprocalThroughput(const MCInst &MI) const;
    204   double computeReciprocalThroughput(unsigned Opcode) const;
    205 };
    206 
    207 } // end namespace llvm
    208 
    209 #endif // LLVM_CODEGEN_TARGETSCHEDULE_H
    210