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.
227int MCSchedModel::getResourceBufferSize(unsigned ProcResourceIdx) const {
228 int BufferSize = getProcResource(ProcResourceIdx)->BufferSize;
229
230 float ReservationStationScaleFactor =
231 MCCLOptions::Global.sched_model_reservation_station_scale_factor;
232 // Skip scaling when factor is 1 (the default).
233 // Use native float comparison to avoid overhead on the hot fast
234 // path, as 1.0f is exactly representable
235 if (LLVM_LIKELY(ReservationStationScaleFactor ==
237 return BufferSize;
238
239 // Skip scaling for special buffer sizes (-1,0,1)
240 if (BufferSize <= 1)
241 return BufferSize;
242
243 // Skip invalid (non-positive) scale factors
244 APFloat Scale(ReservationStationScaleFactor);
245 if (Scale.isNegative() || Scale.isZero())
246 return BufferSize;
247
248 // Scale and truncate the positive computed size towards zero
249 APFloat Product(static_cast<float>(BufferSize));
250 Product.multiply(Scale, APFloat::rmTowardZero);
251 APSInt Result(32, /*IsUnsigned=*/false);
252 bool IsExact;
253 if (Product.convertToInteger(Result, APFloat::rmTowardZero, &IsExact) &
255 return BufferSize;
256 int Scaled = static_cast<int>(Result.getExtValue());
257
258 // Avoid producing special buffer sizes (-1,0,1)
259 if (Scaled <= 1)
260 return BufferSize;
261
262 return Scaled;
263}
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 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.
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:114
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Definition MCSchedule.h:129
bool isVariant() const
Definition MCSchedule.h:150
Machine model for scheduling, bundling, and heuristics.
Definition MCSchedule.h:273
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:381
unsigned getProcessorID() const
Definition MCSchedule.h:352
static constexpr unsigned DefaultIssueWidth
Definition MCSchedule.h:286
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:345
const MCProcResourceDesc * getProcResource(unsigned ProcResourceIdx) const
Definition MCSchedule.h:374
static LLVM_ABI unsigned getBypassDelayCycles(const MCSubtargetInfo &STI, const MCSchedClassDesc &SCDesc)
Returns the bypass delay cycle for the maximum latency write cycle.
static LLVM_ABI double getReciprocalThroughput(const MCSubtargetInfo &STI, const MCSchedClassDesc &SCDesc)
LLVM_ABI int getResourceBufferSize(unsigned ProcResourceIdx) const
Return the buffer size of the resource.
Specify the latency in cpu cycles for a particular scheduling class and def index.
Definition MCSchedule.h:97
Identify one of the processor resource kinds consumed by a particular scheduling class for the specif...
Definition MCSchedule.h:74