LLVM 24.0.0git
GCNPreRAAntiHints.cpp
Go to the documentation of this file.
1//===-- GCNPreRAAntiHints.cpp - MFMA register anti-hints ------------------===//
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 register allocation anti-hints.
11///
12//===----------------------------------------------------------------------===//
13
14#include "GCNPreRAAntiHints.h"
15#include "GCNSubtarget.h"
16#include "SIInstrInfo.h"
17#include "SIRegisterInfo.h"
18#include "llvm/ADT/STLExtras.h"
23
24using namespace llvm;
25using namespace llvm::AMDGPU;
26
27#define DEBUG_TYPE "amdgpu-anti-hints"
28
30
37
39 "amdgpu-anti-hints-rules", cl::Hidden, cl::CommaSeparated,
40 cl::desc("Anti-hints rules to select."),
41 cl::values(clEnumValN(AntiHintRule::None, "none", "Select no rules"),
43 "MFMA destination write-after-write"),
45 "XDL MFMA src2 write-after-read"),
47 "Select all rules (default)")));
48
49namespace {
50
51// Classify the MI into a HazardClassMask.
52HazardClassMask getInstHazardClass(const MachineInstr &MI,
53 const HazardContext &Ctx) {
54 const SIInstrInfo &TII = *Ctx.TII;
56
57 if (TII.isLDSDMA(MI))
58 Mask = HC::VALU | HC::VMEM | HC::DS;
59 else if (TII.isWMMA(MI) || SIInstrInfo::isSWMMAC(MI))
60 Mask = HC::WMMA;
61 else if (TII.isMFMA(MI))
62 Mask = HC::MFMA;
63 else if (SIInstrInfo::isTRANS(MI))
64 Mask = HC::TRANS;
65 else if (SIInstrInfo::isVALU(MI, /*AllowLDSDMA=*/true))
66 Mask = HC::VALU;
67 else if (TII.isDS(MI))
68 Mask = HC::DS;
69 else if (TII.isVMEM(MI))
70 Mask = HC::VMEM;
71 else if (TII.isSMRD(MI))
72 Mask = HC::SMEM;
73 else if (TII.isEXP(MI))
74 Mask = HC::EXP;
75 else if (SIInstrInfo::isSALU(MI))
76 Mask = HC::SALU;
77
78 return Mask;
79}
80
81bool isVirtualVGPR(const HazardContext &Ctx, const MachineOperand &MO) {
82 if (!MO.isReg() || !MO.getReg().isVirtual())
83 return false;
84 return Ctx.TRI->hasVGPRs(Ctx.MRI->getRegClass(MO.getReg()));
85}
86
87void collectOperandRegs(const MachineInstr &MI, HazardOperand Op,
88 const HazardContext &Ctx,
89 SmallVectorImpl<Register> &Out) {
90 const SIInstrInfo &TII = *Ctx.TII;
91 switch (Op) {
92 case HazardOperand::None:
93 break;
94 case HazardOperand::Def:
95 for (const MachineOperand &MO : MI.all_defs()) {
96 if (isVirtualVGPR(Ctx, MO))
97 Out.push_back(MO.getReg());
98 }
99 break;
100 case HazardOperand::Src0:
101 if (const MachineOperand *MO =
102 TII.getNamedOperand(MI, AMDGPU::OpName::src0)) {
103 if (isVirtualVGPR(Ctx, *MO))
104 Out.push_back(MO->getReg());
105 }
106 break;
107 case HazardOperand::Src1:
108 if (const MachineOperand *MO =
109 TII.getNamedOperand(MI, AMDGPU::OpName::src1)) {
110 if (isVirtualVGPR(Ctx, *MO))
111 Out.push_back(MO->getReg());
112 }
113 break;
114 case HazardOperand::Src2:
115 if (const MachineOperand *MO =
116 TII.getNamedOperand(MI, AMDGPU::OpName::src2)) {
117 if (isVirtualVGPR(Ctx, *MO))
118 Out.push_back(MO->getReg());
119 }
120 break;
121 case HazardOperand::Idx:
122 if (const MachineOperand *MO =
123 TII.getNamedOperand(MI, AMDGPU::OpName::idx)) {
124 if (isVirtualVGPR(Ctx, *MO))
125 Out.push_back(MO->getReg());
126 }
127 break;
128 case HazardOperand::Vaddr:
129 if (const MachineOperand *MO =
130 TII.getNamedOperand(MI, AMDGPU::OpName::vaddr)) {
131 if (isVirtualVGPR(Ctx, *MO))
132 Out.push_back(MO->getReg());
133 }
134 break;
135 case HazardOperand::AnySrc:
136 for (AMDGPU::OpName Name :
137 {AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2}) {
138 if (const MachineOperand *MO = TII.getNamedOperand(MI, Name)) {
139 if (isVirtualVGPR(Ctx, *MO))
140 Out.push_back(MO->getReg());
141 }
142 }
143 break;
144 case HazardOperand::AnyUse:
145 for (const MachineOperand &MO : MI.all_uses()) {
146 if (isVirtualVGPR(Ctx, MO))
147 Out.push_back(MO.getReg());
148 }
149 break;
150 }
151}
152
153enum class MFMAHazardKind { RAW, WAW, WAR };
154
155// MFMA anti-hint wait-state window, mirroring GCNHazardRecognizer.cpp wait
156// states.
157unsigned mfmaWaitStates(const MachineInstr &MFMA, MFMAHazardKind Kind,
158 HazardClassMask ReaderClass, const HazardContext &Ctx) {
159 const SIInstrInfo &TII = *Ctx.TII;
160 const GCNSubtarget &ST = *Ctx.ST;
161 const int NumPasses = Ctx.SchedModel->computeInstrLatency(&MFMA);
162 const bool IsDGEMM = SIInstrInfo::isDGEMM(MFMA.getOpcode());
163 const bool Mem = ReaderClass & (HC::VMEM | HC::DS | HC::EXP);
164
165 auto GFX940NPass = [&]() -> unsigned {
166 return TII.isXDL(MFMA)
167 ? NumPasses + 3 + (NumPasses != 2 && ST.hasGFX950Insts())
168 : NumPasses + 2;
169 };
170 auto SMFMANPass = [&]() -> unsigned {
171 switch (NumPasses) {
172 case 2:
173 return 5;
174 case 8:
175 return 11;
176 case 16:
177 return 19;
178 default:
179 return 0;
180 }
181 };
182
183 switch (Kind) {
184 case MFMAHazardKind::RAW:
185 if (IsDGEMM) {
186 switch (NumPasses) {
187 case 4:
188 return Mem ? 9 : 6;
189 case 8:
190 case 16:
191 return Mem ? 18 : (ST.hasGFX950Insts() ? 19 : 11);
192 default:
193 return 0;
194 }
195 }
196 return ST.hasGFX940Insts() ? GFX940NPass() : SMFMANPass();
197
198 case MFMAHazardKind::WAW:
199 if (IsDGEMM) {
200 switch (NumPasses) {
201 case 4:
202 return 6;
203 case 8:
204 case 16:
205 return 11;
206 default:
207 return 0;
208 }
209 }
210 return ST.hasGFX940Insts() ? GFX940NPass() : SMFMANPass();
211
212 case MFMAHazardKind::WAR:
213 switch (NumPasses) {
214 case 2:
215 return 1;
216 case 4:
217 return 3;
218 case 8:
219 return 7;
220 case 16:
221 return 15;
222 default:
223 return 15;
224 }
225 }
226 return 0;
227}
228
229unsigned mfmaWawWindow(const MachineInstr &P, const HazardContext &Ctx) {
230 return mfmaWaitStates(P, MFMAHazardKind::WAW, HC::None, Ctx);
231}
232unsigned mfmaWarWindow(const MachineInstr &P, const HazardContext &Ctx) {
233 return mfmaWaitStates(P, MFMAHazardKind::WAR, HC::None, Ctx);
234}
235
236unsigned mfmaReaderRawWindow(const MachineInstr &Producer,
237 HazardClassMask ReaderClass,
238 const HazardContext &Ctx) {
239 return mfmaWaitStates(Producer, MFMAHazardKind::RAW, ReaderClass, Ctx);
240}
241
242bool hasMFMAHazard(const HazardContext &Ctx) {
243 return Ctx.ST->hasGFX90AInsts();
244}
245
246bool ruleSelected(AntiHintRule Rule) {
247 if (AntiHintRuleSelection.empty() ||
249 return true;
251}
252
253bool isMFMAWAWRuleEnabled(const HazardContext &Ctx) {
254 return hasMFMAHazard(Ctx) && ruleSelected(AntiHintRule::MFMAWAW);
255}
256
257bool isMFMAWARRuleEnabled(const HazardContext &Ctx) {
258 return hasMFMAHazard(Ctx) && ruleSelected(AntiHintRule::MFMAWAR);
259}
260
261bool isXDLMFMA(const MachineInstr &MI, const HazardContext &Ctx) {
262 return Ctx.TII->isXDL(MI);
263}
264
265unsigned resolveWindow(const ConsumerTarget &CT, const MachineInstr &MI,
266 const HazardContext &Ctx) {
267 // Explicity given window length overrides the computed one.
268 if (CT.Window.OptWindowLength &&
270 return *CT.Window.OptWindowLength;
271 if (CT.Window.Fn)
272 return CT.Window.Fn(MI, Ctx);
273 return CT.Window.WindowLength;
274}
275
276// Build the anti-hints rules.
277class HazardRuleSet {
279
280public:
281 class RuleBuilder {
282
283 HazardRuleSet &S;
284 unsigned Idx;
285 HazardAntiHintRule &rule() const { return S.Rules[Idx]; }
286
287 public:
288 RuleBuilder(HazardRuleSet &S, unsigned Idx) : S(S), Idx(Idx) {}
289
290 RuleBuilder &producer(ClassMatch M, HazardOperand Op,
291 InstPredicate Predicate = nullptr) {
292 rule().Producer = {M, Op, Predicate};
293 return *this;
294 }
295
296 RuleBuilder &rawCredit(AdvanceForRawWindowFn AdvanceForRawWindow) {
297 rule().AdvanceForRawWindow = AdvanceForRawWindow;
298 return *this;
299 }
300
301 RuleBuilder &consumer(ClassMatch M, HazardOperand Op, WindowSpec Window,
302 HazardClassMask CountMask = 0,
303 ConsumerHint Hint = ConsumerHint::OneDirectional,
304 InstPredicate Predicate = nullptr) {
305 rule().Consumers.push_back({{M, Op, Predicate}, Window, CountMask, Hint});
306 return *this;
307 }
308
309 RuleBuilder &enabledIf(RulePredicate Predicate) {
310 rule().Predicate = Predicate;
311 return *this;
312 }
313 };
314
315 RuleBuilder addRule() {
316 Rules.emplace_back();
317 return RuleBuilder(*this, Rules.size() - 1);
318 }
319
320 SmallVector<HazardAntiHintRule, 0> buildRules() { return std::move(Rules); }
321};
322
323// Here the anti-hints rules are inserted.
324SmallVector<HazardAntiHintRule, 0> buildAntiHintsRules() {
325 using HO = HazardOperand;
326 HazardRuleSet S;
327
328 const WindowSpec MfmaWawWindow{0, nullptr, mfmaWawWindow};
329 const WindowSpec MfmaWarWindow{0, nullptr, mfmaWarWindow};
330 const ClassMatch MfmaConsumers = {HC::DS | HC::VALU | HC::VMEM | HC::TRANS |
331 HC::EXP};
332
333 // MFMA WAW rules
334 S.addRule()
335 .enabledIf(isMFMAWAWRuleEnabled)
336 .producer({HC::MFMA}, HO::Def)
337 .rawCredit(mfmaReaderRawWindow)
338 .consumer(MfmaConsumers, HO::Def, MfmaWawWindow, HC::None,
339 ConsumerHint::OneDirectional);
340
341 // MFMA WAR rules
342 S.addRule()
343 .enabledIf(isMFMAWARRuleEnabled)
344 .producer({HC::MFMA}, HO::Src2, isXDLMFMA)
345 .rawCredit(mfmaReaderRawWindow)
346 .consumer(MfmaConsumers, HO::Def, MfmaWarWindow, HC::None,
347 ConsumerHint::OneDirectional);
348
349 return S.buildRules();
350}
351
352ArrayRef<HazardAntiHintRule> getAntiHintsRules() {
353 static const SmallVector<HazardAntiHintRule, 0> Rules = buildAntiHintsRules();
354 return Rules;
355}
356
357struct AntiHintWindow {
359 const MachineInstr *Producer = nullptr;
360 unsigned Len = 0;
361 unsigned Elapsed = 0;
362};
363
364using ConsumerTracking = SmallVector<AntiHintWindow, 3>;
365// One per consumer target of a rule.
366using RuleTracking = SmallVector<ConsumerTracking, 3>;
367
368class AntiHintEngine {
369 const HazardContext &Ctx;
371
372 SmallVector<bool, 8> RuleApplies;
373 bool AnyEnabled = false;
374
375public:
376 AntiHintEngine(const HazardContext &Ctx)
377 : Ctx(Ctx), Rules(getAntiHintsRules()), RuleApplies(Rules.size()) {
378 for (unsigned R = 0; R < Rules.size(); ++R) {
379 const HazardAntiHintRule &Rule = Rules[R];
380 RuleApplies[R] = !Rule.Predicate || Rule.Predicate(Ctx);
381 AnyEnabled |= RuleApplies[R];
382 }
383 }
384
385 void run(MachineFunction &MF) {
386 if (!AnyEnabled)
387 return;
388
389 SmallVector<RuleTracking, 8> Tracking(Rules.size());
390 for (unsigned R = 0; R < Rules.size(); ++R)
391 Tracking[R].resize(Rules[R].Consumers.size());
392
393 for (const MachineBasicBlock &MBB : MF) {
394 for (RuleTracking &RT : Tracking) {
395 for (ConsumerTracking &Track : RT)
396 Track.clear();
397 }
398 for (const MachineInstr &MI : MBB) {
399 if (MI.isMetaInstruction())
400 continue;
401 const HazardClassMask C = getInstHazardClass(MI, Ctx);
402 // Wait states this instruction contributes to an open window.
403 unsigned WaitStates = SIInstrInfo::getNumWaitStates(MI);
404 addAntiHintsAndExpire(MI, C, WaitStates, Tracking);
405 addWindows(MI, C, Tracking);
406 }
407 }
408 }
409
410private:
411 // Check if the right class and predicate matches.
412 bool sideMatches(const HazardSide &Side, const MachineInstr &MI,
414 return Side.Match.matches(C) &&
415 (!Side.Predicate || Side.Predicate(MI, Ctx));
416 }
417
418 // Producer phase: open a window for each consumer target.
419 void addWindows(const MachineInstr &MI, HazardClassMask C,
421 for (unsigned R = 0; R < Rules.size(); ++R) {
422 const HazardAntiHintRule &Rule = Rules[R];
423 if (!RuleApplies[R] || !sideMatches(Rule.Producer, MI, C))
424 continue;
425
427 // Collect the producer regs.
428 collectOperandRegs(MI, Rule.Producer.Op, Ctx, Regs);
429 if (Regs.empty())
430 continue;
431 for (unsigned ConsumerIdx = 0, E = Rule.Consumers.size();
432 ConsumerIdx != E; ++ConsumerIdx) {
433 unsigned Window = resolveWindow(Rule.Consumers[ConsumerIdx], MI, Ctx);
434 if (!Window)
435 continue;
436 Tracking[R][ConsumerIdx].push_back({Regs, &MI, Window, 0});
437 }
438 }
439 }
440
441 void advanceByRawWindow(const MachineInstr &MI, HazardClassMask C,
442 const HazardAntiHintRule &Rule,
443 const ConsumerTarget &CT, ConsumerTracking &Track) {
444
445 if (!Rule.AdvanceForRawWindow || !CT.Side.Match.matches(C))
446 return;
447 for (AntiHintWindow &Window : Track) {
448 // Determine if def generated by producer is read by the MI consumer.
449 bool ReadsProducerDef = llvm::any_of(
450 Window.Producer->all_defs(), [&](const MachineOperand &MO) {
451 return MO.getReg().isVirtual() &&
452 MI.readsVirtualRegister(MO.getReg());
453 });
454 // Advance by RAW window from the producer if that is larger than current
455 // Window.Elapsed.
456 if (ReadsProducerDef) {
457 Window.Elapsed = std::max(
458 Window.Elapsed, Rule.AdvanceForRawWindow(*Window.Producer, C, Ctx));
459 }
460 }
461 }
462
463 // Consumer phase: add anti-hints, then charge and expire open windows.
464 void addAntiHintsAndExpire(const MachineInstr &MI, HazardClassMask C,
465 unsigned WaitStates,
467 for (unsigned R = 0; R < Rules.size(); ++R) {
468 const HazardAntiHintRule &Rule = Rules[R];
469 if (!RuleApplies[R])
470 continue;
471 for (unsigned ConsumerIdx = 0, E = Rule.Consumers.size();
472 ConsumerIdx != E; ++ConsumerIdx) {
473 const ConsumerTarget &CT = Rule.Consumers[ConsumerIdx];
474 ConsumerTracking &Track = Tracking[R][ConsumerIdx];
475 if (Track.empty())
476 continue;
477
478 // Before adding the anti-hints, see if advancing by RAW window will
479 // help remove the window.
480 advanceByRawWindow(MI, C, Rule, CT, Track);
481 llvm::erase_if(Track, [](const AntiHintWindow &Window) {
482 return Window.Elapsed >= Window.Len;
483 });
484
485 // Add anti-hints if the consumer matches the instruction.
486 if (sideMatches(CT.Side, MI, C))
487 addAntiHints(CT, MI, Track);
488
489 // This instruction's own wait states count toward the next one.
490 if (!CT.CounterMask || (C & CT.CounterMask)) {
491 for (AntiHintWindow &Window : Track)
492 Window.Elapsed += WaitStates;
493 }
494 }
495 }
496 }
497
498 bool isCopyOf(Register Cand, Register HazardReg) const {
499 const MachineInstr *Def = Ctx.MRI->getUniqueVRegDef(Cand);
500 return Def && Def->isCopy() && Def->getOperand(1).getReg() == HazardReg;
501 }
502
503 void addAntiHints(const ConsumerTarget &CT, const MachineInstr &MI,
504 const ConsumerTracking &Track) {
505 if (Track.empty())
506 return;
507 SmallVector<Register, 4> ConsumerRegs;
508 // Collect the consumer regs.
509 collectOperandRegs(MI, CT.Side.Op, Ctx, ConsumerRegs);
510 if (ConsumerRegs.empty())
511 return;
512 SlotIndex Slot = Ctx.LIS->getInstructionIndex(MI).getRegSlot();
513 auto AntiHint = [&](Register ProducerReg) {
514 if (!Ctx.LIS->hasInterval(ProducerReg))
515 return;
516 const LiveInterval &ProducerLI = Ctx.LIS->getInterval(ProducerReg);
517 // Skip a live producer reg.
518 if (ProducerLI.liveAt(Slot))
519 return;
520 for (Register ConsumerReg : ConsumerRegs) {
521 if (ConsumerReg == ProducerReg || isCopyOf(ConsumerReg, ProducerReg))
522 continue;
523
524 Ctx.MRI->addRegAllocationAntiHints(ConsumerReg, ProducerReg);
525 if (CT.Hint == ConsumerHint::Symmetric)
526 Ctx.MRI->addRegAllocationAntiHints(ProducerReg, ConsumerReg);
528 dbgs() << "anti-hint: keep " << printReg(ProducerReg, Ctx.TRI)
529 << (CT.Hint == ConsumerHint::Symmetric ? " <-> " : " <- ")
530 << printReg(ConsumerReg, Ctx.TRI) << " (consumer "
531 << Ctx.TII->getName(MI.getOpcode()) << ")\n");
532 }
533 };
534 for (const AntiHintWindow &Window : Track) {
535 for (Register ProducerReg : Window.Regs)
536 AntiHint(ProducerReg);
537 }
538 }
539};
540
541} // namespace
542
544 AntiHintEngine(Ctx).run(MF);
545}
MachineBasicBlock & MBB
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
static cl::list< AntiHintRule > AntiHintRuleSelection("amdgpu-anti-hints-rules", cl::Hidden, cl::CommaSeparated, cl::desc("Anti-hints rules to select."), cl::values(clEnumValN(AntiHintRule::None, "none", "Select no rules"), clEnumValN(AntiHintRule::MFMAWAW, "mfma-waw", "MFMA destination write-after-write"), clEnumValN(AntiHintRule::MFMAWAR, "mfma-war", "XDL MFMA src2 write-after-read"), clEnumValN(AntiHintRule::All, "all", "Select all rules (default)")))
AMD GCN specific subclass of TargetSubtarget.
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
static Register isCopyOf(const MachineInstr &MI, Register Reg, const TargetInstrInfo &TII)
isFullCopyOf - If MI is a COPY to or from Reg, return the other register, otherwise return 0.
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define P(N)
Interface definition for SIInstrInfo.
Interface definition for SIRegisterInfo.
This file contains some templates that are useful if you are working with the STL at all.
#define LLVM_DEBUG(...)
Definition Debug.h:119
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool hasInterval(Register Reg) const
SlotIndex getInstructionIndex(const MachineInstr &Instr) const
Returns the base index of the given instruction.
LiveInterval & getInterval(Register Reg)
bool liveAt(SlotIndex index) const
Representation of each machine instruction.
bool isCopy() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
void addRegAllocationAntiHints(Register VReg, ArrayRef< Register > AntiHintVRegs)
Add multiple anti-hints at once.
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
static bool isDGEMM(unsigned Opcode)
static bool isSALU(const MachineInstr &MI)
static bool isSWMMAC(const MachineInstr &MI)
bool isXDL(const MachineInstr &MI) const
static bool isVALU(const MachineInstr &MI, bool AllowLDSDMA)
static bool isTRANS(const MachineInstr &MI)
static unsigned getNumWaitStates(const MachineInstr &MI)
Return the number of wait states that result from executing this instruction.
static bool hasVGPRs(const TargetRegisterClass *RC)
SlotIndex getRegSlot(bool EC=false) const
Returns the register use/def slot in the current instruction for a normal or early-clobber def.
reference emplace_back(ArgTypes &&... Args)
int getNumOccurrences() const
uint32_t HazardClassMask
bool(*)(const HazardContext &) RulePredicate
void applyAntiHintRules(MachineFunction &MF, const HazardContext &Ctx)
unsigned(*)(const MachineInstr &Producer, HazardClassMask ReaderClass, const HazardContext &Ctx) AdvanceForRawWindowFn
bool(*)(const MachineInstr &, const HazardContext &) InstPredicate
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1685
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:1762
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
MutableArrayRef(T &OneElt) -> MutableArrayRef< T >
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
Definition STLExtras.h:2208
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1963
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
bool matches(HazardClassMask Mask) const
SmallVector< ConsumerTarget, 3 > Consumers
AdvanceForRawWindowFn AdvanceForRawWindow
const SIRegisterInfo * TRI
MachineRegisterInfo * MRI
const TargetSchedModel * SchedModel
unsigned(* Fn)(const MachineInstr &Producer, const HazardContext &Ctx)
const cl::opt< unsigned > * OptWindowLength