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"
22#include <optional>
23#include <type_traits>
24
25using namespace llvm;
26
27cl::OptionCategory llvm::MCScheduleOptions("Machine scheduling model options");
28
29static constexpr float DefaultReservationStationScaleFactor = 1.0f;
30
31static_assert(std::is_trivial_v<MCSchedModel>,
32 "MCSchedModel is required to be a trivial type");
33const MCSchedModel MCSchedModel::Default = {DefaultIssueWidth,
34 DefaultMicroOpBufferSize,
35 DefaultLoopMicroOpBufferSize,
36 DefaultLoadLatency,
37 DefaultHighLatency,
38 DefaultMispredictPenalty,
39 false,
40 true,
41 /*EnableIntervals=*/false,
42 0,
43 nullptr,
44 nullptr,
45 0,
46 0,
47 nullptr,
48 nullptr,
49 nullptr};
50
52 const MCSchedClassDesc &SCDesc) {
53 int Latency = 0;
54 for (unsigned DefIdx = 0, DefEnd = SCDesc.NumWriteLatencyEntries;
55 DefIdx != DefEnd; ++DefIdx) {
56 // Lookup the definition's write latency in SubtargetInfo.
57 const MCWriteLatencyEntry *WLEntry =
58 STI.getWriteLatencyEntry(&SCDesc, DefIdx);
59 // Early exit if we found an invalid latency.
60 if (WLEntry->Cycles < 0)
61 return WLEntry->Cycles;
62 Latency = std::max(Latency, static_cast<int>(WLEntry->Cycles));
63 }
64 return Latency;
65}
66
68 unsigned SchedClass) const {
69 const MCSchedClassDesc &SCDesc = *getSchedClassDesc(SchedClass);
70 if (!SCDesc.isValid())
71 return 0;
72 if (!SCDesc.isVariant())
73 return MCSchedModel::computeInstrLatency(STI, SCDesc);
74
75 llvm_unreachable("unsupported variant scheduling class");
76}
77
79 const MCInstrInfo &MCII,
80 const MCInst &Inst) const {
83 STI, MCII, Inst,
84 [&](const MCSchedClassDesc *SCDesc) -> const MCSchedClassDesc * {
85 if (!SCDesc->isValid())
86 return nullptr;
87
88 unsigned CPUID = getProcessorID();
89 unsigned SchedClass = 0;
90 while (SCDesc->isVariant()) {
91 SchedClass =
92 STI.resolveVariantSchedClass(SchedClass, &Inst, &MCII, CPUID);
93 SCDesc = getSchedClassDesc(SchedClass);
94 }
95
96 if (!SchedClass) {
97 assert(false && "unsupported variant scheduling class");
98 return nullptr;
99 }
100
101 return SCDesc;
102 });
103}
104
105double
107 const MCSchedClassDesc &SCDesc) {
108 std::optional<double> MinThroughput;
109 const MCSchedModel &SM = STI.getSchedModel();
110 const MCWriteProcResEntry *I = STI.getWriteProcResBegin(&SCDesc);
111 const MCWriteProcResEntry *E = STI.getWriteProcResEnd(&SCDesc);
112 for (; I != E; ++I) {
113 if (!I->ReleaseAtCycle || I->ReleaseAtCycle == I->AcquireAtCycle)
114 continue;
115 assert(I->ReleaseAtCycle > I->AcquireAtCycle && "invalid resource segment");
116 unsigned NumUnits = SM.getProcResource(I->ProcResourceIdx)->NumUnits;
117 double Throughput =
118 double(NumUnits) / double(I->ReleaseAtCycle - I->AcquireAtCycle);
119 MinThroughput =
120 MinThroughput ? std::min(*MinThroughput, Throughput) : Throughput;
121 }
122 if (MinThroughput)
123 return 1.0 / *MinThroughput;
124
125 // If no throughput value was calculated, assume that we can execute at the
126 // maximum issue width scaled by number of micro-ops for the schedule class.
127 return ((double)SCDesc.NumMicroOps) / SM.IssueWidth;
128}
129
130double
132 const MCInstrInfo &MCII,
133 const MCInst &Inst) const {
134 unsigned SchedClass = MCII.get(Inst.getOpcode()).getSchedClass();
135 const MCSchedClassDesc *SCDesc = getSchedClassDesc(SchedClass);
136
137 // If there's no valid class, assume that the instruction executes/completes
138 // at the maximum issue width.
139 if (!SCDesc->isValid())
140 return 1.0 / IssueWidth;
141
142 unsigned CPUID = getProcessorID();
143 while (SCDesc->isVariant()) {
144 SchedClass = STI.resolveVariantSchedClass(SchedClass, &Inst, &MCII, CPUID);
145 SCDesc = getSchedClassDesc(SchedClass);
146 }
147
148 if (SchedClass)
149 return MCSchedModel::getReciprocalThroughput(STI, *SCDesc);
150
151 llvm_unreachable("unsupported variant scheduling class");
152}
153
154double
156 const InstrItineraryData &IID) {
157 std::optional<double> Throughput;
158 const InstrStage *I = IID.beginStage(SchedClass);
159 const InstrStage *E = IID.endStage(SchedClass);
160 for (; I != E; ++I) {
161 if (!I->getCycles())
162 continue;
163 double Temp = llvm::popcount(I->getUnits()) * 1.0 / I->getCycles();
164 Throughput = Throughput ? std::min(*Throughput, Temp) : Temp;
165 }
166 if (Throughput)
167 return 1.0 / *Throughput;
168
169 // If there are no execution resources specified for this class, then assume
170 // that it can execute at the maximum default issue width.
171 return 1.0 / DefaultIssueWidth;
172}
173
174unsigned
176 unsigned WriteResourceID) {
177 if (Entries.empty())
178 return 0;
179
180 int DelayCycles = 0;
181 for (const MCReadAdvanceEntry &E : Entries) {
182 if (E.WriteResourceID != WriteResourceID)
183 continue;
184 DelayCycles = std::min(DelayCycles, E.Cycles);
185 }
186
187 return std::abs(DelayCycles);
188}
189
191 const MCSchedClassDesc &SCDesc) {
192
194 if (Entries.empty())
195 return 0;
196
197 unsigned MaxLatency = 0;
198 unsigned WriteResourceID = 0;
199 unsigned DefEnd = SCDesc.NumWriteLatencyEntries;
200
201 for (unsigned DefIdx = 0; DefIdx != DefEnd; ++DefIdx) {
202 // Lookup the definition's write latency in SubtargetInfo.
203 const MCWriteLatencyEntry *WLEntry =
204 STI.getWriteLatencyEntry(&SCDesc, DefIdx);
205 unsigned Cycles = 0;
206 // If latency is Invalid (<0), consider 0 cycle latency
207 if (WLEntry->Cycles > 0)
208 Cycles = (unsigned)WLEntry->Cycles;
209 if (Cycles > MaxLatency) {
210 MaxLatency = Cycles;
211 WriteResourceID = WLEntry->WriteResourceID;
212 }
213 }
214
215 for (const MCReadAdvanceEntry &E : Entries) {
216 if (E.WriteResourceID == WriteResourceID)
217 return E.Cycles;
218 }
219
220 // Unable to find WriteResourceID in MCReadAdvanceEntry Entries
221 return 0;
222}
223
224/// Return the buffer size of the resource. If a positive scale factor
225/// is provided and the original buffer size is > 1, the size is scaled
226/// accordingly.
228 unsigned ProcResourceIdx, float ReservationStationScaleFactor) const {
229 int BufferSize = getProcResource(ProcResourceIdx)->BufferSize;
230
231 // Skip scaling when factor is 1 (the default).
232 // Use native float comparison to avoid overhead on the hot fast
233 // path, as 1.0f is exactly representable
234 if (LLVM_LIKELY(ReservationStationScaleFactor ==
236 return BufferSize;
237
238 // Skip scaling for special buffer sizes (-1,0,1)
239 if (BufferSize <= 1)
240 return BufferSize;
241
242 // Skip invalid (non-positive) scale factors
243 APFloat Scale(ReservationStationScaleFactor);
244 if (Scale.isNegative() || Scale.isZero())
245 return BufferSize;
246
247 // Scale and truncate the positive computed size towards zero
248 APFloat Product(static_cast<float>(BufferSize));
249 Product.multiply(Scale, APFloat::rmTowardZero);
250 APSInt Result(32, /*IsUnsigned=*/false);
251 bool IsExact;
252 if (Product.convertToInteger(Result, APFloat::rmTowardZero, &IsExact) &
254 return BufferSize;
255 int Scaled = static_cast<int>(Result.getExtValue());
256
257 // Avoid producing special buffer sizes (-1,0,1)
258 if (Scaled <= 1)
259 return BufferSize;
260
261 return Scaled;
262}
263
265 const MCTargetOptions &Options) {
266 return getMCCLOptions(Options).sched_model_reservation_station_scale_factor;
267}
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:351
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
LLVM_ABI cl::OptionCategory MCScheduleOptions
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:115
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Definition MCSchedule.h:130
bool isVariant() const
Definition MCSchedule.h:151
Machine model for scheduling, bundling, and heuristics.
Definition MCSchedule.h:274
static LLVM_ABI const MCSchedModel Default
Returns the default initialized model.
Definition MCSchedule.h:450
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:382
unsigned getProcessorID() const
Definition MCSchedule.h:353
static constexpr unsigned DefaultIssueWidth
Definition MCSchedule.h:287
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:346
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:375
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:98
Identify one of the processor resource kinds consumed by a particular scheduling class for the specif...
Definition MCSchedule.h:75