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
46 // Legacy triples without a subarch default to the first target that supports
47 // flat addressing for HSA, otherwise the first amdgcn target.
48 if (TT.getSubArch() == Triple::NoSubArch)
49 return TT.getOS() == Triple::AMDHSA ? AMDGPUSubtarget::SEA_ISLANDS
51
52 switch (AMDGPU::getMajorSubArch(TT.getSubArch())) {
77 default:
78 reportFatalUsageError("invalid subarch for amdgpu");
79 }
80}
81
83 const Triple &TT, StringRef GPU, StringRef FS,
84 AMDGPU::TargetIDSetting XnackSetting,
85 AMDGPU::TargetIDSetting SramEccSetting) {
86 // Determine default and user-specified characteristics
87 //
88 // We want to be able to turn these off, but making this a subtarget feature
89 // for SI has the unhelpful behavior that it unsets everything else if you
90 // disable it.
91 //
92 // Similarly we want enable-prt-strict-null to be on by default and not to
93 // unset everything else if it is disabled
94
95 SmallString<256> FullFS("+load-store-opt,+enable-ds128,");
96
97 // Turn on features that HSA ABI requires. Also turn on FlatForGlobal by
98 // default
99 if (isAmdHsaOS())
100 FullFS += "+flat-for-global,+unaligned-access-mode,+trap-handler,";
101
102 FullFS += "+enable-prt-strict-null,"; // This is overridden by a disable in FS
103
104 // Disable mutually exclusive bits.
105 if (FS.contains_insensitive("+wavefrontsize")) {
106 if (!FS.contains_insensitive("wavefrontsize16"))
107 FullFS += "-wavefrontsize16,";
108 if (!FS.contains_insensitive("wavefrontsize32"))
109 FullFS += "-wavefrontsize32,";
110 if (!FS.contains_insensitive("wavefrontsize64"))
111 FullFS += "-wavefrontsize64,";
112 }
113
114 FullFS += FS;
115
116 ParseSubtargetFeatures(GPU, /*TuneCPU*/ GPU, FullFS);
117
118 // Implement the "generic" processors, which acts as the default when no
119 // generation features are enabled (e.g for -mcpu=''). HSA OS defaults to
120 // the first amdgcn target that supports flat addressing. Other OSes defaults
121 // to the first amdgcn target.
124 // Assume wave64 for the unknown target, if not explicitly set.
125 if (getWavefrontSizeLog2() == 0)
127 } else if (!hasFeature(AMDGPU::FeatureWavefrontSize32) &&
128 !hasFeature(AMDGPU::FeatureWavefrontSize64)) {
129 // If there is no default wave size it must be a generation before gfx10,
130 // these have FeatureWavefrontSize64 in their definition already. For gfx10+
131 // set wave32 as a default.
132 ToggleFeature(AMDGPU::FeatureWavefrontSize32);
134 }
135
136 // We don't support FP64 for EG/NI atm.
138
139 // Targets must either support 64-bit offsets for MUBUF instructions, and/or
140 // support flat operations, otherwise they cannot access a 64-bit global
141 // address space
142 assert(hasAddr64() || hasFlat());
143 // Unless +-flat-for-global is specified, turn on FlatForGlobal for targets
144 // that do not support ADDR64 variants of MUBUF instructions. Such targets
145 // cannot use a 64 bit offset with a MUBUF instruction to access the global
146 // address space
147 if (!hasAddr64() && !FS.contains("flat-for-global") && !UseFlatForGlobal) {
148 ToggleFeature(AMDGPU::FeatureUseFlatForGlobal);
149 UseFlatForGlobal = true;
150 }
151 // Unless +-flat-for-global is specified, use MUBUF instructions for global
152 // address space access if flat operations are not available.
153 if (!hasFlat() && !FS.contains("flat-for-global") && UseFlatForGlobal) {
154 ToggleFeature(AMDGPU::FeatureUseFlatForGlobal);
155 UseFlatForGlobal = false;
156 }
157
158 // Set defaults if needed.
159 if (MaxPrivateElementSize == 0)
161
162 if (LDSBankCount == 0)
163 LDSBankCount = 32;
164
165 if (MaxWavesPerEU == 0)
166 MaxWavesPerEU = 10;
167
168 if (FlatOffsetBitWidth == 0)
170
174 getTargetID().getGPUKind(), isFullSIMDMode());
175 // LDS allocation granularity is in bytes.
178
181
182 // InstCacheLineSize is set from TableGen subtarget features
183 // (FeatureInstCacheLineSize64 / FeatureInstCacheLineSize128).
184 // Fall back to 64 if no feature was specified (e.g. generic targets).
185 if (InstCacheLineSize == 0)
187
189 "InstCacheLineSize must be a power of 2");
190
191 // Apply the module flag's xnack setting if the target supports on/off modes.
192 // Targets without on/off mode support have xnack always on and ignore module
193 // flags.
194 if (hasXNACKOnOffModes())
195 TargetID.setXnackSetting(XnackSetting);
196
197 // Apply the module flag's sramecc setting if the target supports on/off
198 // modes. Targets with sramecc hardwired on ignore module flags.
199 if (hasSRAMECCOnOffModes())
200 TargetID.setSramEccSetting(SramEccSetting);
201
202 return *this;
203}
204
206 LLVMContext &Ctx = F.getContext();
207 if (hasFeature(AMDGPU::FeatureWavefrontSize32) &&
208 hasFeature(AMDGPU::FeatureWavefrontSize64)) {
209 Ctx.diagnose(DiagnosticInfoUnsupported(
210 F, "must specify exactly one of wavefrontsize32 and wavefrontsize64"));
211 }
212}
213
214// TODO: Validate subarch for subtarget
215
217 const GCNTargetMachine &TM, bool BufferOOBRelaxed,
219 AMDGPU::TargetIDSetting XnackSetting,
220 AMDGPU::TargetIDSetting SramEccSetting)
221 : // clang-format off
222 AMDGPUGenSubtargetInfo(TT, GPU, /*TuneCPU*/ GPU, FS),
223 AMDGPUSubtarget(TT, TM.getCLOpts()),
224 TargetID(AMDGPU::createAMDGPUTargetID(*this, "")),
225 InstrItins(getInstrItineraryForCPU(GPU)),
228 InstrInfo(initializeSubtargetDependencies(TT, GPU, FS, XnackSetting,
229 SramEccSetting)),
230 TLInfo(TM, *this),
231 // Frame index expansion sometimes assumes the low bit of SP is 0
232 FrameLowering(TargetFrameLowering::StackGrowsUp, getStackAlignment(), 0,
233 /*TransAl=*/Align(4)) {
234
235 // clang-format on
236
237 LLVM_DEBUG(dbgs() << "xnack setting for subtarget: "
238 << TargetID.getXnackSetting() << '\n');
239 LLVM_DEBUG(dbgs() << "sramecc setting for subtarget: "
240 << TargetID.getSramEccSetting() << '\n');
241
243
244 TSInfo = std::make_unique<AMDGPUSelectionDAGInfo>();
245
246 CallLoweringInfo = std::make_unique<AMDGPUCallLowering>(*getTargetLowering());
247 InlineAsmLoweringInfo =
248 std::make_unique<InlineAsmLowering>(getTargetLowering());
249 Legalizer = std::make_unique<AMDGPULegalizerInfo>(*this, TM);
250 RegBankInfo = std::make_unique<AMDGPURegisterBankInfo>(*this);
251 InstSelector =
252 std::make_unique<AMDGPUInstructionSelector>(*this, *RegBankInfo);
253}
254
256 return TSInfo.get();
257}
258
259unsigned GCNSubtarget::getConstantBusLimit(unsigned Opcode) const {
260 if (getGeneration() < GFX10)
261 return 1;
262
263 switch (Opcode) {
264 case AMDGPU::V_LSHLREV_B64_e64:
265 case AMDGPU::V_LSHLREV_B64_gfx10:
266 case AMDGPU::V_LSHLREV_B64_e64_gfx11:
267 case AMDGPU::V_LSHLREV_B64_e32_gfx12:
268 case AMDGPU::V_LSHLREV_B64_e64_gfx12:
269 case AMDGPU::V_LSHL_B64_e64:
270 case AMDGPU::V_LSHRREV_B64_e64:
271 case AMDGPU::V_LSHRREV_B64_gfx10:
272 case AMDGPU::V_LSHRREV_B64_e64_gfx11:
273 case AMDGPU::V_LSHRREV_B64_e64_gfx12:
274 case AMDGPU::V_LSHR_B64_e64:
275 case AMDGPU::V_ASHRREV_I64_e64:
276 case AMDGPU::V_ASHRREV_I64_gfx10:
277 case AMDGPU::V_ASHRREV_I64_e64_gfx11:
278 case AMDGPU::V_ASHRREV_I64_e64_gfx12:
279 case AMDGPU::V_ASHR_I64_e64:
280 return 1;
281 }
282
283 return 2;
284}
285
286/// This list was mostly derived from experimentation.
287bool GCNSubtarget::zeroesHigh16BitsOfDest(unsigned Opcode) const {
288 switch (Opcode) {
289 case AMDGPU::V_CVT_F16_F32_e32:
290 case AMDGPU::V_CVT_F16_F32_e64:
291 case AMDGPU::V_CVT_F16_U16_e32:
292 case AMDGPU::V_CVT_F16_U16_e64:
293 case AMDGPU::V_CVT_F16_I16_e32:
294 case AMDGPU::V_CVT_F16_I16_e64:
295 case AMDGPU::V_RCP_F16_e64:
296 case AMDGPU::V_RCP_F16_e32:
297 case AMDGPU::V_RSQ_F16_e64:
298 case AMDGPU::V_RSQ_F16_e32:
299 case AMDGPU::V_SQRT_F16_e64:
300 case AMDGPU::V_SQRT_F16_e32:
301 case AMDGPU::V_LOG_F16_e64:
302 case AMDGPU::V_LOG_F16_e32:
303 case AMDGPU::V_EXP_F16_e64:
304 case AMDGPU::V_EXP_F16_e32:
305 case AMDGPU::V_SIN_F16_e64:
306 case AMDGPU::V_SIN_F16_e32:
307 case AMDGPU::V_COS_F16_e64:
308 case AMDGPU::V_COS_F16_e32:
309 case AMDGPU::V_FLOOR_F16_e64:
310 case AMDGPU::V_FLOOR_F16_e32:
311 case AMDGPU::V_CEIL_F16_e64:
312 case AMDGPU::V_CEIL_F16_e32:
313 case AMDGPU::V_TRUNC_F16_e64:
314 case AMDGPU::V_TRUNC_F16_e32:
315 case AMDGPU::V_RNDNE_F16_e64:
316 case AMDGPU::V_RNDNE_F16_e32:
317 case AMDGPU::V_FRACT_F16_e64:
318 case AMDGPU::V_FRACT_F16_e32:
319 case AMDGPU::V_FREXP_MANT_F16_e64:
320 case AMDGPU::V_FREXP_MANT_F16_e32:
321 case AMDGPU::V_FREXP_EXP_I16_F16_e64:
322 case AMDGPU::V_FREXP_EXP_I16_F16_e32:
323 case AMDGPU::V_LDEXP_F16_e64:
324 case AMDGPU::V_LDEXP_F16_e32:
325 case AMDGPU::V_LSHLREV_B16_e64:
326 case AMDGPU::V_LSHLREV_B16_e32:
327 case AMDGPU::V_LSHRREV_B16_e64:
328 case AMDGPU::V_LSHRREV_B16_e32:
329 case AMDGPU::V_ASHRREV_I16_e64:
330 case AMDGPU::V_ASHRREV_I16_e32:
331 case AMDGPU::V_ADD_U16_e64:
332 case AMDGPU::V_ADD_U16_e32:
333 case AMDGPU::V_SUB_U16_e64:
334 case AMDGPU::V_SUB_U16_e32:
335 case AMDGPU::V_SUBREV_U16_e64:
336 case AMDGPU::V_SUBREV_U16_e32:
337 case AMDGPU::V_MUL_LO_U16_e64:
338 case AMDGPU::V_MUL_LO_U16_e32:
339 case AMDGPU::V_ADD_F16_e64:
340 case AMDGPU::V_ADD_F16_e32:
341 case AMDGPU::V_SUB_F16_e64:
342 case AMDGPU::V_SUB_F16_e32:
343 case AMDGPU::V_SUBREV_F16_e64:
344 case AMDGPU::V_SUBREV_F16_e32:
345 case AMDGPU::V_MUL_F16_e64:
346 case AMDGPU::V_MUL_F16_e32:
347 case AMDGPU::V_MAX_F16_e64:
348 case AMDGPU::V_MAX_F16_e32:
349 case AMDGPU::V_MIN_F16_e64:
350 case AMDGPU::V_MIN_F16_e32:
351 case AMDGPU::V_MAX_U16_e64:
352 case AMDGPU::V_MAX_U16_e32:
353 case AMDGPU::V_MIN_U16_e64:
354 case AMDGPU::V_MIN_U16_e32:
355 case AMDGPU::V_MAX_I16_e64:
356 case AMDGPU::V_MAX_I16_e32:
357 case AMDGPU::V_MIN_I16_e64:
358 case AMDGPU::V_MIN_I16_e32:
359 case AMDGPU::V_MAD_F16_e64:
360 case AMDGPU::V_MAD_U16_e64:
361 case AMDGPU::V_MAD_I16_e64:
362 case AMDGPU::V_FMA_F16_e64:
363 case AMDGPU::V_DIV_FIXUP_F16_e64:
364 // On gfx10, all 16-bit instructions preserve the high bits.
366 case AMDGPU::V_MADAK_F16:
367 case AMDGPU::V_MADMK_F16:
368 case AMDGPU::V_MAC_F16_e64:
369 case AMDGPU::V_MAC_F16_e32:
370 case AMDGPU::V_FMAMK_F16:
371 case AMDGPU::V_FMAAK_F16:
372 case AMDGPU::V_FMAC_F16_e64:
373 case AMDGPU::V_FMAC_F16_e32:
374 // In gfx9, the preferred handling of the unused high 16-bits changed. Most
375 // instructions maintain the legacy behavior of 0ing. Some instructions
376 // changed to preserving the high bits.
378 case AMDGPU::V_MAD_MIXLO_F16:
379 case AMDGPU::V_MAD_MIXHI_F16:
380 default:
381 return false;
382 }
383}
384
386 const SchedRegion &Region) const {
387 // Track register pressure so the scheduler can try to decrease
388 // pressure once register usage is above the threshold defined by
389 // SIRegisterInfo::getRegPressureSetLimit()
390 Policy.ShouldTrackPressure = true;
391
392 const Function &F = Region.RegionBegin->getMF()->getFunction();
393 if (AMDGPU::getSchedStrategy(getCLOpts(), F) == "coexec") {
394 Policy.OnlyTopDown = true;
395 Policy.OnlyBottomUp = false;
396 return;
397 }
398
399 // Enabling both top down and bottom up scheduling seems to give us less
400 // register spills than just using one of these approaches on its own.
401 Policy.OnlyTopDown = false;
402 Policy.OnlyBottomUp = false;
403
404 // Enabling ShouldTrackLaneMasks crashes the SI Machine Scheduler.
405 if (!enableSIScheduler())
406 Policy.ShouldTrackLaneMasks = true;
407}
408
410 const SchedRegion &Region) const {
411 const Function &F = Region.RegionBegin->getMF()->getFunction();
412 Attribute PostRADirectionAttr = F.getFnAttribute("amdgpu-post-ra-direction");
413 if (!PostRADirectionAttr.isValid())
414 return;
415
416 StringRef PostRADirectionStr = PostRADirectionAttr.getValueAsString();
417 if (PostRADirectionStr == "topdown") {
418 Policy.OnlyTopDown = true;
419 Policy.OnlyBottomUp = false;
420 } else if (PostRADirectionStr == "bottomup") {
421 Policy.OnlyTopDown = false;
422 Policy.OnlyBottomUp = true;
423 } else if (PostRADirectionStr == "bidirectional") {
424 Policy.OnlyTopDown = false;
425 Policy.OnlyBottomUp = false;
426 } else {
428 F, F.getSubprogram(), "invalid value for postRA direction attribute");
429 F.getContext().diagnose(Diag);
430 }
431
432 LLVM_DEBUG({
433 const char *DirStr = "default";
434 if (Policy.OnlyTopDown && !Policy.OnlyBottomUp)
435 DirStr = "topdown";
436 else if (!Policy.OnlyTopDown && Policy.OnlyBottomUp)
437 DirStr = "bottomup";
438 else if (!Policy.OnlyTopDown && !Policy.OnlyBottomUp)
439 DirStr = "bidirectional";
440
441 dbgs() << "Post-MI-sched direction (" << F.getName() << "): " << DirStr
442 << '\n';
443 });
444}
445
450
452 if (isWave32()) {
453 // Fix implicit $vcc operands after MIParser has verified that they match
454 // the instruction definitions.
455 for (auto &MBB : MF) {
456 for (auto &MI : MBB)
457 InstrInfo.fixImplicitOperands(MI);
458 }
459 }
460}
461
463 return InstrInfo.pseudoToMCOpcode(AMDGPU::V_MAD_F16_e64) != -1;
464}
465
467 return hasVGPRIndexMode() && (!hasMovrel() || getCLOpts().vgpr_index_mode);
468}
469
470bool GCNSubtarget::useAA() const { return getCLOpts().use_aa_in_codegen; }
471
473 Align A, bool NoWrapFromMax,
474 bool NoPartialOOB) const {
475 Align Result(16);
477 Result = A;
478 auto *VT = dyn_cast<VectorType>(T);
479 if (!hasRelaxedBufferOOBMode() && VT) {
480 TypeSize ElemBits = DL.getTypeSizeInBits(VT->getElementType());
481 if (ElemBits.isKnownMultipleOf(32)) {
482 // Word-sized operations are bounds-checked per word. So, the only case we
483 // have to worry about is stores that start out of bounds and then go in,
484 // and those can only become in-bounds on a multiple of their alignment.
485 // Therefore, we can use the declared alignment of the operation as the
486 // maximum width, rounding up to 4.
487 if (!NoWrapFromMax)
488 Result = std::min(Result, std::max(A, Align(4)));
489 } else if ((ElemBits.isKnownMultipleOf(8) ||
490 isPowerOf2_64(ElemBits.getKnownMinValue()))) {
491 // To ensure correct behavior for sub-word types, we must always scalarize
492 // unaligned loads of sub-word types. For example, if you load
493 // a <4 x i8> from offset 7 in an 8-byte buffer, expecting the vector
494 // to be padded out with 0s after that last byte, you'll get all 0s
495 // instead. To prevent this behavior when not requested, de-vectorize such
496 // loads.
497 //
498 // If we knew that the value that triggers bounds checks was a multiple of
499 // 4 along with the access being word-aligned, we could avoid the
500 // scalarization here, as the bitcast wouldn't change any check behavior,
501 // but we don't currently try to analyze this.
502 //
503 // Strict OOB checking isn't supported if the size of each element is a
504 // non-power-of-2 value less than 8, since there's no feasible way to
505 // apply such a strict bounds check.
506 if (!NoPartialOOB)
507 Result =
508 commonAlignment(Result, divideCeil(ElemBits.getKnownMinValue(), 8));
509 }
510 }
511 return Result.value() * 8;
512}
513
514unsigned GCNSubtarget::getOccupancyWithNumSGPRs(unsigned SGPRs) const {
516}
517
518unsigned
520 unsigned DynamicVGPRBlockSize) const {
522 DynamicVGPRBlockSize);
523}
524
525unsigned
526GCNSubtarget::getBaseReservedNumSGPRs(const bool HasFlatScratch) const {
528 return 2; // VCC. FLAT_SCRATCH and XNACK are no longer in SGPRs.
529
530 if (HasFlatScratch || HasArchitectedFlatScratch) {
532 return 6; // FLAT_SCRATCH, XNACK, VCC (in that order).
534 return 4; // FLAT_SCRATCH, VCC (in that order).
535 }
536
537 if (isXNACKEnabled())
538 return 4; // XNACK, VCC (in that order).
539 return 2; // VCC.
540}
541
546
548 // In principle we do not need to reserve SGPR pair used for flat_scratch if
549 // we know flat instructions do not access the stack anywhere in the
550 // program. For now assume it's needed if we have flat instructions.
551 const bool KernelUsesFlatScratch = hasFlatAddressSpace();
552 return getBaseReservedNumSGPRs(KernelUsesFlatScratch);
553}
554
555std::pair<unsigned, unsigned>
557 unsigned NumSGPRs, unsigned NumVGPRs) const {
558 unsigned DynamicVGPRBlockSize = AMDGPU::getDynamicVGPRBlockSize(F);
559 auto [MinOcc, MaxOcc] = getOccupancyWithWorkGroupSizes(LDSSize, F);
560 unsigned SGPROcc = getOccupancyWithNumSGPRs(NumSGPRs);
561 unsigned VGPROcc = getOccupancyWithNumVGPRs(NumVGPRs, DynamicVGPRBlockSize);
562
563 // Maximum occupancy may be further limited by high SGPR/VGPR usage.
564 MaxOcc = std::min({MaxOcc, SGPROcc, VGPROcc});
565 return {std::min(MinOcc, MaxOcc), MaxOcc};
566}
567
569 const Function &F, std::pair<unsigned, unsigned> WavesPerEU,
570 unsigned PreloadedSGPRs, unsigned ReservedNumSGPRs) const {
571 // Compute maximum number of SGPRs function can use using default/requested
572 // minimum number of waves per execution unit.
573 unsigned MaxNumSGPRs = getMaxNumSGPRs(WavesPerEU.first, false);
574 unsigned MaxAddressableNumSGPRs = getMaxNumSGPRs(WavesPerEU.first, true);
575
576 // Check if maximum number of SGPRs was explicitly requested using
577 // "amdgpu-num-sgpr" attribute.
578 unsigned Requested = static_cast<unsigned>(
579 F.getFnAttributeAsParsedInteger("amdgpu-num-sgpr", MaxNumSGPRs));
580
581 if (Requested != MaxNumSGPRs) {
582 // Make sure requested value does not violate subtarget's specifications.
583 if (Requested && (Requested <= ReservedNumSGPRs))
584 Requested = 0;
585
586 // If more SGPRs are required to support the input user/system SGPRs,
587 // increase to accommodate them.
588 //
589 // FIXME: This really ends up using the requested number of SGPRs + number
590 // of reserved special registers in total. Theoretically you could re-use
591 // the last input registers for these special registers, but this would
592 // require a lot of complexity to deal with the weird aliasing.
593 unsigned InputNumSGPRs = PreloadedSGPRs;
594 if (Requested && Requested < InputNumSGPRs)
595 Requested = InputNumSGPRs;
596
597 // Make sure requested value is compatible with values implied by
598 // default/requested minimum/maximum number of waves per execution unit.
599 if (Requested && Requested > getMaxNumSGPRs(WavesPerEU.first, false))
600 Requested = 0;
601 if (WavesPerEU.second && Requested &&
602 Requested < getMinNumSGPRs(WavesPerEU.second))
603 Requested = 0;
604
605 if (Requested)
606 MaxNumSGPRs = Requested;
607 }
608
609 if (hasSGPRInitBug())
611
612 return std::min(MaxNumSGPRs - ReservedNumSGPRs, MaxAddressableNumSGPRs);
613}
614
616 const Function &F = MF.getFunction();
620}
621
623 using USI = GCNUserSGPRUsageInfo;
624 // Max number of user SGPRs
625 const unsigned MaxUserSGPRs =
626 USI::getNumUserSGPRForField(USI::PrivateSegmentBufferID) +
627 USI::getNumUserSGPRForField(USI::DispatchPtrID) +
628 USI::getNumUserSGPRForField(USI::QueuePtrID) +
629 USI::getNumUserSGPRForField(USI::KernargSegmentPtrID) +
630 USI::getNumUserSGPRForField(USI::DispatchIdID) +
631 USI::getNumUserSGPRForField(USI::FlatScratchInitID) +
632 USI::getNumUserSGPRForField(USI::ImplicitBufferPtrID);
633
634 // Max number of system SGPRs
635 const unsigned MaxSystemSGPRs = 1 + // WorkGroupIDX
636 1 + // WorkGroupIDY
637 1 + // WorkGroupIDZ
638 1 + // WorkGroupInfo
639 1; // private segment wave byte offset
640
641 // Max number of synthetic SGPRs
642 const unsigned SyntheticSGPRs = 1; // LDSKernelId
643
644 return MaxUserSGPRs + MaxSystemSGPRs + SyntheticSGPRs;
645}
646
651
653 const Function &F, std::pair<unsigned, unsigned> NumVGPRBounds) const {
654 const auto [Min, Max] = NumVGPRBounds;
655
656 // Check if maximum number of VGPRs was explicitly requested using
657 // "amdgpu-num-vgpr" attribute.
658
659 unsigned Requested = static_cast<unsigned>(
660 F.getFnAttributeAsParsedInteger("amdgpu-num-vgpr", Max));
661 if (Requested != Max && hasGFX90AInsts())
662 Requested *= 2;
663
664 // Make sure requested value is inside the range of possible VGPR usage.
665 return std::clamp(Requested, Min, Max);
666}
667
669 unsigned DynamicVGPRBlockSize = AMDGPU::getDynamicVGPRBlockSize(F);
670 std::pair<unsigned, unsigned> Waves = getWavesPerEU(F);
671
672 unsigned MaxNumVGPRs = getBaseMaxNumVGPRs(
673 F, {getMinNumVGPRs(Waves.second, DynamicVGPRBlockSize),
674 getMaxNumVGPRs(Waves.first, DynamicVGPRBlockSize)});
675
676 // In DVGPR mode, a wave launches with a single VGPR block allocated. Applied
677 // after getBaseMaxNumVGPRs so "amdgpu-num-vgpr" cannot raise it back up.
678 if (DynamicVGPRBlockSize != 0 &&
679 AMDGPU::isEntryFunctionCC(F.getCallingConv()))
680 MaxNumVGPRs = std::min(MaxNumVGPRs, DynamicVGPRBlockSize);
681
682 return MaxNumVGPRs;
683}
684
686 return getMaxNumVGPRs(MF.getFunction());
687}
688
689std::pair<unsigned, unsigned>
691 const unsigned MaxVectorRegs = getMaxNumVGPRs(F);
692
693 unsigned MaxNumVGPRs = MaxVectorRegs;
694 unsigned MaxNumAGPRs = 0;
695 unsigned NumArchVGPRs = getAddressableNumArchVGPRs();
696
697 // On GFX90A, the number of VGPRs and AGPRs need not be equal. Theoretically,
698 // a wave may have up to 512 total vector registers combining together both
699 // VGPRs and AGPRs. Hence, in an entry function without calls and without
700 // AGPRs used within it, it is possible to use the whole vector register
701 // budget for VGPRs.
702 //
703 // TODO: it shall be possible to estimate maximum AGPR/VGPR pressure and split
704 // register file accordingly.
705 if (hasGFX90AInsts()) {
706 unsigned MinNumAGPRs = 0;
707 const unsigned TotalNumAGPRs = AMDGPU::AGPR_32RegClass.getNumRegs();
708
709 const std::pair<unsigned, unsigned> DefaultNumAGPR = {~0u, ~0u};
710
711 // TODO: The lower bound should probably force the number of required
712 // registers up, overriding amdgpu-waves-per-eu.
713 std::tie(MinNumAGPRs, MaxNumAGPRs) =
714 AMDGPU::getIntegerPairAttribute(F, "amdgpu-agpr-alloc", DefaultNumAGPR,
715 /*OnlyFirstRequired=*/true);
716
717 if (MinNumAGPRs == DefaultNumAGPR.first) {
718 // Default to splitting half the registers if AGPRs are required.
719 MinNumAGPRs = MaxNumAGPRs = MaxVectorRegs / 2;
720 } else {
721 // Align to accum_offset's allocation granularity.
722 MinNumAGPRs = alignTo(MinNumAGPRs, 4);
723
724 MinNumAGPRs = std::min(MinNumAGPRs, TotalNumAGPRs);
725 }
726
727 // Clamp values to be inbounds of our limits, and ensure min <= max.
728
729 MaxNumAGPRs = std::min(std::max(MinNumAGPRs, MaxNumAGPRs), MaxVectorRegs);
730 MinNumAGPRs = std::min({MinNumAGPRs, TotalNumAGPRs, MaxNumAGPRs});
731
732 MaxNumVGPRs = std::min(MaxVectorRegs - MinNumAGPRs, NumArchVGPRs);
733 MaxNumAGPRs = std::min(MaxVectorRegs - MaxNumVGPRs, MaxNumAGPRs);
734
735 assert(MaxNumVGPRs + MaxNumAGPRs <= MaxVectorRegs &&
736 MaxNumAGPRs <= TotalNumAGPRs && MaxNumVGPRs <= NumArchVGPRs &&
737 "invalid register counts");
738 } else if (hasMAIInsts()) {
739 // On gfx908 the number of AGPRs always equals the number of VGPRs.
740 MaxNumAGPRs = MaxNumVGPRs = MaxVectorRegs;
741 }
742
743 return std::pair(MaxNumVGPRs, MaxNumAGPRs);
744}
745
746// Check to which source operand UseOpIdx points to and return a pointer to the
747// operand of the corresponding source modifier.
748// Return nullptr if UseOpIdx either doesn't point to src0/1/2 or if there is no
749// operand for the corresponding source modifier.
750static const MachineOperand *
752 const SIInstrInfo &InstrInfo) {
753 AMDGPU::OpName UseName = AMDGPU::getOperandIdxName(
754 UseI.getOpcode(), static_cast<int16_t>(UseOpIdx));
755 switch (UseName) {
756 case AMDGPU::OpName::src0:
757 return InstrInfo.getNamedOperand(UseI, AMDGPU::OpName::src0_modifiers);
758 case AMDGPU::OpName::src1:
759 return InstrInfo.getNamedOperand(UseI, AMDGPU::OpName::src1_modifiers);
760 case AMDGPU::OpName::src2:
761 return InstrInfo.getNamedOperand(UseI, AMDGPU::OpName::src2_modifiers);
762 default:
763 return nullptr;
764 }
765}
766
767// Get the subreg idx of the subreg that is used by the given instruction
768// operand, considering the given op_sel modifier.
769// Return 0 if the whole register is used or as a conservative fallback.
771 const SIInstrInfo &InstrInfo,
772 const MachineInstr &I,
773 const MachineOperand &Op) {
774 if (!InstrInfo.isVOP3P(I) || InstrInfo.isWMMA(I) || InstrInfo.isSWMMAC(I))
775 return AMDGPU::NoSubRegister;
776
777 const MachineOperand *OpMod =
778 getVOP3PSourceModifierFromOpIdx(I, Op.getOperandNo(), InstrInfo);
779 if (!OpMod)
780 return AMDGPU::NoSubRegister;
781
782 // Note: the FMA_MIX* and MAD_MIX* instructions have different semantics for
783 // the op_sel and op_sel_hi source modifiers:
784 // - op_sel: selects low/high operand bits as input to the operation;
785 // has only meaning for 16-bit source operands
786 // - op_sel_hi: specifies the size of the source operands (16 or 32 bits);
787 // a value of 0 indicates 32 bit, 1 indicates 16 bit
788 // For the other VOP3P instructions, the semantics are:
789 // - op_sel: selects low/high operand bits as input to the operation which
790 // results in the lower-half of the destination
791 // - op_sel_hi: selects the low/high operand bits as input to the operation
792 // which results in the higher-half of the destination
793 int64_t OpSel = OpMod->getImm() & SISrcMods::OP_SEL_0;
794 int64_t OpSelHi = OpMod->getImm() & SISrcMods::OP_SEL_1;
795
796 // Check if all parts of the register are being used (= op_sel and op_sel_hi
797 // differ for VOP3P or op_sel_hi=0 for VOP3PMix). In that case we can return
798 // early.
799 if ((!InstrInfo.isVOP3PMix(I) && (!OpSel || !OpSelHi) &&
800 (OpSel || OpSelHi)) ||
801 (InstrInfo.isVOP3PMix(I) && !OpSelHi))
802 return AMDGPU::NoSubRegister;
803
804 const MachineRegisterInfo &MRI = I.getParent()->getParent()->getRegInfo();
805 const TargetRegisterClass *RC = TRI.getRegClassForOperandReg(MRI, Op);
806
807 if (unsigned SubRegIdx = OpSel ? AMDGPU::sub1 : AMDGPU::sub0;
808 TRI.getSubClassWithSubReg(RC, SubRegIdx) == RC)
809 return SubRegIdx;
810 if (unsigned SubRegIdx = OpSel ? AMDGPU::hi16 : AMDGPU::lo16;
811 TRI.getSubClassWithSubReg(RC, SubRegIdx) == RC)
812 return SubRegIdx;
813
814 return AMDGPU::NoSubRegister;
815}
816
817Register GCNSubtarget::getRealSchedDependency(const MachineInstr &DefI,
818 int DefOpIdx,
819 const MachineInstr &UseI,
820 int UseOpIdx) const {
821 const SIRegisterInfo *TRI = getRegisterInfo();
822 const MachineOperand &DefOp = DefI.getOperand(DefOpIdx);
823 const MachineOperand &UseOp = UseI.getOperand(UseOpIdx);
824 Register DefReg = DefOp.getReg();
825 Register UseReg = UseOp.getReg();
826
827 // If the registers aren't restricted to a sub-register, there is no point in
828 // further analysis. This check makes only sense for virtual registers because
829 // physical registers may form a tuple and thus be part of a superregister
830 // although they are not a subregister themselves (vgpr0 is a "subreg" of
831 // vgpr0_vgpr1 without being a subreg in itself).
832 unsigned DefSubRegIdx = DefOp.getSubReg();
833 if (DefReg.isVirtual() && DefSubRegIdx == AMDGPU::NoSubRegister)
834 return DefReg;
835 unsigned UseSubRegIdx = getEffectiveSubRegIdx(*TRI, InstrInfo, UseI, UseOp);
836 if (UseReg.isVirtual() && UseSubRegIdx == AMDGPU::NoSubRegister)
837 return DefReg;
838
839 if (!TRI->checkSubRegInterference(DefReg, DefSubRegIdx, UseReg, UseSubRegIdx))
840 return Register(); // No real dependency
841
842 // UseReg might be smaller or larger than DefReg, depending on the subreg and
843 // on whether DefReg is a subreg, too. -> Find the smaller one. This does not
844 // apply to virtual registers because we cannot construct a subreg for them.
845 if (DefReg.isVirtual())
846 return DefReg;
847 MCRegister DefMCReg =
848 DefSubRegIdx ? TRI->getSubReg(DefReg, DefSubRegIdx) : DefReg.asMCReg();
849 MCRegister UseMCReg =
850 UseSubRegIdx ? TRI->getSubReg(UseReg, UseSubRegIdx) : UseReg.asMCReg();
851 return TRI->isSubRegisterEq(DefMCReg, UseMCReg) ? UseMCReg : DefMCReg;
852}
853
855 SUnit *Def, int DefOpIdx, SUnit *Use, int UseOpIdx, SDep &Dep,
856 const TargetSchedModel *SchedModel) const {
857 if (Dep.getKind() != SDep::Kind::Data || !Dep.getReg() || !Def->isInstr() ||
858 !Use->isInstr())
859 return;
860
861 MachineInstr *DefI = Def->getInstr();
862 MachineInstr *UseI = Use->getInstr();
863
864 // Check for false latency on $tensorcnt / $asynccnt dependencies
865 if (Dep.getReg() == AMDGPU::TENSORcnt || Dep.getReg() == AMDGPU::ASYNCcnt) {
866 unsigned UseOp = UseI->getOpcode();
867 // Do not adjust latency for load->s_wait
868 bool IsBarrierCase =
869 InstrInfo.isLDSDMA(*DefI) &&
870 (UseOp == AMDGPU::S_WAIT_TENSORCNT || UseOp == AMDGPU::S_WAIT_ASYNCCNT);
871 if (!IsBarrierCase) {
872 Dep.setLatency(1);
873 return;
874 }
875 }
876
877 if (Register Reg = getRealSchedDependency(*DefI, DefOpIdx, *UseI, UseOpIdx)) {
878 Dep.setReg(Reg);
879 } else {
880 Dep = SDep(Def, SDep::Artificial);
881 return; // This is not a data dependency anymore.
882 }
883
884 if (DefI->isBundle()) {
886 auto Reg = Dep.getReg();
889 unsigned Lat = 0;
890 for (++I; I != E && I->isBundledWithPred(); ++I) {
891 if (I->isMetaInstruction())
892 continue;
893 if (I->modifiesRegister(Reg, TRI))
894 Lat = InstrInfo.getInstrLatency(getInstrItineraryData(), *I);
895 else if (Lat)
896 --Lat;
897 }
898 Dep.setLatency(Lat);
899 } else if (UseI->isBundle()) {
901 auto Reg = Dep.getReg();
904 unsigned Lat = InstrInfo.getInstrLatency(getInstrItineraryData(), *DefI);
905 for (++I; I != E && I->isBundledWithPred() && Lat; ++I) {
906 if (I->isMetaInstruction())
907 continue;
908 if (I->readsRegister(Reg, TRI))
909 break;
910 --Lat;
911 }
912 Dep.setLatency(Lat);
913 } else if (Dep.getLatency() == 0 && Dep.getReg() == AMDGPU::VCC_LO) {
914 // Work around the fact that SIInstrInfo::fixImplicitOperands modifies
915 // implicit operands which come from the MCInstrDesc, which can fool
916 // ScheduleDAGInstrs::addPhysRegDataDeps into treating them as implicit
917 // pseudo operands.
918 Dep.setLatency(InstrInfo.getSchedModel().computeOperandLatency(
919 DefI, DefOpIdx, UseI, UseOpIdx));
920 }
921}
922
925 return 0; // Not MIMG encoding.
926
927 if (getCLOpts().nsa_threshold)
928 return std::max(*getCLOpts().nsa_threshold, 2u);
929
930 int Value = static_cast<int>(MF.getFunction().getFnAttributeAsParsedInteger(
931 "amdgpu-nsa-threshold", -1));
932 if (Value > 0)
933 return std::max(Value, 2);
934
935 return 2;
936}
937
939 const GCNSubtarget &ST)
940 : ST(ST) {
941 const CallingConv::ID CC = F.getCallingConv();
942 const bool IsKernel =
944
945 if (IsKernel && (!F.arg_empty() || ST.getImplicitArgNumBytes(F) != 0))
946 KernargSegmentPtr = true;
947
948 bool IsAmdHsaOrMesa = ST.isAmdHsaOrMesa(F);
949 if (IsAmdHsaOrMesa && !ST.hasFlatScratchEnabled())
950 PrivateSegmentBuffer = true;
951 else if (!ST.hasArchitectedFlatScratch() && ST.isMesaGfxShader(F))
952 ImplicitBufferPtr = true; // Only needed to set up scratch.
953
955 if (!F.hasFnAttribute("amdgpu-no-dispatch-ptr"))
956 DispatchPtr = true;
957
958 // FIXME: Can this always be disabled with < COv5?
959 if (!F.hasFnAttribute("amdgpu-no-queue-ptr"))
960 QueuePtr = true;
961
962 if (!F.hasFnAttribute("amdgpu-no-dispatch-id"))
963 DispatchID = true;
964 }
965
966 if (ST.hasFlatAddressSpace() && AMDGPU::isEntryFunctionCC(CC) &&
967 (IsAmdHsaOrMesa || ST.hasFlatScratchEnabled()) &&
968 // FlatScratchInit cannot be true for graphics CC if
969 // hasFlatScratchEnabled() is false.
970 (ST.hasFlatScratchEnabled() ||
972 !F.hasFnAttribute("amdgpu-no-flat-scratch-init"))) &&
973 !ST.hasArchitectedFlatScratch()) {
974 FlatScratchInit = true;
975 }
976
978 NumUsedUserSGPRs += getNumUserSGPRForField(ImplicitBufferPtrID);
979
982
983 if (hasDispatchPtr())
984 NumUsedUserSGPRs += getNumUserSGPRForField(DispatchPtrID);
985
986 if (hasQueuePtr())
987 NumUsedUserSGPRs += getNumUserSGPRForField(QueuePtrID);
988
990 NumUsedUserSGPRs += getNumUserSGPRForField(KernargSegmentPtrID);
991
992 if (hasDispatchID())
993 NumUsedUserSGPRs += getNumUserSGPRForField(DispatchIdID);
994
995 if (hasFlatScratchInit())
996 NumUsedUserSGPRs += getNumUserSGPRForField(FlatScratchInitID);
997
999 NumUsedUserSGPRs += getNumUserSGPRForField(PrivateSegmentSizeID);
1000}
1001
1003 assert(NumKernargPreloadSGPRs + NumSGPRs <= AMDGPU::getMaxNumUserSGPRs(ST));
1004 NumKernargPreloadSGPRs += NumSGPRs;
1005 NumUsedUserSGPRs += NumSGPRs;
1006}
1007
1009 return AMDGPU::getMaxNumUserSGPRs(ST) - NumUsedUserSGPRs;
1010}
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.
The AMDGPU TargetMachine interface definition for hw codegen targets.
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static AMDGPUSubtarget::Generation computeDefaultGeneration(const Triple &TT)
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
#define T
if(PassOpts->AAPipeline)
RISCVCC::CondCode CC
MachineRegisterInfo & MRI
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
const AMDGPUOptions & getCLOpts() const
unsigned AddressableLocalMemorySize
AMDGPUSubtarget(const Triple &TT, const AMDGPUOptions &CLOpts)
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:262
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
Diagnostic information for optimization failures.
Diagnostic information for unsupported feature in backend.
bool hasFlat() const
InstrItineraryData InstrItins
bool useVGPRIndexMode() const
void mirFileLoaded(MachineFunction &MF) const override
unsigned MaxPrivateElementSize
uint64_t getMaxBufferIntrinsicWidth(const DataLayout &DL, Type *T, Align A, bool NoWrapFromMax, bool NoPartialOOB) const
Return the maximum allowed load/store width for the given type and alignment combination based on sub...
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)
bool hasRelaxedBufferOOBMode() const
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.
bool hasUnalignedBufferAccessEnabled() const
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:76
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:28
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
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
LLVM Value Representation.
Definition Value.h:75
constexpr bool isKnownMultipleOf(ScalarTy RHS) const
This function tells the caller whether the element count is known at compile time to be a multiple of...
Definition TypeSize.h:181
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:166
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)
LLVM_ABI unsigned getLDSAllocGranule(GPUKind AK)
LLVM_ABI unsigned getAddressableLocalMemorySize(GPUKind AK, bool FullSIMDMode)
constexpr unsigned getNumWorkGroupSIMDs(bool FullSIMDMode)
unsigned getMaxNumUserSGPRs(const MCSubtargetInfo &STI)
StringRef getSchedStrategy(const AMDGPUOptions &CLOpts, const Function &F)
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.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
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
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:389
DWARFExpression::Operation Op
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Definition Alignment.h:206
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.