LLVM 22.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 "llvm/MC/MCInst.h"
15#include "llvm/MC/MCInstrDesc.h"
16#include "llvm/MC/MCInstrInfo.h"
18#include <optional>
19#include <type_traits>
20
21using namespace llvm;
22
23static_assert(std::is_trivial_v<MCSchedModel>,
24 "MCSchedModel is required to be a trivial type");
25const MCSchedModel MCSchedModel::Default = {DefaultIssueWidth,
26 DefaultMicroOpBufferSize,
27 DefaultLoopMicroOpBufferSize,
28 DefaultLoadLatency,
29 DefaultHighLatency,
30 DefaultMispredictPenalty,
31 false,
32 true,
33 /*EnableIntervals=*/false,
34 0,
35 nullptr,
36 nullptr,
37 0,
38 0,
39 nullptr,
40 nullptr,
41 nullptr};
42
44 const MCSchedClassDesc &SCDesc) {
45 int Latency = 0;
46 for (unsigned DefIdx = 0, DefEnd = SCDesc.NumWriteLatencyEntries;
47 DefIdx != DefEnd; ++DefIdx) {
48 // Lookup the definition's write latency in SubtargetInfo.
49 const MCWriteLatencyEntry *WLEntry =
50 STI.getWriteLatencyEntry(&SCDesc, DefIdx);
51 // Early exit if we found an invalid latency.
52 if (WLEntry->Cycles < 0)
53 return WLEntry->Cycles;
54 Latency = std::max(Latency, static_cast<int>(WLEntry->Cycles));
55 }
56 return Latency;
57}
58
60 unsigned SchedClass) const {
61 const MCSchedClassDesc &SCDesc = *getSchedClassDesc(SchedClass);
62 if (!SCDesc.isValid())
63 return 0;
64 if (!SCDesc.isVariant())
65 return MCSchedModel::computeInstrLatency(STI, SCDesc);
66
67 llvm_unreachable("unsupported variant scheduling class");
68}
69
71 const MCInstrInfo &MCII,
72 const MCInst &Inst) const {
75 STI, MCII, Inst,
76 [&](const MCSchedClassDesc *SCDesc) -> const MCSchedClassDesc * {
77 if (!SCDesc->isValid())
78 return nullptr;
79
80 unsigned CPUID = getProcessorID();
81 unsigned SchedClass = 0;
82 while (SCDesc->isVariant()) {
83 SchedClass =
84 STI.resolveVariantSchedClass(SchedClass, &Inst, &MCII, CPUID);
85 SCDesc = getSchedClassDesc(SchedClass);
86 }
87
88 if (!SchedClass) {
89 assert(false && "unsupported variant scheduling class");
90 return nullptr;
91 }
92
93 return SCDesc;
94 });
95}
96
97double
99 const MCSchedClassDesc &SCDesc) {
100 std::optional<double> MinThroughput;
101 const MCSchedModel &SM = STI.getSchedModel();
102 const MCWriteProcResEntry *I = STI.getWriteProcResBegin(&SCDesc);
103 const MCWriteProcResEntry *E = STI.getWriteProcResEnd(&SCDesc);
104 for (; I != E; ++I) {
105 if (!I->ReleaseAtCycle || I->ReleaseAtCycle == I->AcquireAtCycle)
106 continue;
107 assert(I->ReleaseAtCycle > I->AcquireAtCycle && "invalid resource segment");
108 unsigned NumUnits = SM.getProcResource(I->ProcResourceIdx)->NumUnits;
109 double Throughput =
110 double(NumUnits) / double(I->ReleaseAtCycle - I->AcquireAtCycle);
111 MinThroughput =
112 MinThroughput ? std::min(*MinThroughput, Throughput) : Throughput;
113 }
114 if (MinThroughput)
115 return 1.0 / *MinThroughput;
116
117 // If no throughput value was calculated, assume that we can execute at the
118 // maximum issue width scaled by number of micro-ops for the schedule class.
119 return ((double)SCDesc.NumMicroOps) / SM.IssueWidth;
120}
121
122double
124 const MCInstrInfo &MCII,
125 const MCInst &Inst) const {
126 unsigned SchedClass = MCII.get(Inst.getOpcode()).getSchedClass();
127 const MCSchedClassDesc *SCDesc = getSchedClassDesc(SchedClass);
128
129 // If there's no valid class, assume that the instruction executes/completes
130 // at the maximum issue width.
131 if (!SCDesc->isValid())
132 return 1.0 / IssueWidth;
133
134 unsigned CPUID = getProcessorID();
135 while (SCDesc->isVariant()) {
136 SchedClass = STI.resolveVariantSchedClass(SchedClass, &Inst, &MCII, CPUID);
137 SCDesc = getSchedClassDesc(SchedClass);
138 }
139
140 if (SchedClass)
141 return MCSchedModel::getReciprocalThroughput(STI, *SCDesc);
142
143 llvm_unreachable("unsupported variant scheduling class");
144}
145
146double
148 const InstrItineraryData &IID) {
149 std::optional<double> Throughput;
150 const InstrStage *I = IID.beginStage(SchedClass);
151 const InstrStage *E = IID.endStage(SchedClass);
152 for (; I != E; ++I) {
153 if (!I->getCycles())
154 continue;
155 double Temp = llvm::popcount(I->getUnits()) * 1.0 / I->getCycles();
156 Throughput = Throughput ? std::min(*Throughput, Temp) : Temp;
157 }
158 if (Throughput)
159 return 1.0 / *Throughput;
160
161 // If there are no execution resources specified for this class, then assume
162 // that it can execute at the maximum default issue width.
163 return 1.0 / DefaultIssueWidth;
164}
165
166unsigned
168 unsigned WriteResourceID) {
169 if (Entries.empty())
170 return 0;
171
172 int DelayCycles = 0;
173 for (const MCReadAdvanceEntry &E : Entries) {
174 if (E.WriteResourceID != WriteResourceID)
175 continue;
176 DelayCycles = std::min(DelayCycles, E.Cycles);
177 }
178
179 return std::abs(DelayCycles);
180}
181
183 const MCSchedClassDesc &SCDesc) {
184
186 if (Entries.empty())
187 return 0;
188
189 unsigned MaxLatency = 0;
190 unsigned WriteResourceID = 0;
191 unsigned DefEnd = SCDesc.NumWriteLatencyEntries;
192
193 for (unsigned DefIdx = 0; DefIdx != DefEnd; ++DefIdx) {
194 // Lookup the definition's write latency in SubtargetInfo.
195 const MCWriteLatencyEntry *WLEntry =
196 STI.getWriteLatencyEntry(&SCDesc, DefIdx);
197 unsigned Cycles = 0;
198 // If latency is Invalid (<0), consider 0 cycle latency
199 if (WLEntry->Cycles > 0)
200 Cycles = (unsigned)WLEntry->Cycles;
201 if (Cycles > MaxLatency) {
202 MaxLatency = Cycles;
203 WriteResourceID = WLEntry->WriteResourceID;
204 }
205 }
206
207 for (const MCReadAdvanceEntry &E : Entries) {
208 if (E.WriteResourceID == WriteResourceID)
209 return E.Cycles;
210 }
211
212 // Unable to find WriteResourceID in MCReadAdvanceEntry Entries
213 return 0;
214}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define I(x, y, z)
Definition MD5.cpp:58
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
bool empty() const
empty - Check if the array is empty.
Definition ArrayRef.h:142
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:64
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.
int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:307
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:108
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Definition MCSchedule.h:123
bool isVariant() const
Definition MCSchedule.h:144
uint16_t NumWriteLatencyEntries
Definition MCSchedule.h:137
Machine model for scheduling, bundling, and heuristics.
Definition MCSchedule.h:258
static LLVM_ABI const MCSchedModel Default
Returns the default initialized model.
Definition MCSchedule.h:424
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:366
unsigned getProcessorID() const
Definition MCSchedule.h:337
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:330
const MCProcResourceDesc * getProcResource(unsigned ProcResourceIdx) const
Definition MCSchedule.h:359
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)
static const unsigned DefaultIssueWidth
Definition MCSchedule.h:271
Specify the latency in cpu cycles for a particular scheduling class and def index.
Definition MCSchedule.h:91
Identify one of the processor resource kinds consumed by a particular scheduling class for the specif...
Definition MCSchedule.h:68