TargetSchedule.h 7.7 KB

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