LLVM 24.0.0git
AMDGPUCoExecSchedStrategy.h
Go to the documentation of this file.
1//===- AMDGPUCoExecSchedStrategy.h - CoExec Scheduling Strategy -*- 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/// \file
10/// Coexecution-focused scheduling strategy for AMDGPU.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPUCOEXECSCHEDSTRATEGY_H
15#define LLVM_LIB_TARGET_AMDGPU_AMDGPUCOEXECSCHEDSTRATEGY_H
16
17#include "AMDGPUCoExecInfo.h"
18#include "GCNSchedStrategy.h"
20
21namespace llvm {
22
23namespace AMDGPU {
24
25/// AMDGPU-specific scheduling decision reasons. These provide more granularity
26/// than the generic CandReason enum for debugging purposes.
29 CritResourceBalance, // tryCriticalResource chose based on resource pressure
30 CritResourceDep, // tryCriticalResourceDependency chose based on enabling
32};
33
35 switch (R) {
37 return "None";
39 return "CritResource";
41 return "CritResourceDep";
43 llvm_unreachable("Unknown AMDGPUSchedReason");
44 }
45 llvm_unreachable("Unknown AMDGPUSchedReason");
46}
47
48} // End namespace AMDGPU
49
50//===----------------------------------------------------------------------===//
51// Hardware Unit Information
52//===----------------------------------------------------------------------===//
53
54/// HardwareUnitInfo is a wrapper class which maps to some real hardware
55/// resource. This is used to model hardware resource pressure per region, and
56/// guide scheduling heuristics.
58private:
59 /// PrioritySUs maintains a list of the SUs we want to prioritize scheduling
60 /// for this HardwareUnit. This is used for agreement between
61 /// tryCriticalResourceDependency and tryCriticalResource: we schedule the
62 /// dependencies for a SU on critical resource, then schedule that same SU on
63 /// the critical resource. This agreement results in shorter live ranges and
64 /// more regular HardwareUnit access patterns. SUs are prioritized based on
65 /// depth for top-down scheduling.
67 /// All the SUs in the region that consume this resource.
69 /// The total number of busy cycles for this HardwareUnit for a given region.
70 unsigned TotalCycles = 0;
71 /// InstructionFlavor mapping.
73 /// Whether or not instructions on this HardwareUnit may produce a window in
74 /// which instructions in other HardwareUnits can coexecute. For example, WMMA
75 /// / MFMA instructions may take multiple cycles, which may be overlapped with
76 /// instructions on other HardwareUnits.
77 bool ProducesCoexecWindow = false;
78
79public:
81
82 unsigned size() { return AllSUs.size(); }
83
84 unsigned getTotalCycles() { return TotalCycles; }
85
86 void setType(unsigned TheType) {
88 Type = (AMDGPU::InstructionFlavor)(TheType);
89 }
90
91 AMDGPU::InstructionFlavor getType() const { return Type; }
92
93 bool producesCoexecWindow() const { return ProducesCoexecWindow; }
94
95 void setProducesCoexecWindow(bool Val) { ProducesCoexecWindow = Val; }
96
97 bool contains(SUnit *SU) const { return AllSUs.contains(SU); }
98
99 /// \returns the SUnit with higher priority or nullptr if they are the same.
100 /// This method looks through the PrioritySUs to determine if one SU is more
101 /// prioritized than the other. If neither are in the PrioritySUs list, then
102 /// neither have priority over each other.
104 for (SUnit *SUOrder : PrioritySUs) {
105 if (SUOrder == SU)
106 return SU;
107
108 if (SUOrder == Other)
109 return Other;
110 }
111 return nullptr;
112 }
113
114 void reset() {
115 AllSUs.clear();
116 PrioritySUs.clear();
117 TotalCycles = 0;
119 ProducesCoexecWindow = false;
120 }
121
122 /// \returns the next SU in PrioritySUs that is not ready. If \p LookDeep is
123 /// set, we will look beyond the PrioritySUs (if all the PrioritySUs are
124 /// ready) to AllSUs to attempt to find a target SU. When looking through
125 /// AllSUs we sort pick the target SU by minimal depth for top-down
126 /// scheduling. getNextTargetSU is useful for determining which SU on this
127 /// HardwareUnit we are trying to schedule - this info helps us determine
128 /// which dependencies to schedule. LookDeep is useful if the dependencies are
129 /// long latency (e.g. memory instructions). If we have many long latency
130 /// dependencies, it is beneficial to enable SUs multiple levels ahead.
131 SUnit *getNextTargetSU(bool LookDeep = false) const;
132 /// Insert the \p SU into AllSUs and account its \p BlockingCycles into
133 /// the TotalCycles. This maintains the list of PrioritySUs.
134 void insert(SUnit *SU, unsigned BlockingCycles);
135 /// Update the state for \p SU being scheduled by removing it from the AllSUs
136 /// and reducing its \p BlockingCycles from the TotalCycles. This maintains
137 /// the list of PrioritySUs.
138 void markScheduled(SUnit *SU, unsigned BlockingCycles);
139};
140
141//===----------------------------------------------------------------------===//
142// Candidate Heuristics
143//===----------------------------------------------------------------------===//
144
145/// CandidateHeuristics contains state and implementations to facilitate making
146/// per instruction scheduling decisions; it contains methods used in
147/// tryCandidate to decide which instruction to schedule next.
149protected:
155
156 /// Walk over the region and collect total usage per HardwareUnit.
157 void collectHWUIPressure();
158
159 /// Compute the blocking cycles for the appropriate HardwareUnit given an \p
160 /// SU.
161 unsigned getHWUICyclesForInst(SUnit *SU);
162
163 /// Given a \p Flavor , find the corresponding HardwareUnit. \returns the
164 /// mapped HardwareUnit.
166
167public:
169
171 const TargetRegisterInfo *TRI);
172
173 /// Update the state to reflect that \p SU is going to be scheduled.
174 void updateForScheduling(SUnit *SU);
175
176 /// Sort the HWUInfo vector. After sorting, the HardwareUnits that are highest
177 /// priority are first. Priority is determined by maximizing coexecution and
178 /// keeping the critical HardwareUnit busy.
179 void sortHWUIResources();
180
181 /// Check for critical resource consumption. Prefer the candidate that uses
182 /// the most prioritized HardwareUnit. If both candidates use the same
183 /// HarwareUnit, prefer the candidate with higher priority on that
184 /// HardwareUnit.
187 SchedBoundary *Zone) const;
188
189 /// Check for dependencies of instructions that use prioritized HardwareUnits.
190 /// Prefer the candidate that is a dependency of an instruction that uses the
191 /// most prioritized HardwareUnit. If both candidates enable the same
192 /// HardwareUnit, prefer the candidate that enables the higher priority
193 /// instruction on that HardwareUnit.
194 bool
197 SchedBoundary *Zone) const;
198
199 void dumpRegionSummary();
200};
201
203protected:
205 SchedBoundary &Zone) const;
208
209#ifndef NDEBUG
210 void dumpPickSummary(SUnit *SU, bool IsTopNode, SchedCandidate &Cand);
211#endif
212
214 SchedBoundary *Zone);
215 void pickNodeFromQueue(SchedBoundary &Zone, const CandPolicy &ZonePolicy,
216 const RegPressureTracker &RPTracker,
217 SchedCandidate &Cand, bool &PickedPending,
218 bool IsBottomUp);
219
220public:
222
225 unsigned NumRegionInstrs) override;
226 void initialize(ScheduleDAGMI *DAG) override;
227 SUnit *pickNode(bool &IsTopNode) override;
228 void schedNode(SUnit *SU, bool IsTopNode) override;
229};
230
233
234} // End namespace llvm
235
236#endif // LLVM_LIB_TARGET_AMDGPU_AMDGPUCOEXECSCHEDSTRATEGY_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Shared types for co-execution modeling used by GCNHazardRecognizer and the schedulers.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
Register const TargetRegisterInfo * TRI
bool tryEffectiveStall(SchedCandidate &Cand, SchedCandidate &TryCand, SchedBoundary &Zone) const
void initPolicy(MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, unsigned NumRegionInstrs) override
Optionally override the per-region scheduling policy.
SUnit * pickNode(bool &IsTopNode) override
Pick the next node to schedule, or return NULL.
void pickNodeFromQueue(SchedBoundary &Zone, const CandPolicy &ZonePolicy, const RegPressureTracker &RPTracker, SchedCandidate &Cand, bool &PickedPending, bool IsBottomUp)
void initialize(ScheduleDAGMI *DAG) override
Initialize the strategy after building the DAG for a new region.
void schedNode(SUnit *SU, bool IsTopNode) override
Notify MachineSchedStrategy that ScheduleDAGMI has scheduled an instruction and updated scheduled/rem...
AMDGPUCoExecSchedStrategy(const MachineSchedContext *C)
void dumpPickSummary(SUnit *SU, bool IsTopNode, SchedCandidate &Cand)
bool tryCandidateCoexec(SchedCandidate &Cand, SchedCandidate &TryCand, SchedBoundary *Zone)
CandidateHeuristics contains state and implementations to facilitate making per instruction schedulin...
void updateForScheduling(SUnit *SU)
Update the state to reflect that SU is going to be scheduled.
HardwareUnitInfo * getHWUIFromFlavor(AMDGPU::InstructionFlavor Flavor)
Given a Flavor , find the corresponding HardwareUnit.
void sortHWUIResources()
Sort the HWUInfo vector.
bool tryCriticalResource(GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, SchedBoundary *Zone) const
Check for critical resource consumption.
bool tryCriticalResourceDependency(GenericSchedulerBase::SchedCandidate &TryCand, GenericSchedulerBase::SchedCandidate &Cand, SchedBoundary *Zone) const
Check for dependencies of instructions that use prioritized HardwareUnits.
SmallVector< HardwareUnitInfo, 8 > HWUInfo
const TargetSchedModel * SchedModel
void collectHWUIPressure()
Walk over the region and collect total usage per HardwareUnit.
void initialize(ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel, const TargetRegisterInfo *TRI)
unsigned getHWUICyclesForInst(SUnit *SU)
Compute the blocking cycles for the appropriate HardwareUnit given an SU.
GCNSchedStrategy(const MachineSchedContext *C)
ScheduleDAGMILive * DAG
HardwareUnitInfo is a wrapper class which maps to some real hardware resource.
void markScheduled(SUnit *SU, unsigned BlockingCycles)
Update the state for SU being scheduled by removing it from the AllSUs and reducing its BlockingCycle...
SUnit * getNextTargetSU(bool LookDeep=false) const
void insert(SUnit *SU, unsigned BlockingCycles)
Insert the SU into AllSUs and account its BlockingCycles into the TotalCycles.
void setType(unsigned TheType)
AMDGPU::InstructionFlavor getType() const
SUnit * getHigherPriority(SUnit *SU, SUnit *Other) const
MachineInstrBundleIterator< MachineInstr > iterator
Track the current register pressure at some position in the instruction stream, and remember the high...
Scheduling unit. This is a node in the scheduling DAG.
Each Scheduling boundary is associated with ready queues.
A ScheduleDAG for scheduling lists of MachineInstr.
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
A SetVector that performs no allocations if smaller than a certain size.
Definition SetVector.h:345
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Provide an instruction scheduling machine model to CodeGen passes.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
InstructionFlavor
Classification of instructions by execution characteristics.
AMDGPUSchedReason
AMDGPU-specific scheduling decision reasons.
StringRef getReasonName(AMDGPUSchedReason R)
This is an optimization pass for GlobalISel generic memory operations.
ScheduleDAGInstrs * createGCNNoopPostMachineScheduler(MachineSchedContext *C)
@ Other
Any other memory.
Definition ModRef.h:68
ScheduleDAGInstrs * createGCNCoExecMachineScheduler(MachineSchedContext *C)
Policy for scheduling the next instruction in the candidate's zone.
Store the state used by GenericScheduler heuristics, required for the lifetime of one invocation of p...
MachineSchedContext provides enough context from the MachineScheduler pass for the target to instanti...