LLVM 21.0.0git
AMDGPUWaitSGPRHazards.cpp
Go to the documentation of this file.
1//===- AMDGPUWaitSGPRHazards.cpp - Insert waits for SGPR read hazards -----===//
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/// Insert s_wait_alu instructions to mitigate SGPR read hazards on GFX12.
11//
12//===----------------------------------------------------------------------===//
13
15#include "AMDGPU.h"
16#include "GCNSubtarget.h"
18#include "SIInstrInfo.h"
19#include "llvm/ADT/SetVector.h"
20
21using namespace llvm;
22
23#define DEBUG_TYPE "amdgpu-wait-sgpr-hazards"
24
26 "amdgpu-sgpr-hazard-wait", cl::init(true), cl::Hidden,
27 cl::desc("Enable required s_wait_alu on SGPR hazards"));
28
30 "amdgpu-sgpr-hazard-boundary-cull", cl::init(false), cl::Hidden,
31 cl::desc("Cull hazards on function boundaries"));
32
33static cl::opt<bool>
34 GlobalCullSGPRHazardsAtMemWait("amdgpu-sgpr-hazard-mem-wait-cull",
35 cl::init(false), cl::Hidden,
36 cl::desc("Cull hazards on memory waits"));
37
39 "amdgpu-sgpr-hazard-mem-wait-cull-threshold", cl::init(8), cl::Hidden,
40 cl::desc("Number of tracked SGPRs before initiating hazard cull on memory "
41 "wait"));
42
43namespace {
44
45class AMDGPUWaitSGPRHazards {
46public:
47 const SIInstrInfo *TII;
48 const SIRegisterInfo *TRI;
50 unsigned DsNopCount;
51
52 bool EnableSGPRHazardWaits;
53 bool CullSGPRHazardsOnFunctionBoundary;
54 bool CullSGPRHazardsAtMemWait;
55 unsigned CullSGPRHazardsMemWaitThreshold;
56
57 AMDGPUWaitSGPRHazards() {}
58
59 // Return the numeric ID 0-127 for a given SGPR.
60 static std::optional<unsigned> sgprNumber(Register Reg,
61 const SIRegisterInfo &TRI) {
62 switch (Reg) {
63 case AMDGPU::M0:
64 case AMDGPU::EXEC:
65 case AMDGPU::EXEC_LO:
66 case AMDGPU::EXEC_HI:
67 case AMDGPU::SGPR_NULL:
68 case AMDGPU::SGPR_NULL64:
69 return {};
70 default:
71 break;
72 }
73 unsigned RegN = TRI.getHWRegIndex(Reg);
74 if (RegN > 127)
75 return {};
76 return RegN;
77 }
78
79 static inline bool isVCC(Register Reg) {
80 return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::VCC_HI;
81 }
82
83 // Adjust global offsets for instructions bundled with S_GETPC_B64 after
84 // insertion of a new instruction.
85 static void updateGetPCBundle(MachineInstr *NewMI) {
86 if (!NewMI->isBundled())
87 return;
88
89 // Find start of bundle.
90 auto I = NewMI->getIterator();
91 while (I->isBundledWithPred())
92 I--;
93 if (I->isBundle())
94 I++;
95
96 // Bail if this is not an S_GETPC bundle.
97 if (I->getOpcode() != AMDGPU::S_GETPC_B64)
98 return;
99
100 // Update offsets of any references in the bundle.
101 const unsigned NewBytes = 4;
102 assert(NewMI->getOpcode() == AMDGPU::S_WAITCNT_DEPCTR &&
103 "Unexpected instruction insertion in bundle");
104 auto NextMI = std::next(NewMI->getIterator());
105 auto End = NewMI->getParent()->end();
106 while (NextMI != End && NextMI->isBundledWithPred()) {
107 for (auto &Operand : NextMI->operands()) {
108 if (Operand.isGlobal())
109 Operand.setOffset(Operand.getOffset() + NewBytes);
110 }
111 NextMI++;
112 }
113 }
114
115 struct HazardState {
116 static constexpr unsigned None = 0;
117 static constexpr unsigned SALU = (1 << 0);
118 static constexpr unsigned VALU = (1 << 1);
119
120 std::bitset<64> Tracked; // SGPR banks ever read by VALU
121 std::bitset<128> SALUHazards; // SGPRs with uncommitted values from SALU
122 std::bitset<128> VALUHazards; // SGPRs with uncommitted values from VALU
123 unsigned VCCHazard = None; // Source of current VCC writes
124 bool ActiveFlat = false; // Has unwaited flat instructions
125
126 bool merge(const HazardState &RHS) {
127 HazardState Orig(*this);
128 *this |= RHS;
129 return (*this != Orig);
130 }
131
132 bool operator==(const HazardState &RHS) const {
133 return Tracked == RHS.Tracked && SALUHazards == RHS.SALUHazards &&
134 VALUHazards == RHS.VALUHazards && VCCHazard == RHS.VCCHazard &&
135 ActiveFlat == RHS.ActiveFlat;
136 }
137
138 bool operator!=(const HazardState &RHS) const { return !(*this == RHS); }
139
140 void operator|=(const HazardState &RHS) {
141 Tracked |= RHS.Tracked;
142 SALUHazards |= RHS.SALUHazards;
143 VALUHazards |= RHS.VALUHazards;
144 VCCHazard |= RHS.VCCHazard;
145 ActiveFlat |= RHS.ActiveFlat;
146 }
147 };
148
149 struct BlockHazardState {
150 HazardState In;
151 HazardState Out;
152 };
153
155
156 static constexpr unsigned WAVE32_NOPS = 4;
157 static constexpr unsigned WAVE64_NOPS = 8;
158
159 void insertHazardCull(MachineBasicBlock &MBB,
161 assert(!MI->isBundled());
162 unsigned Count = DsNopCount;
163 while (Count--)
164 BuildMI(MBB, MI, MI->getDebugLoc(), TII->get(AMDGPU::DS_NOP));
165 }
166
167 bool runOnMachineBasicBlock(MachineBasicBlock &MBB, bool Emit) {
168 enum { WA_VALU = 0x1, WA_SALU = 0x2, WA_VCC = 0x4 };
169
170 HazardState State = BlockState[&MBB].In;
171 SmallSet<Register, 8> SeenRegs;
172 bool Emitted = false;
173 unsigned DsNops = 0;
174
176 E = MBB.instr_end();
177 MI != E; ++MI) {
178 if (MI->isMetaInstruction())
179 continue;
180
181 // Clear tracked SGPRs if sufficient DS_NOPs occur
182 if (MI->getOpcode() == AMDGPU::DS_NOP) {
183 if (++DsNops >= DsNopCount)
184 State.Tracked.reset();
185 continue;
186 }
187 DsNops = 0;
188
189 // Snoop FLAT instructions to avoid adding culls before scratch/lds loads.
190 // Culls could be disproportionate in cost to load time.
192 State.ActiveFlat = true;
193
194 // SMEM or VMEM clears hazards
196 State.VCCHazard = HazardState::None;
197 State.SALUHazards.reset();
198 State.VALUHazards.reset();
199 continue;
200 }
201
202 // Existing S_WAITALU can clear hazards
203 if (MI->getOpcode() == AMDGPU::S_WAITCNT_DEPCTR) {
204 unsigned int Mask = MI->getOperand(0).getImm();
206 State.VCCHazard &= ~HazardState::VALU;
207 if (AMDGPU::DepCtr::decodeFieldSaSdst(Mask) == 0) {
208 State.SALUHazards.reset();
209 State.VCCHazard &= ~HazardState::SALU;
210 }
212 State.VALUHazards.reset();
213 continue;
214 }
215
216 // Snoop counter waits to insert culls
217 if (CullSGPRHazardsAtMemWait &&
218 (MI->getOpcode() == AMDGPU::S_WAIT_LOADCNT ||
219 MI->getOpcode() == AMDGPU::S_WAIT_SAMPLECNT ||
220 MI->getOpcode() == AMDGPU::S_WAIT_BVHCNT) &&
221 (MI->getOperand(0).isImm() && MI->getOperand(0).getImm() == 0) &&
222 (State.Tracked.count() >= CullSGPRHazardsMemWaitThreshold)) {
223 if (MI->getOpcode() == AMDGPU::S_WAIT_LOADCNT && State.ActiveFlat) {
224 State.ActiveFlat = false;
225 } else {
226 State.Tracked.reset();
227 if (Emit)
228 insertHazardCull(MBB, MI);
229 continue;
230 }
231 }
232
233 // Process only VALUs and SALUs
234 bool IsVALU = SIInstrInfo::isVALU(*MI);
235 bool IsSALU = SIInstrInfo::isSALU(*MI);
236 if (!IsVALU && !IsSALU)
237 continue;
238
239 unsigned Wait = 0;
240
241 auto processOperand = [&](const MachineOperand &Op, bool IsUse) {
242 if (!Op.isReg())
243 return;
244 Register Reg = Op.getReg();
245 assert(!Op.getSubReg());
246 if (!TRI->isSGPRReg(*MRI, Reg))
247 return;
248
249 // Only visit each register once
250 if (!SeenRegs.insert(Reg).second)
251 return;
252
253 auto RegNumber = sgprNumber(Reg, *TRI);
254 if (!RegNumber)
255 return;
256
257 // Track SGPRs by pair -- numeric ID of an 64b SGPR pair.
258 // i.e. SGPR0 = SGPR0_SGPR1 = 0, SGPR3 = SGPR2_SGPR3 = 1, etc
259 unsigned RegN = *RegNumber;
260 unsigned PairN = (RegN >> 1) & 0x3f;
261
262 // Read/write of untracked register is safe; but must record any new
263 // reads.
264 if (!State.Tracked[PairN]) {
265 if (IsVALU && IsUse)
266 State.Tracked.set(PairN);
267 return;
268 }
269
270 uint8_t SGPRCount =
271 AMDGPU::getRegBitWidth(*TRI->getRegClassForReg(*MRI, Reg)) / 32;
272
273 if (IsUse) {
274 // SALU reading SGPR clears VALU hazards
275 if (IsSALU) {
276 if (isVCC(Reg)) {
277 if (State.VCCHazard & HazardState::VALU)
278 State.VCCHazard = HazardState::None;
279 } else {
280 State.VALUHazards.reset();
281 }
282 }
283 // Compute required waits
284 for (uint8_t RegIdx = 0; RegIdx < SGPRCount; ++RegIdx) {
285 Wait |= State.SALUHazards[RegN + RegIdx] ? WA_SALU : 0;
286 Wait |= IsVALU && State.VALUHazards[RegN + RegIdx] ? WA_VALU : 0;
287 }
288 if (isVCC(Reg) && State.VCCHazard) {
289 // Note: it's possible for both SALU and VALU to exist if VCC
290 // was updated differently by merged predecessors.
291 if (State.VCCHazard & HazardState::SALU)
292 Wait |= WA_SALU;
293 if (State.VCCHazard & HazardState::VALU)
294 Wait |= WA_VCC;
295 }
296 } else {
297 // Update hazards
298 if (isVCC(Reg)) {
299 State.VCCHazard = IsSALU ? HazardState::SALU : HazardState::VALU;
300 } else {
301 for (uint8_t RegIdx = 0; RegIdx < SGPRCount; ++RegIdx) {
302 if (IsSALU)
303 State.SALUHazards.set(RegN + RegIdx);
304 else
305 State.VALUHazards.set(RegN + RegIdx);
306 }
307 }
308 }
309 };
310
311 const bool IsSetPC =
312 (MI->isCall() || MI->isReturn() || MI->isIndirectBranch()) &&
313 MI->getOpcode() != AMDGPU::S_ENDPGM &&
314 MI->getOpcode() != AMDGPU::S_ENDPGM_SAVED;
315
316 // Only consider implicit VCC specified by instruction descriptor.
317 const bool HasImplicitVCC =
318 llvm::any_of(MI->getDesc().implicit_uses(),
319 [](MCPhysReg Reg) { return isVCC(Reg); }) ||
320 llvm::any_of(MI->getDesc().implicit_defs(),
321 [](MCPhysReg Reg) { return isVCC(Reg); });
322
323 if (IsSetPC) {
324 // All SGPR writes before a call/return must be flushed as the
325 // callee/caller will not will not see the hazard chain.
326 if (State.VCCHazard & HazardState::VALU)
327 Wait |= WA_VCC;
328 if (State.SALUHazards.any() || (State.VCCHazard & HazardState::SALU))
329 Wait |= WA_SALU;
330 if (State.VALUHazards.any())
331 Wait |= WA_VALU;
332 if (CullSGPRHazardsOnFunctionBoundary && State.Tracked.any()) {
333 State.Tracked.reset();
334 if (Emit)
335 insertHazardCull(MBB, MI);
336 }
337 } else {
338 // Process uses to determine required wait.
339 SeenRegs.clear();
340 for (const MachineOperand &Op : MI->all_uses()) {
341 if (Op.isImplicit() &&
342 (!HasImplicitVCC || !Op.isReg() || !isVCC(Op.getReg())))
343 continue;
344 processOperand(Op, true);
345 }
346 }
347
348 // Apply wait
349 if (Wait) {
350 unsigned Mask = 0xffff;
351 if (Wait & WA_VCC) {
352 State.VCCHazard &= ~HazardState::VALU;
354 }
355 if (Wait & WA_SALU) {
356 State.SALUHazards.reset();
357 State.VCCHazard &= ~HazardState::SALU;
359 }
360 if (Wait & WA_VALU) {
361 State.VALUHazards.reset();
363 }
364 if (Emit) {
365 auto NewMI = BuildMI(MBB, MI, MI->getDebugLoc(),
366 TII->get(AMDGPU::S_WAITCNT_DEPCTR))
367 .addImm(Mask);
368 updateGetPCBundle(NewMI);
369 Emitted = true;
370 }
371 }
372
373 // On return from a call SGPR state is unknown, so all potential hazards.
374 if (MI->isCall() && !CullSGPRHazardsOnFunctionBoundary)
375 State.Tracked.set();
376
377 // Update hazards based on defs.
378 SeenRegs.clear();
379 for (const MachineOperand &Op : MI->all_defs()) {
380 if (Op.isImplicit() &&
381 (!HasImplicitVCC || !Op.isReg() || !isVCC(Op.getReg())))
382 continue;
383 processOperand(Op, false);
384 }
385 }
386
387 bool Changed = State != BlockState[&MBB].Out;
388 if (Emit) {
389 assert(!Changed && "Hazard state should not change on emit pass");
390 return Emitted;
391 }
392 if (Changed)
393 BlockState[&MBB].Out = State;
394 return Changed;
395 }
396
397 bool run(MachineFunction &MF) {
399 if (!ST.hasVALUReadSGPRHazard())
400 return false;
401
402 // Parse settings
403 EnableSGPRHazardWaits = GlobalEnableSGPRHazardWaits;
404 CullSGPRHazardsOnFunctionBoundary = GlobalCullSGPRHazardsOnFunctionBoundary;
405 CullSGPRHazardsAtMemWait = GlobalCullSGPRHazardsAtMemWait;
406 CullSGPRHazardsMemWaitThreshold = GlobalCullSGPRHazardsMemWaitThreshold;
407
409 EnableSGPRHazardWaits = MF.getFunction().getFnAttributeAsParsedInteger(
410 "amdgpu-sgpr-hazard-wait", EnableSGPRHazardWaits);
412 CullSGPRHazardsOnFunctionBoundary =
413 MF.getFunction().hasFnAttribute("amdgpu-sgpr-hazard-boundary-cull");
415 CullSGPRHazardsAtMemWait =
416 MF.getFunction().hasFnAttribute("amdgpu-sgpr-hazard-mem-wait-cull");
417 if (!GlobalCullSGPRHazardsMemWaitThreshold.getNumOccurrences())
418 CullSGPRHazardsMemWaitThreshold =
420 "amdgpu-sgpr-hazard-mem-wait-cull-threshold",
421 CullSGPRHazardsMemWaitThreshold);
422
423 // Bail if disabled
424 if (!EnableSGPRHazardWaits)
425 return false;
426
427 TII = ST.getInstrInfo();
428 TRI = ST.getRegisterInfo();
429 MRI = &MF.getRegInfo();
430 DsNopCount = ST.isWave64() ? WAVE64_NOPS : WAVE32_NOPS;
431
433 if (!AMDGPU::isEntryFunctionCC(CallingConv) &&
434 !CullSGPRHazardsOnFunctionBoundary) {
435 // Callee must consider all SGPRs as tracked.
436 LLVM_DEBUG(dbgs() << "Is called function, track all SGPRs.\n");
437 MachineBasicBlock &EntryBlock = MF.front();
438 BlockState[&EntryBlock].In.Tracked.set();
439 }
440
441 // Calculate the hazard state for each basic block.
442 // Iterate until a fixed point is reached.
443 // Fixed point is guaranteed as merge function only ever increases
444 // the hazard set, and all backedges will cause a merge.
445 //
446 // Note: we have to take care of the entry block as this technically
447 // has an edge from outside the function. Failure to treat this as
448 // a merge could prevent fixed point being reached.
450 for (auto &MBB : reverse(MF))
451 Worklist.insert(&MBB);
452 while (!Worklist.empty()) {
453 auto &MBB = *Worklist.pop_back_val();
454 bool Changed = runOnMachineBasicBlock(MBB, false);
455 if (Changed) {
456 // Note: take a copy of state here in case it is reallocated by map
457 HazardState NewState = BlockState[&MBB].Out;
458 // Propagate to all successor blocks
459 for (auto Succ : MBB.successors()) {
460 // We only need to merge hazards at CFG merge points.
461 auto &SuccState = BlockState[Succ];
462 if (Succ->getSinglePredecessor() && !Succ->isEntryBlock()) {
463 if (SuccState.In != NewState) {
464 SuccState.In = NewState;
465 Worklist.insert(Succ);
466 }
467 } else if (SuccState.In.merge(NewState)) {
468 Worklist.insert(Succ);
469 }
470 }
471 }
472 }
473
474 LLVM_DEBUG(dbgs() << "Emit s_wait_alu instructions\n");
475
476 // Final to emit wait instructions.
477 bool Changed = false;
478 for (auto &MBB : MF)
479 Changed |= runOnMachineBasicBlock(MBB, true);
480
481 BlockState.clear();
482 return Changed;
483 }
484};
485
486class AMDGPUWaitSGPRHazardsLegacy : public MachineFunctionPass {
487public:
488 static char ID;
489
490 AMDGPUWaitSGPRHazardsLegacy() : MachineFunctionPass(ID) {}
491
492 bool runOnMachineFunction(MachineFunction &MF) override {
493 return AMDGPUWaitSGPRHazards().run(MF);
494 }
495
496 void getAnalysisUsage(AnalysisUsage &AU) const override {
497 AU.setPreservesCFG();
499 }
500};
501
502} // namespace
503
504char AMDGPUWaitSGPRHazardsLegacy::ID = 0;
505
506char &llvm::AMDGPUWaitSGPRHazardsLegacyID = AMDGPUWaitSGPRHazardsLegacy::ID;
507
508INITIALIZE_PASS(AMDGPUWaitSGPRHazardsLegacy, DEBUG_TYPE,
509 "AMDGPU Insert waits for SGPR read hazards", false, false)
510
514 if (AMDGPUWaitSGPRHazards().run(MF))
516 return PreservedAnalyses::all();
517}
unsigned const MachineRegisterInfo * MRI
Provides AMDGPU specific target descriptions.
static cl::opt< bool > GlobalCullSGPRHazardsAtMemWait("amdgpu-sgpr-hazard-mem-wait-cull", cl::init(false), cl::Hidden, cl::desc("Cull hazards on memory waits"))
static cl::opt< unsigned > GlobalCullSGPRHazardsMemWaitThreshold("amdgpu-sgpr-hazard-mem-wait-cull-threshold", cl::init(8), cl::Hidden, cl::desc("Number of tracked SGPRs before initiating hazard cull on memory " "wait"))
static cl::opt< bool > GlobalCullSGPRHazardsOnFunctionBoundary("amdgpu-sgpr-hazard-boundary-cull", cl::init(false), cl::Hidden, cl::desc("Cull hazards on function boundaries"))
static cl::opt< bool > GlobalEnableSGPRHazardWaits("amdgpu-sgpr-hazard-wait", cl::init(true), cl::Hidden, cl::desc("Enable required s_wait_alu on SGPR hazards"))
#define DEBUG_TYPE
MachineBasicBlock & MBB
#define LLVM_DEBUG(...)
Definition: Debug.h:106
bool End
Definition: ELF_riscv.cpp:480
static void updateGetPCBundle(MachineInstr *NewMI)
AMD GCN specific subclass of TargetSubtarget.
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
static LoopDeletionResult merge(LoopDeletionResult A, LoopDeletionResult B)
#define I(x, y, z)
Definition: MD5.cpp:58
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
Interface definition for SIInstrInfo.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements a set that has insertion order iteration characteristics.
Value * RHS
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:253
Represent the analysis usage information of a pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:256
This class represents an Operation in the Expression.
uint64_t getFnAttributeAsParsedInteger(StringRef Kind, uint64_t Default=0) const
For a string attribute Kind, parse attribute as an integer.
Definition: Function.cpp:778
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition: Function.h:277
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition: Function.cpp:731
instr_iterator instr_begin()
Instructions::iterator instr_iterator
instr_iterator instr_end()
iterator_range< succ_iterator > successors()
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineBasicBlock & front() const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Representation of each machine instruction.
Definition: MachineInstr.h:71
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:577
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:349
bool isBundled() const
Return true if this instruction part of a bundle.
Definition: MachineInstr.h:474
MachineOperand class - Representation of each machine instruction operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:111
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition: Analysis.h:114
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:117
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
static bool isVMEM(const MachineInstr &MI)
Definition: SIInstrInfo.h:441
static bool isSMRD(const MachineInstr &MI)
Definition: SIInstrInfo.h:553
static bool isSALU(const MachineInstr &MI)
Definition: SIInstrInfo.h:417
static bool isFLATGlobal(const MachineInstr &MI)
Definition: SIInstrInfo.h:637
static bool isFLAT(const MachineInstr &MI)
Definition: SIInstrInfo.h:621
static bool isVALU(const MachineInstr &MI)
Definition: SIInstrInfo.h:425
A vector that has set insertion semantics.
Definition: SetVector.h:57
bool empty() const
Determine if the SetVector is empty or not.
Definition: SetVector.h:93
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition: SetVector.h:162
value_type pop_back_val()
Definition: SetVector.h:285
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition: SmallSet.h:132
void clear()
Definition: SmallSet.h:204
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition: SmallSet.h:181
int getNumOccurrences() const
Definition: CommandLine.h:399
self_iterator getIterator()
Definition: ilist_node.h:132
unsigned decodeFieldVaVcc(unsigned Encoded)
unsigned encodeFieldVaVcc(unsigned Encoded, unsigned VaVcc)
unsigned decodeFieldSaSdst(unsigned Encoded)
unsigned decodeFieldVaSdst(unsigned Encoded)
unsigned encodeFieldSaSdst(unsigned Encoded, unsigned SaSdst)
unsigned encodeFieldVaSdst(unsigned Encoded, unsigned VaSdst)
bool isEntryFunctionCC(CallingConv::ID CC)
unsigned getRegBitWidth(const TargetRegisterClass &RC)
Get the size in bits of a register from the register class RC.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
Definition: BitmaskEnum.h:125
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:443
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
@ Emitted
Assigned address, still materializing.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
@ Wait
Definition: Threading.h:60
bool operator!=(uint64_t V1, const APInt &V2)
Definition: APInt.h:2082
char & AMDGPUWaitSGPRHazardsLegacyID
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1746
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:420
@ None
Definition: CodeGenData.h:106
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
DWARFExpression::Operation Op
bool operator|=(SparseBitVector< ElementSize > &LHS, const SparseBitVector< ElementSize > *RHS)