LLVM 24.0.0git
MCSchedule.cpp
Go to the documentation of this file.
1//===- MCSchedule.cpp - Scheduling ------------------------------*- 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 the default scheduling model.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/MC/MCSchedule.h"
14#include "MCCLOptions.h"
15#include "llvm/ADT/APFloat.h"
16#include "llvm/ADT/APSInt.h"
17#include "llvm/MC/MCInst.h"
18#include "llvm/MC/MCInstrDesc.h"
19#include "llvm/MC/MCInstrInfo.h"
21#include <optional>
22#include <type_traits>
23
24using namespace llvm;
25
26static constexpr float DefaultReservationStationScaleFactor = 1.0f;
27
28static_assert(std::is_trivial_v<MCSchedModel>,
29 "MCSchedModel is required to be a trivial type");
30const MCSchedModel MCSchedModel::Default = {DefaultIssueWidth,
31 DefaultMicroOpBufferSize,
32 DefaultLoopMicroOpBufferSize,
33 DefaultLoadLatency,
34 DefaultHighLatency,
35 DefaultMispredictPenalty,
36 false,
37 true,
38 /*EnableIntervals=*/false,
39 0,
40 nullptr,
41 nullptr,
42 0,
43 0,
44 nullptr,
45 nullptr,
46 nullptr};
47
49 const MCSchedClassDesc &SCDesc) {
50 int Latency = 0;
51 for (unsigned DefIdx = 0, DefEnd = SCDesc.NumWriteLatencyEntries;
52 DefIdx != DefEnd; ++DefIdx) {
53 // Lookup the definition's write latency in SubtargetInfo.
54 const MCWriteLatencyEntry *WLEntry =
55 STI.getWriteLatencyEntry(&SCDesc, DefIdx);
56 // Early exit if we found an invalid latency.
57 if (WLEntry->Cycles < 0)
58 return WLEntry->Cycles;
59 Latency = std::max(Latency, static_cast<int>(WLEntry->Cycles));
60 }
61 return Latency;
62}
63
65 unsigned SchedClass) const {
66 const MCSchedClassDesc &SCDesc = *getSchedClassDesc(SchedClass);
67 if (!SCDesc.isValid())
68 return 0;
69 if (!SCDesc.isVariant())
70 return MCSchedModel::computeInstrLatency(STI, SCDesc);
71
72 llvm_unreachable("unsupported variant scheduling class");
73}
74
76 const MCInstrInfo &MCII,
77 const MCInst &Inst) const {
80 STI, MCII, Inst,
81 [&](const MCSchedClassDesc *SCDesc) -> const MCSchedClassDesc * {
82 if (!SCDesc->isValid())
83 return nullptr;
84
85 unsigned CPUID = getProcessorID();
86 unsigned SchedClass = 0;
87 while (SCDesc->isVariant()) {
88 SchedClass =
89 STI.resolveVariantSchedClass(SchedClass, &Inst, &MCII, CPUID);
90 SCDesc = getSchedClassDesc(SchedClass);
91 }
92
93 if (!SchedClass) {
94 assert(false && "unsupported variant scheduling class");
95 return nullptr;
96 }
97
98 return SCDesc;
99 });
100}
101
102double
104 const MCSchedClassDesc &SCDesc) {
105 std::optional<double> MinThroughput;
106 const MCSchedModel &SM = STI.getSchedModel();
107 const MCWriteProcResEntry *I = STI.getWriteProcResBegin(&SCDesc);
108 const MCWriteProcResEntry *E = STI.getWriteProcResEnd(&SCDesc);
109 for (; I != E; ++I) {
110 if (!I->ReleaseAtCycle || I->ReleaseAtCycle == I->AcquireAtCycle)
111 continue;
112 assert(I->ReleaseAtCycle > I->AcquireAtCycle && "invalid resource segment");
113 unsigned NumUnits = SM.getProcResource(I->ProcResourceIdx)->NumUnits;
114 double Throughput =
115 double(NumUnits) / double(I->ReleaseAtCycle - I->AcquireAtCycle);
116 MinThroughput =
117 MinThroughput ? std::min(*MinThroughput, Throughput) : Throughput;
118 }
119 if (MinThroughput)
120 return 1.0 / *MinThroughput;
121
122 // If no throughput value was calculated, assume that we can execute at the
123 // maximum issue width scaled by number of micro-ops for the schedule class.
124 return ((double)SCDesc.NumMicroOps) / SM.IssueWidth;
125}
126
127double
129 const MCInstrInfo &MCII,
130 const MCInst &Inst) const {
131 unsigned SchedClass = MCII.get(Inst.getOpcode()).getSchedClass();
132 const MCSchedClassDesc *SCDesc = getSchedClassDesc(SchedClass);
133
134 // If there's no valid class, assume that the instruction executes/completes
135 // at the maximum issue width.
136 if (!SCDesc->isValid())
137 return 1.0 / IssueWidth;
138
139 unsigned CPUID = getProcessorID();
140 while (SCDesc->isVariant()) {
141 SchedClass = STI.resolveVariantSchedClass(SchedClass, &Inst, &MCII, CPUID);
142 SCDesc = getSchedClassDesc(SchedClass);
143 }
144
145 if (SchedClass)
146 return MCSchedModel::getReciprocalThroughput(STI, *SCDesc);
147
148 llvm_unreachable("unsupported variant scheduling class");
149}
150
151double
153 const InstrItineraryData &IID) {
154 std::optional<double> Throughput;
155 const InstrStage *I = IID.beginStage(SchedClass);
156 const InstrStage *E = IID.endStage(SchedClass);
157 for (; I != E; ++I) {
158 if (!I->getCycles())
159 continue;
160 double Temp = llvm::popcount(I->getUnits()) * 1.0 / I->getCycles();
161 Throughput = Throughput ? std::min(*Throughput, Temp) : Temp;
162 }
163 if (Throughput)
164 return 1.0 / *Throughput;
165
166 // If there are no execution resources specified for this class, then assume
167 // that it can execute at the maximum default issue width.
168 return 1.0 / DefaultIssueWidth;
169}
170
171unsigned
173 unsigned WriteResourceID) {
174 if (Entries.empty())
175 return 0;
176
177 int DelayCycles = 0;
178 for (const MCReadAdvanceEntry &E : Entries) {
179 if (E.WriteResourceID != WriteResourceID)
180 continue;
181 DelayCycles = std::min(DelayCycles, E.Cycles);
182 }
183
184 return std::abs(DelayCycles);
185}
186
188 const MCSchedClassDesc &SCDesc) {
189
191 if (Entries.empty())
192 return 0;
193
194 unsigned MaxLatency = 0;
195 unsigned WriteResourceID = 0;
196 unsigned DefEnd = SCDesc.NumWriteLatencyEntries;
197
198 for (unsigned DefIdx = 0; DefIdx != DefEnd; ++DefIdx) {
199 // Lookup the definition's write latency in SubtargetInfo.
200 const MCWriteLatencyEntry *WLEntry =
201 STI.getWriteLatencyEntry(&SCDesc, DefIdx);
202 unsigned Cycles = 0;
203 // If latency is Invalid (<0), consider 0 cycle latency
204 if (WLEntry->Cycles > 0)
205 Cycles = (unsigned)WLEntry->Cycles;
206 if (Cycles > MaxLatency) {
207 MaxLatency = Cycles;
208 WriteResourceID = WLEntry->WriteResourceID;
209 }
210 }
211
212 for (const MCReadAdvanceEntry &E : Entries) {
213 if (E.WriteResourceID == WriteResourceID)
214 return E.Cycles;
215 }
216
217 // Unable to find WriteResourceID in MCReadAdvanceEntry Entries
218 return 0;
219}
220
221/// Return the buffer size of the resource. If a positive scale factor
222/// is provided and the original buffer size is > 1, the size is scaled
223/// accordingly.
225 unsigned ProcResourceIdx, float ReservationStationScaleFactor) const {
226 int BufferSize = getProcResource(ProcResourceIdx)->BufferSize;
227
228 // Skip scaling when factor is 1 (the default).
229 // Use native float comparison to avoid overhead on the hot fast
230 // path, as 1.0f is exactly representable
231 if (LLVM_LIKELY(ReservationStationScaleFactor ==
233 return BufferSize;
234
235 // Skip scaling for special buffer sizes (-1,0,1)
236 if (BufferSize <= 1)
237 return BufferSize;
238
239 // Skip invalid (non-positive) scale factors
240 APFloat Scale(ReservationStationScaleFactor);
241 if (Scale.isNegative() || Scale.isZero())
242 return BufferSize;
243
244 // Scale and truncate the positive computed size towards zero
245 APFloat Product(static_cast<float>(BufferSize));
246 Product.multiply(Scale, APFloat::rmTowardZero);
247 APSInt Result(32, /*IsUnsigned=*/false);
248 bool IsExact;
249 if (Product.convertToInteger(Result, APFloat::rmTowardZero, &IsExact) &
251 return BufferSize;
252 int Scaled = static_cast<int>(Result.getExtValue());
253
254 // Avoid producing special buffer sizes (-1,0,1)
255 if (Scaled <= 1)
256 return BufferSize;
257
258 return Scaled;
259}
260
262 const MCTargetOptions &Options) {
263 return getMCCLOptions(Options).sched_model_reservation_station_scale_factor;
264}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
@ Scaled
#define LLVM_LIKELY(EXPR)
Definition Compiler.h:347
static LVOptions Options
Definition LVOptions.cpp:25
static constexpr float DefaultReservationStationScaleFactor
#define I(x, y, z)
Definition MD5.cpp:57
static constexpr roundingMode rmTowardZero
Definition APFloat.h:365
bool isNegative() const
Definition APFloat.h:1583
opStatus multiply(const APFloat &RHS, roundingMode RM)
Definition APFloat.h:1303
bool isZero() const
Definition APFloat.h:1579
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const
Definition APFloat.h:1436
An arbitrary precision integer that knows its signedness.
Definition APSInt.h:24
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
const InstrStage * beginStage(unsigned ItinClassIndx) const
Return the first stage of the itinerary.
const InstrStage * endStage(unsigned ItinClassIndx) const
Return the last+1 stage of the itinerary.
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
unsigned getOpcode() const
Definition MCInst.h:202
unsigned getSchedClass() const
Return the scheduling class for this instruction.
Interface to description of machine instruction set.
Definition MCInstrInfo.h:27
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition MCInstrInfo.h:89
Generic base class for all target subtargets.
const MCWriteProcResEntry * getWriteProcResEnd(const MCSchedClassDesc *SC) const
virtual unsigned resolveVariantSchedClass(unsigned SchedClass, const MCInst *MI, const MCInstrInfo *MCII, unsigned CPUID) const
Resolve a variant scheduling class for the given MCInst and CPU.
ArrayRef< MCReadAdvanceEntry > getReadAdvanceEntries(const MCSchedClassDesc &SC) const
Return the set of ReadAdvance entries declared by the scheduling class descriptor in input.
const MCWriteLatencyEntry * getWriteLatencyEntry(const MCSchedClassDesc *SC, unsigned DefIdx) const
const MCWriteProcResEntry * getWriteProcResBegin(const MCSchedClassDesc *SC) const
Return an iterator at the first process resource consumed by the given scheduling class.
const MCSchedModel & getSchedModel() const
Get the machine model for this subtarget's CPU.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
const MCCLOptions & getMCCLOptions(const MCTargetOptions &Options)
Definition MCCLOptions.h:19
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:156
These values represent a non-pipelined step in the execution of an instruction.
Specify the number of cycles allowed after instruction issue before a particular use operand reads it...
Definition MCSchedule.h:109
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Definition MCSchedule.h:124
bool isVariant() const
Definition MCSchedule.h:145
Machine model for scheduling, bundling, and heuristics.
Definition MCSchedule.h:268
static LLVM_ABI const MCSchedModel Default
Returns the default initialized model.
Definition MCSchedule.h:444
static LLVM_ABI unsigned getForwardingDelayCycles(ArrayRef< MCReadAdvanceEntry > Entries, unsigned WriteResourceIdx=0)
Returns the maximum forwarding delay for register reads dependent on writes of scheduling class Write...
const MCSchedClassDesc * getSchedClassDesc(unsigned SchedClassIdx) const
Definition MCSchedule.h:376
unsigned getProcessorID() const
Definition MCSchedule.h:347
static constexpr unsigned DefaultIssueWidth
Definition MCSchedule.h:281
static LLVM_ABI int computeInstrLatency(const MCSubtargetInfo &STI, const MCSchedClassDesc &SCDesc)
Returns the latency value for the scheduling class.
friend class InstrItineraryData
Definition MCSchedule.h:340
static LLVM_ABI float getReservationStationScaleFactor(const MCTargetOptions &Options)
Returns the -sched-model-reservation-station-scale-factor value.
const MCProcResourceDesc * getProcResource(unsigned ProcResourceIdx) const
Definition MCSchedule.h:369
static LLVM_ABI unsigned getBypassDelayCycles(const MCSubtargetInfo &STI, const MCSchedClassDesc &SCDesc)
Returns the bypass delay cycle for the maximum latency write cycle.
LLVM_ABI int getResourceBufferSize(unsigned ProcResourceIdx, float ReservationStationScaleFactor) const
Return the buffer size of the resource.
static LLVM_ABI double getReciprocalThroughput(const MCSubtargetInfo &STI, const MCSchedClassDesc &SCDesc)
Specify the latency in cpu cycles for a particular scheduling class and def index.
Definition MCSchedule.h:92
Identify one of the processor resource kinds consumed by a particular scheduling class for the specif...
Definition MCSchedule.h:69