LLVM 24.0.0git
GCNSubtarget.cpp
Go to the documentation of this file.
1//===-- GCNSubtarget.cpp - GCN Subtarget Information ----------------------===//
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/// Implements the GCN specific subclass of TargetSubtarget.
11//
12//===----------------------------------------------------------------------===//
13
14#include "GCNSubtarget.h"
15#include "AMDGPUCallLowering.h"
17#include "AMDGPULegalizerInfo.h"
20#include "AMDGPUTargetMachine.h"
29#include "llvm/IR/MDBuilder.h"
31#include <algorithm>
32
33using namespace llvm;
34
35#define DEBUG_TYPE "gcn-subtarget"
36
37#define GET_SUBTARGETINFO_TARGET_DESC
38#define GET_SUBTARGETINFO_CTOR
39#define AMDGPUSubtarget GCNSubtarget
40#include "AMDGPUGenSubtargetInfo.inc"
41#undef AMDGPUSubtarget
42
44 "amdgpu-vgpr-index-mode",
45 cl::desc("Use GPR indexing mode instead of movrel for vector indexing"),
46 cl::init(false));
47
48static cl::opt<bool> UseAA("amdgpu-use-aa-in-codegen",
49 cl::desc("Enable the use of AA during codegen."),
50 cl::init(true));
51
53 NSAThreshold("amdgpu-nsa-threshold",
54 cl::desc("Number of addresses from which to enable MIMG NSA."),
56
58
60 // Legacy triples without a subarch default to the first target that supports
61 // flat addressing for HSA, otherwise the first amdgcn target.
62 if (TT.getSubArch() == Triple::NoSubArch)
63 return TT.getOS() == Triple::AMDHSA ? AMDGPUSubtarget::SEA_ISLANDS
65
66 switch (AMDGPU::getMajorSubArch(TT.getSubArch())) {
91 default:
92 reportFatalUsageError("invalid subarch for amdgpu");
93 }
94}
95
97 const Triple &TT, StringRef GPU, StringRef FS,
100 // Determine default and user-specified characteristics
101 //
102 // We want to be able to turn these off, but making this a subtarget feature
103 // for SI has the unhelpful behavior that it unsets everything else if you
104 // disable it.
105 //
106 // Similarly we want enable-prt-strict-null to be on by default and not to
107 // unset everything else if it is disabled
108
109 SmallString<256> FullFS("+load-store-opt,+enable-ds128,");
110
111 // Turn on features that HSA ABI requires. Also turn on FlatForGlobal by
112 // default
113 if (isAmdHsaOS())
114 FullFS += "+flat-for-global,+unaligned-access-mode,+trap-handler,";
115
116 FullFS += "+enable-prt-strict-null,"; // This is overridden by a disable in FS
117
118 // Disable mutually exclusive bits.
119 if (FS.contains_insensitive("+wavefrontsize")) {
120 if (!FS.contains_insensitive("wavefrontsize16"))
121 FullFS += "-wavefrontsize16,";
122 if (!FS.contains_insensitive("wavefrontsize32"))
123 FullFS += "-wavefrontsize32,";
124 if (!FS.contains_insensitive("wavefrontsize64"))
125 FullFS += "-wavefrontsize64,";
126 }
127
128 FullFS += FS;
129
130 ParseSubtargetFeatures(GPU, /*TuneCPU*/ GPU, FullFS);
131
132 // Implement the "generic" processors, which acts as the default when no
133 // generation features are enabled (e.g for -mcpu=''). HSA OS defaults to
134 // the first amdgcn target that supports flat addressing. Other OSes defaults
135 // to the first amdgcn target.
138 // Assume wave64 for the unknown target, if not explicitly set.
139 if (getWavefrontSizeLog2() == 0)
141 } else if (!hasFeature(AMDGPU::FeatureWavefrontSize32) &&
142 !hasFeature(AMDGPU::FeatureWavefrontSize64)) {
143 // If there is no default wave size it must be a generation before gfx10,
144 // these have FeatureWavefrontSize64 in their definition already. For gfx10+
145 // set wave32 as a default.
146 ToggleFeature(AMDGPU::FeatureWavefrontSize32);
148 }
149
150 // We don't support FP64 for EG/NI atm.
152
153 // Targets must either support 64-bit offsets for MUBUF instructions, and/or
154 // support flat operations, otherwise they cannot access a 64-bit global
155 // address space
156 assert(hasAddr64() || hasFlat());
157 // Unless +-flat-for-global is specified, turn on FlatForGlobal for targets
158 // that do not support ADDR64 variants of MUBUF instructions. Such targets
159 // cannot use a 64 bit offset with a MUBUF instruction to access the global
160 // address space
161 if (!hasAddr64() && !FS.contains("flat-for-global") && !UseFlatForGlobal) {
162 ToggleFeature(AMDGPU::FeatureUseFlatForGlobal);
163 UseFlatForGlobal = true;
164 }
165 // Unless +-flat-for-global is specified, use MUBUF instructions for global
166 // address space access if flat operations are not available.
167 if (!hasFlat() && !FS.contains("flat-for-global") && UseFlatForGlobal) {
168 ToggleFeature(AMDGPU::FeatureUseFlatForGlobal);
169 UseFlatForGlobal = false;
170 }
171
172 // Set defaults if needed.
173 if (MaxPrivateElementSize == 0)
175
176 if (LDSBankCount == 0)
177 LDSBankCount = 32;
178
179 if (MaxWavesPerEU == 0)
180 MaxWavesPerEU = 10;
181
182 if (FlatOffsetBitWidth == 0)
184
188 getTargetID().getGPUKind(), isFullSIMDMode());
189 // LDS allocation granularity is in bytes.
192
195
196 // InstCacheLineSize is set from TableGen subtarget features
197 // (FeatureInstCacheLineSize64 / FeatureInstCacheLineSize128).
198 // Fall back to 64 if no feature was specified (e.g. generic targets).
199 if (InstCacheLineSize == 0)
201
203 "InstCacheLineSize must be a power of 2");
204
205 // Apply the module flag's xnack setting if the target supports on/off modes.
206 // Targets without on/off mode support have xnack always on and ignore module
207 // flags.
208 if (hasXNACKOnOffModes())
209 TargetID.setXnackSetting(XnackSetting);
210
211 // Apply the module flag's sramecc setting if the target supports on/off
212 // modes. Targets with sramecc hardwired on ignore module flags.
213 if (hasSRAMECCOnOffModes())
214 TargetID.setSramEccSetting(SramEccSetting);
215
216 return *this;
217}
218
220 LLVMContext &Ctx = F.getContext();
221 if (hasFeature(AMDGPU::FeatureWavefrontSize32) &&
222 hasFeature(AMDGPU::FeatureWavefrontSize64)) {
223 Ctx.diagnose(DiagnosticInfoUnsupported(
224 F, "must specify exactly one of wavefrontsize32 and wavefrontsize64"));
225 }
226}
227
228// TODO: Validate subarch for subtarget
229
231 const GCNTargetMachine &TM, bool BufferOOBRelaxed,
235 : // clang-format off
236 AMDGPUGenSubtargetInfo(TT, GPU, /*TuneCPU*/ GPU, FS),
237 AMDGPUSubtarget(TT),
238 TargetID(AMDGPU::createAMDGPUTargetID(*this, "")),
239 InstrItins(getInstrItineraryForCPU(GPU)),
242 InstrInfo(initializeSubtargetDependencies(TT, GPU, FS, XnackSetting,
244 TLInfo(TM, *this),
245 // Frame index expansion sometimes assumes the low bit of SP is 0
246 FrameLowering(TargetFrameLowering::StackGrowsUp, getStackAlignment(), 0,
247 /*TransAl=*/Align(4)) {
248
249 // clang-format on
250
251 LLVM_DEBUG(dbgs() << "xnack setting for subtarget: "
252 << TargetID.getXnackSetting() << '\n');
253 LLVM_DEBUG(dbgs() << "sramecc setting for subtarget: "
254 << TargetID.getSramEccSetting() << '\n');
255
257
258 TSInfo = std::make_unique<AMDGPUSelectionDAGInfo>();
259
260 CallLoweringInfo = std::make_unique<AMDGPUCallLowering>(*getTargetLowering());
261 InlineAsmLoweringInfo =
262 std::make_unique<InlineAsmLowering>(getTargetLowering());
263 Legalizer = std::make_unique<AMDGPULegalizerInfo>(*this, TM);
264 RegBankInfo = std::make_unique<AMDGPURegisterBankInfo>(*this);
265 InstSelector =
266 std::make_unique<AMDGPUInstructionSelector>(*this, *RegBankInfo);
267}
268
270 return TSInfo.get();
271}
272
273unsigned GCNSubtarget::getConstantBusLimit(unsigned Opcode) const {
274 if (getGeneration() < GFX10)
275 return 1;
276
277 switch (Opcode) {
278 case AMDGPU::V_LSHLREV_B64_e64:
279 case AMDGPU::V_LSHLREV_B64_gfx10:
280 case AMDGPU::V_LSHLREV_B64_e64_gfx11:
281 case AMDGPU::V_LSHLREV_B64_e32_gfx12:
282 case AMDGPU::V_LSHLREV_B64_e64_gfx12:
283 case AMDGPU::V_LSHL_B64_e64:
284 case AMDGPU::V_LSHRREV_B64_e64:
285 case AMDGPU::V_LSHRREV_B64_gfx10:
286 case AMDGPU::V_LSHRREV_B64_e64_gfx11:
287 case AMDGPU::V_LSHRREV_B64_e64_gfx12:
288 case AMDGPU::V_LSHR_B64_e64:
289 case AMDGPU::V_ASHRREV_I64_e64:
290 case AMDGPU::V_ASHRREV_I64_gfx10:
291 case AMDGPU::V_ASHRREV_I64_e64_gfx11:
292 case AMDGPU::V_ASHRREV_I64_e64_gfx12:
293 case AMDGPU::V_ASHR_I64_e64:
294 return 1;
295 }
296
297 return 2;
298}
299
300/// This list was mostly derived from experimentation.
301bool GCNSubtarget::zeroesHigh16BitsOfDest(unsigned Opcode) const {
302 switch (Opcode) {
303 case AMDGPU::V_CVT_F16_F32_e32:
304 case AMDGPU::V_CVT_F16_F32_e64:
305 case AMDGPU::V_CVT_F16_U16_e32:
306 case AMDGPU::V_CVT_F16_U16_e64:
307 case AMDGPU::V_CVT_F16_I16_e32:
308 case AMDGPU::V_CVT_F16_I16_e64:
309 case AMDGPU::V_RCP_F16_e64:
310 case AMDGPU::V_RCP_F16_e32:
311 case AMDGPU::V_RSQ_F16_e64:
312 case AMDGPU::V_RSQ_F16_e32:
313 case AMDGPU::V_SQRT_F16_e64:
314 case AMDGPU::V_SQRT_F16_e32:
315 case AMDGPU::V_LOG_F16_e64:
316 case AMDGPU::V_LOG_F16_e32:
317 case AMDGPU::V_EXP_F16_e64:
318 case AMDGPU::V_EXP_F16_e32:
319 case AMDGPU::V_SIN_F16_e64:
320 case AMDGPU::V_SIN_F16_e32:
321 case AMDGPU::V_COS_F16_e64:
322 case AMDGPU::V_COS_F16_e32:
323 case AMDGPU::V_FLOOR_F16_e64:
324 case AMDGPU::V_FLOOR_F16_e32:
325 case AMDGPU::V_CEIL_F16_e64:
326 case AMDGPU::V_CEIL_F16_e32:
327 case AMDGPU::V_TRUNC_F16_e64:
328 case AMDGPU::V_TRUNC_F16_e32:
329 case AMDGPU::V_RNDNE_F16_e64:
330 case AMDGPU::V_RNDNE_F16_e32:
331 case AMDGPU::V_FRACT_F16_e64:
332 case AMDGPU::V_FRACT_F16_e32:
333 case AMDGPU::V_FREXP_MANT_F16_e64:
334 case AMDGPU::V_FREXP_MANT_F16_e32:
335 case AMDGPU::V_FREXP_EXP_I16_F16_e64:
336 case AMDGPU::V_FREXP_EXP_I16_F16_e32:
337 case AMDGPU::V_LDEXP_F16_e64:
338 case AMDGPU::V_LDEXP_F16_e32:
339 case AMDGPU::V_LSHLREV_B16_e64:
340 case AMDGPU::V_LSHLREV_B16_e32:
341 case AMDGPU::V_LSHRREV_B16_e64:
342 case AMDGPU::V_LSHRREV_B16_e32:
343 case AMDGPU::V_ASHRREV_I16_e64:
344 case AMDGPU::V_ASHRREV_I16_e32:
345 case AMDGPU::V_ADD_U16_e64:
346 case AMDGPU::V_ADD_U16_e32:
347 case AMDGPU::V_SUB_U16_e64:
348 case AMDGPU::V_SUB_U16_e32:
349 case AMDGPU::V_SUBREV_U16_e64:
350 case AMDGPU::V_SUBREV_U16_e32:
351 case AMDGPU::V_MUL_LO_U16_e64:
352 case AMDGPU::V_MUL_LO_U16_e32:
353 case AMDGPU::V_ADD_F16_e64:
354 case AMDGPU::V_ADD_F16_e32:
355 case AMDGPU::V_SUB_F16_e64:
356 case AMDGPU::V_SUB_F16_e32:
357 case AMDGPU::V_SUBREV_F16_e64:
358 case AMDGPU::V_SUBREV_F16_e32:
359 case AMDGPU::V_MUL_F16_e64:
360 case AMDGPU::V_MUL_F16_e32:
361 case AMDGPU::V_MAX_F16_e64:
362 case AMDGPU::V_MAX_F16_e32:
363 case AMDGPU::V_MIN_F16_e64:
364 case AMDGPU::V_MIN_F16_e32:
365 case AMDGPU::V_MAX_U16_e64:
366 case AMDGPU::V_MAX_U16_e32:
367 case AMDGPU::V_MIN_U16_e64:
368 case AMDGPU::V_MIN_U16_e32:
369 case AMDGPU::V_MAX_I16_e64:
370 case AMDGPU::V_MAX_I16_e32:
371 case AMDGPU::V_MIN_I16_e64:
372 case AMDGPU::V_MIN_I16_e32:
373 case AMDGPU::V_MAD_F16_e64:
374 case AMDGPU::V_MAD_U16_e64:
375 case AMDGPU::V_MAD_I16_e64:
376 case AMDGPU::V_FMA_F16_e64:
377 case AMDGPU::V_DIV_FIXUP_F16_e64:
378 // On gfx10, all 16-bit instructions preserve the high bits.
380 case AMDGPU::V_MADAK_F16:
381 case AMDGPU::V_MADMK_F16:
382 case AMDGPU::V_MAC_F16_e64:
383 case AMDGPU::V_MAC_F16_e32:
384 case AMDGPU::V_FMAMK_F16:
385 case AMDGPU::V_FMAAK_F16:
386 case AMDGPU::V_FMAC_F16_e64:
387 case AMDGPU::V_FMAC_F16_e32:
388 // In gfx9, the preferred handling of the unused high 16-bits changed. Most
389 // instructions maintain the legacy behavior of 0ing. Some instructions
390 // changed to preserving the high bits.
392 case AMDGPU::V_MAD_MIXLO_F16:
393 case AMDGPU::V_MAD_MIXHI_F16:
394 default:
395 return false;
396 }
397}
398
400 const SchedRegion &Region) const {
401 // Track register pressure so the scheduler can try to decrease
402 // pressure once register usage is above the threshold defined by
403 // SIRegisterInfo::getRegPressureSetLimit()
404 Policy.ShouldTrackPressure = true;
405
406 const Function &F = Region.RegionBegin->getMF()->getFunction();
407 if (AMDGPU::getSchedStrategy(F) == "coexec") {
408 Policy.OnlyTopDown = true;
409 Policy.OnlyBottomUp = false;
410 return;
411 }
412
413 // Enabling both top down and bottom up scheduling seems to give us less
414 // register spills than just using one of these approaches on its own.
415 Policy.OnlyTopDown = false;
416 Policy.OnlyBottomUp = false;
417
418 // Enabling ShouldTrackLaneMasks crashes the SI Machine Scheduler.
419 if (!enableSIScheduler())
420 Policy.ShouldTrackLaneMasks = true;
421}
422
424 const SchedRegion &Region) const {
425 const Function &F = Region.RegionBegin->getMF()->getFunction();
426 Attribute PostRADirectionAttr = F.getFnAttribute("amdgpu-post-ra-direction");
427 if (!PostRADirectionAttr.isValid())
428 return;
429
430 StringRef PostRADirectionStr = PostRADirectionAttr.getValueAsString();
431 if (PostRADirectionStr == "topdown") {
432 Policy.OnlyTopDown = true;
433 Policy.OnlyBottomUp = false;
434 } else if (PostRADirectionStr == "bottomup") {
435 Policy.OnlyTopDown = false;
436 Policy.OnlyBottomUp = true;
437 } else if (PostRADirectionStr == "bidirectional") {
438 Policy.OnlyTopDown = false;
439 Policy.OnlyBottomUp = false;
440 } else {
442 F, F.getSubprogram(), "invalid value for postRA direction attribute");
443 F.getContext().diagnose(Diag);
444 }
445
446 LLVM_DEBUG({
447 const char *DirStr = "default";
448 if (Policy.OnlyTopDown && !Policy.OnlyBottomUp)
449 DirStr = "topdown";
450 else if (!Policy.OnlyTopDown && Policy.OnlyBottomUp)
451 DirStr = "bottomup";
452 else if (!Policy.OnlyTopDown && !Policy.OnlyBottomUp)
453 DirStr = "bidirectional";
454
455 dbgs() << "Post-MI-sched direction (" << F.getName() << "): " << DirStr
456 << '\n';
457 });
458}
459
464
466 if (isWave32()) {
467 // Fix implicit $vcc operands after MIParser has verified that they match
468 // the instruction definitions.
469 for (auto &MBB : MF) {
470 for (auto &MI : MBB)
471 InstrInfo.fixImplicitOperands(MI);
472 }
473 }
474}
475
477 return InstrInfo.pseudoToMCOpcode(AMDGPU::V_MAD_F16_e64) != -1;
478}
479
481 return hasVGPRIndexMode() && (!hasMovrel() || EnableVGPRIndexMode);
482}
483
484bool GCNSubtarget::useAA() const { return UseAA; }
485
486unsigned GCNSubtarget::getOccupancyWithNumSGPRs(unsigned SGPRs) const {
488}
489
490unsigned
492 unsigned DynamicVGPRBlockSize) const {
494 DynamicVGPRBlockSize);
495}
496
497unsigned
498GCNSubtarget::getBaseReservedNumSGPRs(const bool HasFlatScratch) const {
500 return 2; // VCC. FLAT_SCRATCH and XNACK are no longer in SGPRs.
501
502 if (HasFlatScratch || HasArchitectedFlatScratch) {
504 return 6; // FLAT_SCRATCH, XNACK, VCC (in that order).
506 return 4; // FLAT_SCRATCH, VCC (in that order).
507 }
508
509 if (isXNACKEnabled())
510 return 4; // XNACK, VCC (in that order).
511 return 2; // VCC.
512}
513
518
520 // In principle we do not need to reserve SGPR pair used for flat_scratch if
521 // we know flat instructions do not access the stack anywhere in the
522 // program. For now assume it's needed if we have flat instructions.
523 const bool KernelUsesFlatScratch = hasFlatAddressSpace();
524 return getBaseReservedNumSGPRs(KernelUsesFlatScratch);
525}
526
527std::pair<unsigned, unsigned>
529 unsigned NumSGPRs, unsigned NumVGPRs) const {
530 unsigned DynamicVGPRBlockSize = AMDGPU::getDynamicVGPRBlockSize(F);
531 auto [MinOcc, MaxOcc] = getOccupancyWithWorkGroupSizes(LDSSize, F);
532 unsigned SGPROcc = getOccupancyWithNumSGPRs(NumSGPRs);
533 unsigned VGPROcc = getOccupancyWithNumVGPRs(NumVGPRs, DynamicVGPRBlockSize);
534
535 // Maximum occupancy may be further limited by high SGPR/VGPR usage.
536 MaxOcc = std::min({MaxOcc, SGPROcc, VGPROcc});
537 return {std::min(MinOcc, MaxOcc), MaxOcc};
538}
539
541 const Function &F, std::pair<unsigned, unsigned> WavesPerEU,
542 unsigned PreloadedSGPRs, unsigned ReservedNumSGPRs) const {
543 // Compute maximum number of SGPRs function can use using default/requested
544 // minimum number of waves per execution unit.
545 unsigned MaxNumSGPRs = getMaxNumSGPRs(WavesPerEU.first, false);
546 unsigned MaxAddressableNumSGPRs = getMaxNumSGPRs(WavesPerEU.first, true);
547
548 // Check if maximum number of SGPRs was explicitly requested using
549 // "amdgpu-num-sgpr" attribute.
550 unsigned Requested =
551 F.getFnAttributeAsParsedInteger("amdgpu-num-sgpr", MaxNumSGPRs);
552
553 if (Requested != MaxNumSGPRs) {
554 // Make sure requested value does not violate subtarget's specifications.
555 if (Requested && (Requested <= ReservedNumSGPRs))
556 Requested = 0;
557
558 // If more SGPRs are required to support the input user/system SGPRs,
559 // increase to accommodate them.
560 //
561 // FIXME: This really ends up using the requested number of SGPRs + number
562 // of reserved special registers in total. Theoretically you could re-use
563 // the last input registers for these special registers, but this would
564 // require a lot of complexity to deal with the weird aliasing.
565 unsigned InputNumSGPRs = PreloadedSGPRs;
566 if (Requested && Requested < InputNumSGPRs)
567 Requested = InputNumSGPRs;
568
569 // Make sure requested value is compatible with values implied by
570 // default/requested minimum/maximum number of waves per execution unit.
571 if (Requested && Requested > getMaxNumSGPRs(WavesPerEU.first, false))
572 Requested = 0;
573 if (WavesPerEU.second && Requested &&
574 Requested < getMinNumSGPRs(WavesPerEU.second))
575 Requested = 0;
576
577 if (Requested)
578 MaxNumSGPRs = Requested;
579 }
580
581 if (hasSGPRInitBug())
583
584 return std::min(MaxNumSGPRs - ReservedNumSGPRs, MaxAddressableNumSGPRs);
585}
586
588 const Function &F = MF.getFunction();
592}
593
595 using USI = GCNUserSGPRUsageInfo;
596 // Max number of user SGPRs
597 const unsigned MaxUserSGPRs =
598 USI::getNumUserSGPRForField(USI::PrivateSegmentBufferID) +
599 USI::getNumUserSGPRForField(USI::DispatchPtrID) +
600 USI::getNumUserSGPRForField(USI::QueuePtrID) +
601 USI::getNumUserSGPRForField(USI::KernargSegmentPtrID) +
602 USI::getNumUserSGPRForField(USI::DispatchIdID) +
603 USI::getNumUserSGPRForField(USI::FlatScratchInitID) +
604 USI::getNumUserSGPRForField(USI::ImplicitBufferPtrID);
605
606 // Max number of system SGPRs
607 const unsigned MaxSystemSGPRs = 1 + // WorkGroupIDX
608 1 + // WorkGroupIDY
609 1 + // WorkGroupIDZ
610 1 + // WorkGroupInfo
611 1; // private segment wave byte offset
612
613 // Max number of synthetic SGPRs
614 const unsigned SyntheticSGPRs = 1; // LDSKernelId
615
616 return MaxUserSGPRs + MaxSystemSGPRs + SyntheticSGPRs;
617}
618
623
625 const Function &F, std::pair<unsigned, unsigned> NumVGPRBounds) const {
626 const auto [Min, Max] = NumVGPRBounds;
627
628 // Check if maximum number of VGPRs was explicitly requested using
629 // "amdgpu-num-vgpr" attribute.
630
631 unsigned Requested = F.getFnAttributeAsParsedInteger("amdgpu-num-vgpr", Max);
632 if (Requested != Max && hasGFX90AInsts())
633 Requested *= 2;
634
635 // Make sure requested value is inside the range of possible VGPR usage.
636 return std::clamp(Requested, Min, Max);
637}
638
640 unsigned DynamicVGPRBlockSize = AMDGPU::getDynamicVGPRBlockSize(F);
641 std::pair<unsigned, unsigned> Waves = getWavesPerEU(F);
642
643 unsigned MaxNumVGPRs = getBaseMaxNumVGPRs(
644 F, {getMinNumVGPRs(Waves.second, DynamicVGPRBlockSize),
645 getMaxNumVGPRs(Waves.first, DynamicVGPRBlockSize)});
646
647 // In DVGPR mode, a wave launches with a single VGPR block allocated. Applied
648 // after getBaseMaxNumVGPRs so "amdgpu-num-vgpr" cannot raise it back up.
649 if (DynamicVGPRBlockSize != 0 &&
650 AMDGPU::isEntryFunctionCC(F.getCallingConv()))
651 MaxNumVGPRs = std::min(MaxNumVGPRs, DynamicVGPRBlockSize);
652
653 return MaxNumVGPRs;
654}
655
657 return getMaxNumVGPRs(MF.getFunction());
658}
659
660std::pair<unsigned, unsigned>
662 const unsigned MaxVectorRegs = getMaxNumVGPRs(F);
663
664 unsigned MaxNumVGPRs = MaxVectorRegs;
665 unsigned MaxNumAGPRs = 0;
666 unsigned NumArchVGPRs = getAddressableNumArchVGPRs();
667
668 // On GFX90A, the number of VGPRs and AGPRs need not be equal. Theoretically,
669 // a wave may have up to 512 total vector registers combining together both
670 // VGPRs and AGPRs. Hence, in an entry function without calls and without
671 // AGPRs used within it, it is possible to use the whole vector register
672 // budget for VGPRs.
673 //
674 // TODO: it shall be possible to estimate maximum AGPR/VGPR pressure and split
675 // register file accordingly.
676 if (hasGFX90AInsts()) {
677 unsigned MinNumAGPRs = 0;
678 const unsigned TotalNumAGPRs = AMDGPU::AGPR_32RegClass.getNumRegs();
679
680 const std::pair<unsigned, unsigned> DefaultNumAGPR = {~0u, ~0u};
681
682 // TODO: The lower bound should probably force the number of required
683 // registers up, overriding amdgpu-waves-per-eu.
684 std::tie(MinNumAGPRs, MaxNumAGPRs) =
685 AMDGPU::getIntegerPairAttribute(F, "amdgpu-agpr-alloc", DefaultNumAGPR,
686 /*OnlyFirstRequired=*/true);
687
688 if (MinNumAGPRs == DefaultNumAGPR.first) {
689 // Default to splitting half the registers if AGPRs are required.
690 MinNumAGPRs = MaxNumAGPRs = MaxVectorRegs / 2;
691 } else {
692 // Align to accum_offset's allocation granularity.
693 MinNumAGPRs = alignTo(MinNumAGPRs, 4);
694
695 MinNumAGPRs = std::min(MinNumAGPRs, TotalNumAGPRs);
696 }
697
698 // Clamp values to be inbounds of our limits, and ensure min <= max.
699
700 MaxNumAGPRs = std::min(std::max(MinNumAGPRs, MaxNumAGPRs), MaxVectorRegs);
701 MinNumAGPRs = std::min({MinNumAGPRs, TotalNumAGPRs, MaxNumAGPRs});
702
703 MaxNumVGPRs = std::min(MaxVectorRegs - MinNumAGPRs, NumArchVGPRs);
704 MaxNumAGPRs = std::min(MaxVectorRegs - MaxNumVGPRs, MaxNumAGPRs);
705
706 assert(MaxNumVGPRs + MaxNumAGPRs <= MaxVectorRegs &&
707 MaxNumAGPRs <= TotalNumAGPRs && MaxNumVGPRs <= NumArchVGPRs &&
708 "invalid register counts");
709 } else if (hasMAIInsts()) {
710 // On gfx908 the number of AGPRs always equals the number of VGPRs.
711 MaxNumAGPRs = MaxNumVGPRs = MaxVectorRegs;
712 }
713
714 return std::pair(MaxNumVGPRs, MaxNumAGPRs);
715}
716
717// Check to which source operand UseOpIdx points to and return a pointer to the
718// operand of the corresponding source modifier.
719// Return nullptr if UseOpIdx either doesn't point to src0/1/2 or if there is no
720// operand for the corresponding source modifier.
721static const MachineOperand *
723 const SIInstrInfo &InstrInfo) {
724 AMDGPU::OpName UseName =
725 AMDGPU::getOperandIdxName(UseI.getOpcode(), UseOpIdx);
726 switch (UseName) {
727 case AMDGPU::OpName::src0:
728 return InstrInfo.getNamedOperand(UseI, AMDGPU::OpName::src0_modifiers);
729 case AMDGPU::OpName::src1:
730 return InstrInfo.getNamedOperand(UseI, AMDGPU::OpName::src1_modifiers);
731 case AMDGPU::OpName::src2:
732 return InstrInfo.getNamedOperand(UseI, AMDGPU::OpName::src2_modifiers);
733 default:
734 return nullptr;
735 }
736}
737
738// Get the subreg idx of the subreg that is used by the given instruction
739// operand, considering the given op_sel modifier.
740// Return 0 if the whole register is used or as a conservative fallback.
742 const SIInstrInfo &InstrInfo,
743 const MachineInstr &I,
744 const MachineOperand &Op) {
745 if (!InstrInfo.isVOP3P(I) || InstrInfo.isWMMA(I) || InstrInfo.isSWMMAC(I))
746 return AMDGPU::NoSubRegister;
747
748 const MachineOperand *OpMod =
749 getVOP3PSourceModifierFromOpIdx(I, Op.getOperandNo(), InstrInfo);
750 if (!OpMod)
751 return AMDGPU::NoSubRegister;
752
753 // Note: the FMA_MIX* and MAD_MIX* instructions have different semantics for
754 // the op_sel and op_sel_hi source modifiers:
755 // - op_sel: selects low/high operand bits as input to the operation;
756 // has only meaning for 16-bit source operands
757 // - op_sel_hi: specifies the size of the source operands (16 or 32 bits);
758 // a value of 0 indicates 32 bit, 1 indicates 16 bit
759 // For the other VOP3P instructions, the semantics are:
760 // - op_sel: selects low/high operand bits as input to the operation which
761 // results in the lower-half of the destination
762 // - op_sel_hi: selects the low/high operand bits as input to the operation
763 // which results in the higher-half of the destination
764 int64_t OpSel = OpMod->getImm() & SISrcMods::OP_SEL_0;
765 int64_t OpSelHi = OpMod->getImm() & SISrcMods::OP_SEL_1;
766
767 // Check if all parts of the register are being used (= op_sel and op_sel_hi
768 // differ for VOP3P or op_sel_hi=0 for VOP3PMix). In that case we can return
769 // early.
770 if ((!InstrInfo.isVOP3PMix(I) && (!OpSel || !OpSelHi) &&
771 (OpSel || OpSelHi)) ||
772 (InstrInfo.isVOP3PMix(I) && !OpSelHi))
773 return AMDGPU::NoSubRegister;
774
775 const MachineRegisterInfo &MRI = I.getParent()->getParent()->getRegInfo();
776 const TargetRegisterClass *RC = TRI.getRegClassForOperandReg(MRI, Op);
777
778 if (unsigned SubRegIdx = OpSel ? AMDGPU::sub1 : AMDGPU::sub0;
779 TRI.getSubClassWithSubReg(RC, SubRegIdx) == RC)
780 return SubRegIdx;
781 if (unsigned SubRegIdx = OpSel ? AMDGPU::hi16 : AMDGPU::lo16;
782 TRI.getSubClassWithSubReg(RC, SubRegIdx) == RC)
783 return SubRegIdx;
784
785 return AMDGPU::NoSubRegister;
786}
787
788Register GCNSubtarget::getRealSchedDependency(const MachineInstr &DefI,
789 int DefOpIdx,
790 const MachineInstr &UseI,
791 int UseOpIdx) const {
792 const SIRegisterInfo *TRI = getRegisterInfo();
793 const MachineOperand &DefOp = DefI.getOperand(DefOpIdx);
794 const MachineOperand &UseOp = UseI.getOperand(UseOpIdx);
795 Register DefReg = DefOp.getReg();
796 Register UseReg = UseOp.getReg();
797
798 // If the registers aren't restricted to a sub-register, there is no point in
799 // further analysis. This check makes only sense for virtual registers because
800 // physical registers may form a tuple and thus be part of a superregister
801 // although they are not a subregister themselves (vgpr0 is a "subreg" of
802 // vgpr0_vgpr1 without being a subreg in itself).
803 unsigned DefSubRegIdx = DefOp.getSubReg();
804 if (DefReg.isVirtual() && DefSubRegIdx == AMDGPU::NoSubRegister)
805 return DefReg;
806 unsigned UseSubRegIdx = getEffectiveSubRegIdx(*TRI, InstrInfo, UseI, UseOp);
807 if (UseReg.isVirtual() && UseSubRegIdx == AMDGPU::NoSubRegister)
808 return DefReg;
809
810 if (!TRI->checkSubRegInterference(DefReg, DefSubRegIdx, UseReg, UseSubRegIdx))
811 return Register(); // No real dependency
812
813 // UseReg might be smaller or larger than DefReg, depending on the subreg and
814 // on whether DefReg is a subreg, too. -> Find the smaller one. This does not
815 // apply to virtual registers because we cannot construct a subreg for them.
816 if (DefReg.isVirtual())
817 return DefReg;
818 MCRegister DefMCReg =
819 DefSubRegIdx ? TRI->getSubReg(DefReg, DefSubRegIdx) : DefReg.asMCReg();
820 MCRegister UseMCReg =
821 UseSubRegIdx ? TRI->getSubReg(UseReg, UseSubRegIdx) : UseReg.asMCReg();
822 return TRI->isSubRegisterEq(DefMCReg, UseMCReg) ? UseMCReg : DefMCReg;
823}
824
826 SUnit *Def, int DefOpIdx, SUnit *Use, int UseOpIdx, SDep &Dep,
827 const TargetSchedModel *SchedModel) const {
828 if (Dep.getKind() != SDep::Kind::Data || !Dep.getReg() || !Def->isInstr() ||
829 !Use->isInstr())
830 return;
831
832 MachineInstr *DefI = Def->getInstr();
833 MachineInstr *UseI = Use->getInstr();
834
835 // Check for false latency on $tensorcnt / $asynccnt dependencies
836 if (Dep.getReg() == AMDGPU::TENSORcnt || Dep.getReg() == AMDGPU::ASYNCcnt) {
837 unsigned UseOp = UseI->getOpcode();
838 // Do not adjust latency for load->s_wait
839 bool IsBarrierCase =
840 InstrInfo.isLDSDMA(*DefI) &&
841 (UseOp == AMDGPU::S_WAIT_TENSORCNT || UseOp == AMDGPU::S_WAIT_ASYNCCNT);
842 if (!IsBarrierCase) {
843 Dep.setLatency(1);
844 return;
845 }
846 }
847
848 if (Register Reg = getRealSchedDependency(*DefI, DefOpIdx, *UseI, UseOpIdx)) {
849 Dep.setReg(Reg);
850 } else {
851 Dep = SDep(Def, SDep::Artificial);
852 return; // This is not a data dependency anymore.
853 }
854
855 if (DefI->isBundle()) {
857 auto Reg = Dep.getReg();
860 unsigned Lat = 0;
861 for (++I; I != E && I->isBundledWithPred(); ++I) {
862 if (I->isMetaInstruction())
863 continue;
864 if (I->modifiesRegister(Reg, TRI))
865 Lat = InstrInfo.getInstrLatency(getInstrItineraryData(), *I);
866 else if (Lat)
867 --Lat;
868 }
869 Dep.setLatency(Lat);
870 } else if (UseI->isBundle()) {
872 auto Reg = Dep.getReg();
875 unsigned Lat = InstrInfo.getInstrLatency(getInstrItineraryData(), *DefI);
876 for (++I; I != E && I->isBundledWithPred() && Lat; ++I) {
877 if (I->isMetaInstruction())
878 continue;
879 if (I->readsRegister(Reg, TRI))
880 break;
881 --Lat;
882 }
883 Dep.setLatency(Lat);
884 } else if (Dep.getLatency() == 0 && Dep.getReg() == AMDGPU::VCC_LO) {
885 // Work around the fact that SIInstrInfo::fixImplicitOperands modifies
886 // implicit operands which come from the MCInstrDesc, which can fool
887 // ScheduleDAGInstrs::addPhysRegDataDeps into treating them as implicit
888 // pseudo operands.
889 Dep.setLatency(InstrInfo.getSchedModel().computeOperandLatency(
890 DefI, DefOpIdx, UseI, UseOpIdx));
891 }
892}
893
896 return 0; // Not MIMG encoding.
897
898 if (NSAThreshold.getNumOccurrences() > 0)
899 return std::max(NSAThreshold.getValue(), 2u);
900
902 "amdgpu-nsa-threshold", -1);
903 if (Value > 0)
904 return std::max(Value, 2);
905
906 return NSAThreshold;
907}
908
910 const GCNSubtarget &ST)
911 : ST(ST) {
912 const CallingConv::ID CC = F.getCallingConv();
913 const bool IsKernel =
915
916 if (IsKernel && (!F.arg_empty() || ST.getImplicitArgNumBytes(F) != 0))
917 KernargSegmentPtr = true;
918
919 bool IsAmdHsaOrMesa = ST.isAmdHsaOrMesa(F);
920 if (IsAmdHsaOrMesa && !ST.hasFlatScratchEnabled())
921 PrivateSegmentBuffer = true;
922 else if (ST.isMesaGfxShader(F))
923 ImplicitBufferPtr = true;
924
925 if (!AMDGPU::isGraphics(CC)) {
926 if (!F.hasFnAttribute("amdgpu-no-dispatch-ptr"))
927 DispatchPtr = true;
928
929 // FIXME: Can this always be disabled with < COv5?
930 if (!F.hasFnAttribute("amdgpu-no-queue-ptr"))
931 QueuePtr = true;
932
933 if (!F.hasFnAttribute("amdgpu-no-dispatch-id"))
934 DispatchID = true;
935 }
936
937 if (ST.hasFlatAddressSpace() && AMDGPU::isEntryFunctionCC(CC) &&
938 (IsAmdHsaOrMesa || ST.hasFlatScratchEnabled()) &&
939 // FlatScratchInit cannot be true for graphics CC if
940 // hasFlatScratchEnabled() is false.
941 (ST.hasFlatScratchEnabled() ||
942 (!AMDGPU::isGraphics(CC) &&
943 !F.hasFnAttribute("amdgpu-no-flat-scratch-init"))) &&
944 !ST.hasArchitectedFlatScratch()) {
945 FlatScratchInit = true;
946 }
947
949 NumUsedUserSGPRs += getNumUserSGPRForField(ImplicitBufferPtrID);
950
953
954 if (hasDispatchPtr())
955 NumUsedUserSGPRs += getNumUserSGPRForField(DispatchPtrID);
956
957 if (hasQueuePtr())
958 NumUsedUserSGPRs += getNumUserSGPRForField(QueuePtrID);
959
961 NumUsedUserSGPRs += getNumUserSGPRForField(KernargSegmentPtrID);
962
963 if (hasDispatchID())
964 NumUsedUserSGPRs += getNumUserSGPRForField(DispatchIdID);
965
966 if (hasFlatScratchInit())
967 NumUsedUserSGPRs += getNumUserSGPRForField(FlatScratchInitID);
968
970 NumUsedUserSGPRs += getNumUserSGPRForField(PrivateSegmentSizeID);
971}
972
974 assert(NumKernargPreloadSGPRs + NumSGPRs <= AMDGPU::getMaxNumUserSGPRs(ST));
975 NumKernargPreloadSGPRs += NumSGPRs;
976 NumUsedUserSGPRs += NumSGPRs;
977}
978
980 return AMDGPU::getMaxNumUserSGPRs(ST) - NumUsedUserSGPRs;
981}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file describes how to lower LLVM calls to machine code calls.
This file declares the targeting of the InstructionSelector class for AMDGPU.
This file declares the targeting of the Machinelegalizer class for AMDGPU.
This file declares the targeting of the RegisterBankInfo class for AMDGPU.
static cl::opt< bool > SramEccSetting("amdgpu-sramecc", cl::desc("Force amdgpu.sramecc for testing"), cl::ReallyHidden)
static cl::opt< bool > XnackSetting("amdgpu-xnack", cl::desc("Force amdgpu.xnack value for testing"), cl::ReallyHidden)
The AMDGPU TargetMachine interface definition for hw codegen targets.
MachineBasicBlock & MBB
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static AMDGPUSubtarget::Generation computeDefaultGeneration(const Triple &TT)
static cl::opt< unsigned > NSAThreshold("amdgpu-nsa-threshold", cl::desc("Number of addresses from which to enable MIMG NSA."), cl::init(2), cl::Hidden)
static cl::opt< bool > EnableVGPRIndexMode("amdgpu-vgpr-index-mode", cl::desc("Use GPR indexing mode instead of movrel for vector indexing"), cl::init(false))
static cl::opt< bool > UseAA("amdgpu-use-aa-in-codegen", cl::desc("Enable the use of AA during codegen."), cl::init(true))
static const MachineOperand * getVOP3PSourceModifierFromOpIdx(const MachineInstr &UseI, int UseOpIdx, const SIInstrInfo &InstrInfo)
static unsigned getEffectiveSubRegIdx(const SIRegisterInfo &TRI, const SIInstrInfo &InstrInfo, const MachineInstr &I, const MachineOperand &Op)
AMD GCN specific subclass of TargetSubtarget.
static Register UseReg(const MachineOperand &MO)
IRTranslator LLVM IR MI
This file describes how to lower LLVM inline asm to machine code INLINEASM.
static bool hasFeature(StringRef Feature, const FeatureBitset &FeatureBits, ArrayRef< SubtargetFeatureKV > ProcFeatures)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
if(PassOpts->AAPipeline)
This file defines the SmallString class.
#define LLVM_DEBUG(...)
Definition Debug.h:119
std::pair< unsigned, unsigned > getWavesPerEU(const Function &F) const
std::pair< unsigned, unsigned > getOccupancyWithWorkGroupSizes(uint32_t LDSBytes, const Function &F) const
Subtarget's minimum/maximum occupancy, in number of waves per EU, that can be achieved when the only ...
unsigned getWavefrontSizeLog2() const
AMDGPUSubtarget(const Triple &TT)
unsigned AddressableLocalMemorySize
Functions, function parameters, and return types can have attributes to indicate how they should be t...
Definition Attributes.h:106
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition Attributes.h:266
Diagnostic information for optimization failures.
Diagnostic information for unsupported feature in backend.
uint64_t getFnAttributeAsParsedInteger(StringRef Kind, uint64_t Default=0) const
For a string attribute Kind, parse attribute as an integer.
Definition Function.cpp:781
bool hasFlat() const
InstrItineraryData InstrItins
bool useVGPRIndexMode() const
void mirFileLoaded(MachineFunction &MF) const override
unsigned MaxPrivateElementSize
unsigned getAddressableNumArchVGPRs() const
unsigned getMinNumSGPRs(unsigned WavesPerEU) const
void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS)
void overridePipelinerPolicy(MachinePipelinerPolicy &Policy) const override
GCNSubtarget & initializeSubtargetDependencies(const Triple &TT, StringRef GPU, StringRef FS, AMDGPU::TargetIDSetting XnackSetting, AMDGPU::TargetIDSetting SramEccSetting)
unsigned getConstantBusLimit(unsigned Opcode) const
const InstrItineraryData * getInstrItineraryData() const override
void adjustSchedDependency(SUnit *Def, int DefOpIdx, SUnit *Use, int UseOpIdx, SDep &Dep, const TargetSchedModel *SchedModel) const override
void overridePostRASchedPolicy(MachineSchedPolicy &Policy, const SchedRegion &Region) const override
bool isFullSIMDMode() const
Align getStackAlignment() const
const bool BufferOOBRelaxed
bool hasMadF16() const
unsigned getMinNumVGPRs(unsigned WavesPerEU, unsigned DynamicVGPRBlockSize) const
const SIRegisterInfo * getRegisterInfo() const override
unsigned getBaseMaxNumVGPRs(const Function &F, std::pair< unsigned, unsigned > NumVGPRBounds) const
bool zeroesHigh16BitsOfDest(unsigned Opcode) const
Returns if the result of this instruction with a 16-bit result returned in a 32-bit register implicit...
unsigned getBaseMaxNumSGPRs(const Function &F, std::pair< unsigned, unsigned > WavesPerEU, unsigned PreloadedSGPRs, unsigned ReservedNumSGPRs) const
unsigned getMaxNumPreloadedSGPRs() const
void overrideSchedPolicy(MachineSchedPolicy &Policy, const SchedRegion &Region) const override
std::pair< unsigned, unsigned > computeOccupancy(const Function &F, unsigned LDSSize=0, unsigned NumSGPRs=0, unsigned NumVGPRs=0) const
Subtarget's minimum/maximum occupancy, in number of waves per EU, that can be achieved when the only ...
unsigned getMaxNumVGPRs(unsigned WavesPerEU, unsigned DynamicVGPRBlockSize) const
AMDGPU::TargetID TargetID
const SITargetLowering * getTargetLowering() const override
unsigned getNSAThreshold(const MachineFunction &MF) const
const AMDGPU::TargetID & getTargetID() const
GCNSubtarget(const Triple &TT, StringRef GPU, StringRef FS, const GCNTargetMachine &TM, bool BufferOOBRelaxed=false, bool TBufferOOBRelaxed=false, AMDGPU::TargetIDSetting XnackSetting=AMDGPU::TargetIDSetting::Any, AMDGPU::TargetIDSetting SramEccSetting=AMDGPU::TargetIDSetting::Any)
unsigned getReservedNumSGPRs(const MachineFunction &MF) const
const bool TBufferOOBRelaxed
bool useAA() const override
bool isWave32() const
unsigned getOccupancyWithNumVGPRs(unsigned VGPRs, unsigned DynamicVGPRBlockSize) const
Return the maximum number of waves per SIMD for kernels using VGPRs VGPRs.
unsigned InstCacheLineSize
unsigned getOccupancyWithNumSGPRs(unsigned SGPRs) const
Return the maximum number of waves per SIMD for kernels using SGPRs SGPRs.
Generation getGeneration() const
unsigned getMaxNumSGPRs(unsigned WavesPerEU, bool Addressable) const
std::pair< unsigned, unsigned > getMaxNumVectorRegs(const Function &F) const
Return a pair of maximum numbers of VGPRs and AGPRs that meet the number of waves per execution unit ...
bool isXNACKEnabled() const
unsigned getBaseReservedNumSGPRs(const bool HasFlatScratch) const
bool hasAddr64() const
void checkSubtargetFeatures(const Function &F) const
Diagnose inconsistent subtarget features before attempting to codegen function F.
~GCNSubtarget() override
const SelectionDAGTargetInfo * getSelectionDAGInfo() const override
static unsigned getNumUserSGPRForField(UserSGPRID ID)
void allocKernargPreloadSGPRs(unsigned NumSGPRs)
bool hasPrivateSegmentBuffer() const
GCNUserSGPRUsageInfo(const Function &F, const GCNSubtarget &ST)
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
Instructions::const_iterator const_instr_iterator
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
bool isBundle() const
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
int64_t getImm() const
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
Definition Register.h:20
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
Definition Register.h:107
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
Scheduling dependency.
Definition ScheduleDAG.h:54
Kind getKind() const
Returns an enum value representing the kind of the dependence.
@ Data
Regular data dependence (aka true-dependence).
Definition ScheduleDAG.h:58
void setLatency(unsigned Lat)
Sets the latency for this edge.
@ Artificial
Arbitrary strong DAG edge (no real dependence).
Definition ScheduleDAG.h:77
unsigned getLatency() const
Returns the latency value for this edge, which roughly means the minimum number of cycles that must e...
Register getReg() const
Returns the register associated with this edge.
void setReg(Register Reg)
Assigns the associated register for this edge.
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
std::pair< unsigned, unsigned > getWavesPerEU() const
GCNUserSGPRUsageInfo & getUserSGPRInfo()
Scheduling unit. This is a node in the scheduling DAG.
Targets can subclass this to parameterize the SelectionDAG lowering and instruction selection process...
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Information about stack frame layout on the target.
Provide an instruction scheduling machine model to CodeGen passes.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
@ AMDGPUSubArch1250S
Definition Triple.h:273
@ AMDGPUSubArch9
Definition Triple.h:220
@ AMDGPUSubArch9_4
Definition Triple.h:233
@ AMDGPUSubArch6
Definition Triple.h:198
@ AMDGPUSubArch10_3
Definition Triple.h:243
@ AMDGPUSubArch90A
Definition Triple.h:231
@ AMDGPUSubArch810
Definition Triple.h:218
@ AMDGPUSubArch11
Definition Triple.h:252
@ AMDGPUSubArch7
Definition Triple.h:203
@ AMDGPUSubArch12_5
Definition Triple.h:272
@ AMDGPUSubArch10_1
Definition Triple.h:237
@ AMDGPUSubArch11_7
Definition Triple.h:263
@ AMDGPUSubArch8
Definition Triple.h:211
@ AMDGPUSubArch13
Definition Triple.h:277
@ AMDGPUSubArch12
Definition Triple.h:268
@ AMDGPUSubArch908
Definition Triple.h:230
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
LLVM Value Representation.
Definition Value.h:75
self_iterator getIterator()
Definition ilist_node.h:123
unsigned getNumWavesPerEUWithNumVGPRs(const MCSubtargetInfo &STI, unsigned NumVGPRs, unsigned DynamicVGPRBlockSize)
unsigned getOccupancyWithNumSGPRs(unsigned SGPRs, unsigned MaxWaves, unsigned TotalNumSGPRs, unsigned Granule, unsigned TrapReserve)
StringRef getSchedStrategy(const Function &F)
LLVM_ABI unsigned getLDSAllocGranule(GPUKind AK)
LLVM_ABI unsigned getAddressableLocalMemorySize(GPUKind AK, bool FullSIMDMode)
constexpr unsigned getNumWorkGroupSIMDs(bool FullSIMDMode)
unsigned getMaxNumUserSGPRs(const MCSubtargetInfo &STI)
LLVM_ABI unsigned getLocalMemorySize(GPUKind AK, bool FullSIMDMode)
LLVM_READNONE constexpr bool isEntryFunctionCC(CallingConv::ID CC)
unsigned getDynamicVGPRBlockSize(const Function &F)
LLVM_ABI Triple::SubArchType getMajorSubArch(Triple::SubArchType SubArch)
std::pair< unsigned, unsigned > getIntegerPairAttribute(const Function &F, StringRef Name, std::pair< unsigned, unsigned > Default, bool OnlyFirstRequired)
LLVM_READNONE constexpr bool isGraphics(CallingConv::ID CC)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ SPIR_KERNEL
Used for SPIR kernel functions.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:149
DWARFExpression::Operation Op
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:177
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Software pipelining policy for a loop, which a target can customize by implementing TargetSubtargetIn...
bool ShouldLimitRegPressure
Limit the register pressure of the scheduled loop, retrying at a higher II when a schedule needs too ...
Define a generic scheduling policy for targets that don't provide their own MachineSchedStrategy.
bool ShouldTrackLaneMasks
Track LaneMasks to allow reordering of independent subregister writes of the same vreg.
A region of an MBB for scheduling.