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: TargetSchedModel()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. getSubtargetInfo()63 const TargetSubtargetInfo *getSubtargetInfo() const { return STI; } 64 65 /// TargetInstrInfo getter. getInstrInfo()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 getMCSchedModel()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 getInstrItineraries()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. hasInstrSchedModelOrItineraries()91 bool hasInstrSchedModelOrItineraries() const { 92 return hasInstrSchedModel() || hasInstrItineraries(); 93 } 94 95 /// Identify the processor corresponding to the current subtarget. getProcessorID()96 unsigned getProcessorID() const { return SchedModel.getProcessorID(); } 97 98 /// Maximum number of micro-ops that may be scheduled per cycle. getIssueWidth()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. getNumProcResourceKinds()113 unsigned getNumProcResourceKinds() const { 114 return SchedModel.getNumProcResourceKinds(); 115 } 116 117 /// Get a processor resource by ID for convenience. getProcResource(unsigned PIdx)118 const MCProcResourceDesc *getProcResource(unsigned PIdx) const { 119 return SchedModel.getProcResource(PIdx); 120 } 121 122 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) getResourceName(unsigned PIdx)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. getWriteProcResBegin(const MCSchedClassDesc * SC)134 ProcResIter getWriteProcResBegin(const MCSchedClassDesc *SC) const { 135 // The subtarget holds a single resource table for all processors. 136 return STI->getWriteProcResBegin(SC); 137 } getWriteProcResEnd(const MCSchedClassDesc * SC)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. getResourceFactor(unsigned ResIdx)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. getMicroOpFactor()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. getLatencyFactor()156 unsigned getLatencyFactor() const { 157 return ResourceLCM; 158 } 159 160 /// Number of micro-ops that may be buffered for OOO execution. getMicroOpBufferSize()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. getResourceBufferSize(unsigned PIdx)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