LLVM 24.0.0git
AMDGPUAsmPrinter.cpp
Go to the documentation of this file.
1//===-- AMDGPUAsmPrinter.cpp - AMDGPU assembly printer --------------------===//
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///
11/// The AMDGPUAsmPrinter is used to print both assembly string and also binary
12/// code. When passed an MCAsmStreamer it prints assembly and when passed
13/// an MCObjectStreamer it outputs binary code.
14//
15//===----------------------------------------------------------------------===//
16//
17
18#include "AMDGPUAsmPrinter.h"
19#include "AMDGPU.h"
23#include "AMDGPUTargetMachine.h"
24#include "GCNSubtarget.h"
29#include "R600AsmPrinter.h"
43#include "llvm/MC/MCAssembler.h"
44#include "llvm/MC/MCContext.h"
46#include "llvm/MC/MCStreamer.h"
47#include "llvm/MC/MCValue.h"
54
55using namespace llvm;
56using namespace llvm::AMDGPU;
57
58// This should get the default rounding mode from the kernel. We just set the
59// default here, but this could change if the OpenCL rounding mode pragmas are
60// used.
61//
62// The denormal mode here should match what is reported by the OpenCL runtime
63// for the CL_FP_DENORM bit from CL_DEVICE_{HALF|SINGLE|DOUBLE}_FP_CONFIG, but
64// can also be override to flush with the -cl-denorms-are-zero compiler flag.
65//
66// AMD OpenCL only sets flush none and reports CL_FP_DENORM for double
67// precision, and leaves single precision to flush all and does not report
68// CL_FP_DENORM for CL_DEVICE_SINGLE_FP_CONFIG. Mesa's OpenCL currently reports
69// CL_FP_DENORM for both.
70//
71// FIXME: It seems some instructions do not support single precision denormals
72// regardless of the mode (exp_*_f32, rcp_*_f32, rsq_*_f32, rsq_*f32, sqrt_f32,
73// and sin_f32, cos_f32 on most parts).
74
75// We want to use these instructions, and using fp32 denormals also causes
76// instructions to run at the double precision rate for the device so it's
77// probably best to just report no single precision denormals.
84
85static AsmPrinter *
87 std::unique_ptr<MCStreamer> &&Streamer) {
88 return new AMDGPUAsmPrinter(tm, std::move(Streamer));
89}
90
100
101namespace {
102class AMDGPUAsmPrinterHandler : public AsmPrinterHandler {
103protected:
104 AMDGPUAsmPrinter *Asm;
105
106public:
107 AMDGPUAsmPrinterHandler(AMDGPUAsmPrinter *A) : Asm(A) {}
108
109 void beginFunction(const MachineFunction *MF) override {}
110
111 void endFunction(const MachineFunction *MF) override { Asm->endFunction(MF); }
112
113 void endModule() override {}
114};
115} // End anonymous namespace
116
118 std::unique_ptr<MCStreamer> Streamer)
120 assert(OutStreamer && "AsmPrinter constructed without streamer");
123 if (auto *ResourceUsageW =
125 return &ResourceUsageW->getResourceInfo();
126 return nullptr;
127 };
128}
129
131 return "AMDGPU Assembly Printer";
132}
133
135 return &TM.getMCSubtargetInfo();
136}
137
139 if (!OutStreamer)
140 return nullptr;
141 return static_cast<AMDGPUTargetStreamer *>(OutStreamer->getTargetStreamer());
142}
143
147
148void AMDGPUAsmPrinter::initTargetStreamer(Module &M) {
150
151 // TODO: Which one is called first, emitStartOfAsmFile or
152 // emitFunctionBodyStart?
153 if (getTargetStreamer() && !getTargetStreamer()->getTargetID())
154 initializeTargetID(M);
155
156 const Triple &TT = M.getTargetTriple();
157 if (TT.getOS() != Triple::AMDHSA && TT.getOS() != Triple::AMDPAL)
158 return;
159
161
162 if (TT.getOS() == Triple::AMDHSA) {
164 CodeObjectVersion);
165 HSAMetadataStream->begin(M, *getTargetStreamer()->getTargetID());
166 }
167
168 if (TT.getOS() == Triple::AMDPAL)
170}
171
173 // Init target streamer if it has not yet happened
175 initTargetStreamer(M);
176
177 const Triple &TT = M.getTargetTriple();
178 if (TT.getOS() != Triple::AMDHSA)
180
181 // Emit HSA Metadata (NT_AMD_AMDGPU_HSA_METADATA).
182 // Emit HSA Metadata (NT_AMD_HSA_METADATA).
183 if (TT.getOS() == Triple::AMDHSA) {
184 HSAMetadataStream->end();
185 bool Success = HSAMetadataStream->emitTo(*getTargetStreamer());
186 (void)Success;
187 assert(Success && "Malformed HSA Metadata");
188 }
189}
190
192 const SIMachineFunctionInfo &MFI = *MF->getInfo<SIMachineFunctionInfo>();
193 const GCNSubtarget &STM = MF->getSubtarget<GCNSubtarget>();
194 const Function &F = MF->getFunction();
195
196 // TODO: We're checking this late, would be nice to check it earlier.
197 if (STM.requiresCodeObjectV6() && CodeObjectVersion < AMDGPU::AMDHSA_COV6) {
199 STM.getCPU() + " is only available on code object version 6 or better");
200 }
201
202 // TODO: Which one is called first, emitStartOfAsmFile or
203 // emitFunctionBodyStart?
204 if (!getTargetStreamer()->getTargetID())
205 initializeTargetID(*F.getParent());
206
207 if (!MFI.isEntryFunction())
208 return;
209
210 if (STM.isMesaKernel(F) &&
211 (F.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
212 F.getCallingConv() == CallingConv::SPIR_KERNEL)) {
213 AMDGPUMCKernelCodeT KernelCode;
214 getAmdKernelCode(KernelCode, CurrentProgramInfo, *MF);
215 KernelCode.validate(&STM, MF->getContext());
217 }
218
219 if (STM.isAmdHsaOS())
220 HSAMetadataStream->emitKernel(*MF, CurrentProgramInfo);
221}
222
223/// Set bits in a kernel descriptor MCExpr field:
224/// return ((Dst & ~Mask) | (Value << Shift))
225static const MCExpr *setBits(const MCExpr *Dst, const MCExpr *Value,
226 uint32_t Mask, uint32_t Shift, MCContext &Ctx) {
227 const auto *Shft = MCConstantExpr::create(Shift, Ctx);
228 const auto *Msk = MCConstantExpr::create(Mask, Ctx);
229 Dst = MCBinaryExpr::createAnd(Dst, MCUnaryExpr::createNot(Msk, Ctx), Ctx);
231 Ctx);
232 return Dst;
233}
234
236 const SIMachineFunctionInfo &MFI = *MF->getInfo<SIMachineFunctionInfo>();
237 if (!MFI.isEntryFunction())
238 return;
239
240 assert(TM.getTargetTriple().getOS() == Triple::AMDHSA);
241
242 const GCNSubtarget &STM = MF->getSubtarget<GCNSubtarget>();
243 MCContext &Ctx = MF->getContext();
244
246 getAmdhsaKernelDescriptor(*MF, CurrentProgramInfo);
247
248 // Compute inst_pref_size using MCExpr label subtraction for exact code
249 // size. At this point .Lfunc_end has been emitted (by the base AsmPrinter)
250 // right after the function code, so (Lfunc_end - func_sym) gives the
251 // exact function code size in bytes.
252 if (STM.hasInstPrefSize()) {
253 const MCExpr *CodeSizeExpr = MCBinaryExpr::createSub(
256
257 uint32_t Mask, Shift, Width, CacheLineSize;
258 STM.getInstPrefSizeArgs(Mask, Shift, Width, CacheLineSize);
259 const MCExpr *InstPrefSize =
260 AMDGPUMCExpr::createInstPrefSize(CodeSizeExpr, Ctx);
262 setBits(KD.compute_pgm_rsrc3, InstPrefSize, Mask, Shift, Ctx);
263 }
264
266 auto &Context = Streamer.getContext();
267 auto &ObjectFileInfo = *Context.getObjectFileInfo();
268 auto &ReadOnlySection = *ObjectFileInfo.getReadOnlySection();
269
270 Streamer.pushSection();
271 Streamer.switchSection(&ReadOnlySection);
272
273 // CP microcode requires the kernel descriptor to be allocated on 64 byte
274 // alignment.
275 Streamer.emitValueToAlignment(Align(64), 0, 1, 0);
276 ReadOnlySection.ensureMinAlignment(Align(64));
277
278 SmallString<128> KernelName;
279 getNameWithPrefix(KernelName, &MF->getFunction());
281 STM, KernelName, KD, CurrentProgramInfo.NumVGPRsForWavesPerEU,
283 CurrentProgramInfo.NumSGPRsForWavesPerEU,
285 CurrentProgramInfo.VCCUsed, CurrentProgramInfo.FlatUsed,
286 getTargetStreamer()->getTargetID()->isXnackOnOrAny(), Context),
287 Context),
288 CurrentProgramInfo.VCCUsed, CurrentProgramInfo.FlatUsed);
289
290 Streamer.popSection();
291}
292
294 Register RegNo = MI->getOperand(0).getReg();
295
297 raw_svector_ostream OS(Str);
298 OS << "implicit-def: "
299 << printReg(RegNo, MF->getSubtarget().getRegisterInfo());
300
301 if (MI->getAsmPrinterFlags() & AMDGPU::SGPR_SPILL)
302 OS << " : SGPR spill to VGPR lane";
303
304 OutStreamer->AddComment(OS.str());
305 OutStreamer->addBlankLine();
306}
307
309 if (TM.getTargetTriple().getOS() == Triple::AMDHSA) {
311 return;
312 }
313
314 const SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>();
315 const GCNSubtarget &STM = MF->getSubtarget<GCNSubtarget>();
316 if (MFI->isEntryFunction() && STM.isAmdHsaOrMesa(MF->getFunction())) {
317 SmallString<128> SymbolName;
318 getNameWithPrefix(SymbolName, &MF->getFunction()),
321 }
322 if (DumpCodeInstEmitter) {
323 // Disassemble function name label to text.
324 DisasmLines.push_back(MF->getName().str() + ":");
325 DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLines.back().size());
326 HexLines.emplace_back("");
327 }
328
330}
331
333 if (DumpCodeInstEmitter && !isBlockOnlyReachableByFallthrough(&MBB)) {
334 // Write a line for the basic block label if it is not only fallthrough.
335 DisasmLines.push_back((Twine("BB") + Twine(getFunctionNumber()) + "_" +
336 Twine(MBB.getNumber()) + ":")
337 .str());
338 DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLines.back().size());
339 HexLines.emplace_back("");
340 }
342}
343
346 if (GV->hasInitializer() && !isa<UndefValue>(GV->getInitializer())) {
347 OutContext.reportError({},
348 Twine(GV->getName()) +
349 ": unsupported initializer for address space");
350 return;
351 }
352
353 const Triple::OSType OS = TM.getTargetTriple().getOS();
354 if (OS == Triple::AMDHSA || OS == Triple::AMDPAL) {
356 return;
357 // With object linking, LDS definitions should have been externalized
358 // by earlier passes (e.g. LDS lowering, named barrier lowering).
359 // Only declarations reach here, emitted as SHN_AMDGPU_LDS symbols
360 // so the linker can assign their offsets.
361 assert(GV->isDeclaration() &&
362 "LDS definitions should have been externalized when object "
363 "linking is enabled");
364 }
365
366 MCSymbol *GVSym = getSymbol(GV);
367
368 GVSym->redefineIfPossible();
369 if (GVSym->isDefined() || GVSym->isVariable())
370 report_fatal_error("symbol '" + Twine(GVSym->getName()) +
371 "' is already defined");
372
373 const DataLayout &DL = GV->getDataLayout();
374 uint64_t Size = GV->getGlobalSize(DL);
375 Align Alignment = GV->getAlign().value_or(Align(4));
376
377 emitVisibility(GVSym, GV->getVisibility(), !GV->isDeclaration());
378 emitLinkage(GV, GVSym);
379 auto *TS = getTargetStreamer();
380 TS->emitAMDGPULDS(GVSym, Size, Alignment);
381 return;
382 }
383
385}
386
388 const Triple &TT = M.getTargetTriple();
389 if (TT.getSubArch() == Triple::NoSubArch) {
390 Triple::SubArchType SubArch =
392 if (SubArch != Triple::NoSubArch) {
393 Triple Fixed(TT);
394 Fixed.setArch(Triple::amdgpu, SubArch);
395 M.getContext().diagnose(DiagnosticInfoGeneric(
396 "codegen with no subarch in the target triple is deprecated and will "
397 "become an error; use the target triple '" +
398 Fixed.str() + "' instead",
399 DS_Warning));
400 } else {
401 M.getContext().diagnose(DiagnosticInfoGeneric(
402 "codegen with no subarch in the target triple is deprecated and will "
403 "become an error",
404 DS_Warning));
405 }
406 }
407
408 CodeObjectVersion = AMDGPU::getAMDHSACodeObjectVersion(M);
409
410 if (TT.getOS() == Triple::AMDHSA) {
411 switch (CodeObjectVersion) {
413 HSAMetadataStream = std::make_unique<HSAMD::MetadataStreamerMsgPackV4>();
414 break;
416 HSAMetadataStream = std::make_unique<HSAMD::MetadataStreamerMsgPackV5>();
417 break;
419 HSAMetadataStream = std::make_unique<HSAMD::MetadataStreamerMsgPackV6>();
420 break;
421 default:
422 reportFatalUsageError("unsupported code object version");
423 }
424
425 addAsmPrinterHandler(std::make_unique<AMDGPUAsmPrinterHandler>(this));
426 }
427
429}
430
431/// Mimics GCNSubtarget::computeOccupancy for MCExpr.
432///
433/// Remove dependency on GCNSubtarget and depend only only the necessary values
434/// for said occupancy computation. Should match computeOccupancy implementation
435/// without passing \p STM on.
436const AMDGPUMCExpr *createOccupancy(unsigned InitOcc, const MCExpr *NumSGPRs,
437 const MCExpr *NumVGPRs,
438 unsigned DynamicVGPRBlockSize,
439 const GCNSubtarget &STM, MCContext &Ctx) {
440 unsigned MaxWaves = STM.getMaxWavesPerEU();
441 unsigned Granule = IsaInfo::getVGPRAllocGranule(STM, DynamicVGPRBlockSize);
442 unsigned TargetTotalNumVGPRs = STM.getTotalNumVGPRs();
443
444 // Bake the per-function SGPR budget into the operands so the late-evaluated
445 // MCExpr stays arithmetic. The trap reservation in particular is implicit on
446 // amdhsa and lives on STM, not on the assembler's MCSubtargetInfo.
448 unsigned SGPRTotal = AMDGPU::getTotalNumSGPRs(Kind);
449 unsigned SGPRGranule = AMDGPU::getSGPRAllocGranule(Kind);
450 unsigned SGPRTrapReserve = STM.hasTrapHandler() ? IsaInfo::TRAP_NUM_SGPRS : 0;
451
452 auto CreateExpr = [&Ctx](unsigned Value) {
453 return MCConstantExpr::create(Value, Ctx);
454 };
455
456 // Zero SGPR count when SGPRs don't limit occupancy, so the MCExpr skips the
457 // SGPR term without having to test the generation itself.
458 const MCExpr *SGPRArg =
459 IsaInfo::isSGPROccupancyLimited(STM) ? NumSGPRs : CreateExpr(0);
460
462 {CreateExpr(MaxWaves), CreateExpr(Granule),
463 CreateExpr(TargetTotalNumVGPRs),
464 CreateExpr(InitOcc), CreateExpr(SGPRTotal),
465 CreateExpr(SGPRGranule),
466 CreateExpr(SGPRTrapReserve), SGPRArg, NumVGPRs},
467 Ctx);
468}
469
470void AMDGPUAsmPrinter::validateMCResourceInfo(Function &F) {
471 if (F.isDeclaration() || !AMDGPU::isModuleEntryFunctionCC(F.getCallingConv()))
472 return;
473
475 const GCNSubtarget &STM = TM.getSubtarget<GCNSubtarget>(F);
476 MCSymbol *FnSym = TM.getSymbol(&F);
477
478 auto TryGetMCExprValue = [](const MCExpr *Value, uint64_t &Res) -> bool {
479 int64_t Val;
480 if (Value->evaluateAsAbsolute(Val)) {
481 Res = Val;
482 return true;
483 }
484 return false;
485 };
486
487 const uint64_t MaxScratchPerWorkitem =
489 MCSymbol *ScratchSizeSymbol =
490 RI.getSymbol(FnSym->getName(), RIK::RIK_PrivateSegSize, OutContext);
491 uint64_t ScratchSize;
492 if (ScratchSizeSymbol->isVariable() &&
493 TryGetMCExprValue(ScratchSizeSymbol->getVariableValue(), ScratchSize) &&
494 ScratchSize > MaxScratchPerWorkitem) {
495 DiagnosticInfoStackSize DiagStackSize(F, ScratchSize, MaxScratchPerWorkitem,
496 DS_Error);
497 F.getContext().diagnose(DiagStackSize);
498 }
499
500 // Validate addressable scalar registers (i.e., prior to added implicit
501 // SGPRs).
502 MCSymbol *NumSGPRSymbol =
503 RI.getSymbol(FnSym->getName(), RIK::RIK_NumSGPR, OutContext);
505 !STM.hasSGPRInitBug()) {
506 unsigned MaxAddressableNumSGPRs = STM.getAddressableNumSGPRs();
507 uint64_t NumSgpr;
508 if (NumSGPRSymbol->isVariable() &&
509 TryGetMCExprValue(NumSGPRSymbol->getVariableValue(), NumSgpr) &&
510 NumSgpr > MaxAddressableNumSGPRs) {
511 F.getContext().diagnose(DiagnosticInfoResourceLimit(
512 F, "addressable scalar registers", NumSgpr, MaxAddressableNumSGPRs,
514 return;
515 }
516 }
517
518 MCSymbol *VCCUsedSymbol =
519 RI.getSymbol(FnSym->getName(), RIK::RIK_UsesVCC, OutContext);
520 MCSymbol *FlatUsedSymbol =
521 RI.getSymbol(FnSym->getName(), RIK::RIK_UsesFlatScratch, OutContext);
522 uint64_t VCCUsed, FlatUsed, NumSgpr;
523
524 if (NumSGPRSymbol->isVariable() && VCCUsedSymbol->isVariable() &&
525 FlatUsedSymbol->isVariable() &&
526 TryGetMCExprValue(NumSGPRSymbol->getVariableValue(), NumSgpr) &&
527 TryGetMCExprValue(VCCUsedSymbol->getVariableValue(), VCCUsed) &&
528 TryGetMCExprValue(FlatUsedSymbol->getVariableValue(), FlatUsed)) {
529
530 // Recomputes NumSgprs + implicit SGPRs but all symbols should now be
531 // resolvable.
532 NumSgpr += IsaInfo::getNumExtraSGPRs(
533 STM, VCCUsed, FlatUsed,
534 getTargetStreamer()->getTargetID()->isXnackOnOrAny());
536 STM.hasSGPRInitBug()) {
537 unsigned MaxAddressableNumSGPRs = STM.getAddressableNumSGPRs();
538 if (NumSgpr > MaxAddressableNumSGPRs) {
539 F.getContext().diagnose(DiagnosticInfoResourceLimit(
540 F, "scalar registers", NumSgpr, MaxAddressableNumSGPRs, DS_Error,
542 return;
543 }
544 }
545
546 MCSymbol *NumVgprSymbol =
547 RI.getSymbol(FnSym->getName(), RIK::RIK_NumVGPR, OutContext);
548 MCSymbol *NumAgprSymbol =
549 RI.getSymbol(FnSym->getName(), RIK::RIK_NumAGPR, OutContext);
550 uint64_t NumVgpr, NumAgpr;
551
552 MachineModuleInfo &MMI = *GetMMI();
553 MachineFunction *MF = MMI.getMachineFunction(F);
554 if (MF && NumVgprSymbol->isVariable() && NumAgprSymbol->isVariable() &&
555 TryGetMCExprValue(NumVgprSymbol->getVariableValue(), NumVgpr) &&
556 TryGetMCExprValue(NumAgprSymbol->getVariableValue(), NumAgpr)) {
557 const SIMachineFunctionInfo &MFI = *MF->getInfo<SIMachineFunctionInfo>();
558 unsigned MaxWaves = MFI.getMaxWavesPerEU();
559 uint64_t TotalNumVgpr =
560 getTotalNumVGPRs(STM.hasGFX90AInsts(), NumAgpr, NumVgpr);
561 uint64_t NumVGPRsForWavesPerEU =
562 std::max({TotalNumVgpr, (uint64_t)1,
564 MaxWaves, MFI.getDynamicVGPRBlockSize())});
565 uint64_t NumSGPRsForWavesPerEU = std::max(
566 {NumSgpr, (uint64_t)1, (uint64_t)STM.getMinNumSGPRs(MaxWaves)});
567 const MCExpr *OccupancyExpr = createOccupancy(
568 STM.getOccupancyWithWorkGroupSizes(*MF).second,
569 MCConstantExpr::create(NumSGPRsForWavesPerEU, OutContext),
570 MCConstantExpr::create(NumVGPRsForWavesPerEU, OutContext),
572 uint64_t Occupancy;
573
574 const auto [MinWEU, MaxWEU] = AMDGPU::getIntegerPairAttribute(
575 F, "amdgpu-waves-per-eu", {0, 0}, true);
576
577 if (TryGetMCExprValue(OccupancyExpr, Occupancy) && Occupancy < MinWEU) {
578 DiagnosticInfoOptimizationFailure Diag(
579 F, F.getSubprogram(),
580 "failed to meet occupancy target given by 'amdgpu-waves-per-eu' in "
581 "'" +
582 F.getName() + "': desired occupancy was " + Twine(MinWEU) +
583 ", final occupancy is " + Twine(Occupancy));
584 F.getContext().diagnose(Diag);
585 return;
586 }
587 }
588 }
589}
590
591static void appendTypeEncoding(std::string &Enc, Type *Ty, const DataLayout &DL,
592 bool IsReturnType) {
593 if (Ty->isVoidTy()) {
594 Enc += 'v';
595 return;
596 }
597 unsigned Bits = DL.getTypeSizeInBits(Ty);
598 // Zero-sized non-void types (e.g. `{}` or `[0 x i8]`) consume no ABI
599 // registers. For returns, emit the same no-result marker as void so the
600 // parameter encoding still has an explicit return-type prefix.
601 if (Bits == 0) {
602 if (IsReturnType)
603 Enc += 'v';
604 return;
605 }
606 if (Bits <= 32)
607 Enc += 'i';
608 else if (Bits <= 64)
609 Enc += 'l';
610 else
611 Enc.append(divideCeil(Bits, 32), 'i');
612}
613
614static std::string computeTypeId(const FunctionType *FTy,
615 const DataLayout &DL) {
616 std::string Enc;
617 appendTypeEncoding(Enc, FTy->getReturnType(), DL, /*IsReturnType=*/true);
618 for (Type *ParamTy : FTy->params())
619 appendTypeEncoding(Enc, ParamTy, DL, /*IsReturnType=*/false);
620 return Enc;
621}
622
623void AMDGPUAsmPrinter::collectCallEdge(const MachineInstr &MI) {
625 return;
626 const SIInstrInfo *TII = MF->getSubtarget<GCNSubtarget>().getInstrInfo();
627 const MachineOperand *Callee =
628 TII->getNamedOperand(MI, AMDGPU::OpName::callee);
629 if (!Callee || !Callee->isGlobal())
630 return;
631 DirectCallEdges.insert(
632 {getSymbol(&MF->getFunction()), getSymbol(Callee->getGlobal())});
633}
634
635void AMDGPUAsmPrinter::emitAMDGPUInfo(Module &M) {
637 return;
638
639 const NamedMDNode *LDSMD = M.getNamedMetadata("amdgpu.lds.uses");
640 bool HasLDSUses = LDSMD && LDSMD->getNumOperands() > 0;
641
642 const NamedMDNode *BarMD = M.getNamedMetadata("amdgpu.named_barrier.uses");
643 bool HasNamedBarriers = BarMD && BarMD->getNumOperands() > 0;
644
645 // Collect address-taken functions (with type IDs) and indirect call sites.
646 DenseMap<const Function *, std::string> AddrTakenTypeIds;
647 using IndirectCallInfo = std::pair<const Function *, std::string>;
649
650 for (const Function &F : M) {
651 bool IsKernel = AMDGPU::isKernel(F.getCallingConv());
652
653 if (!IsKernel && F.hasAddressTaken(/*PutOffender=*/nullptr,
654 /*IgnoreCallbackUses=*/false,
655 /*IgnoreAssumeLikeCalls=*/true,
656 /*IgnoreLLVMUsed=*/true)) {
657 AddrTakenTypeIds[&F] =
658 computeTypeId(F.getFunctionType(), M.getDataLayout());
659 }
660
661 if (F.isDeclaration())
662 continue;
663
664 StringSet<> SeenTypeIds;
665 for (const BasicBlock &BB : F) {
666 for (const Instruction &I : BB) {
667 const auto *CB = dyn_cast<CallBase>(&I);
668 if (!CB || !CB->isIndirectCall())
669 continue;
670 std::string TId =
671 computeTypeId(CB->getFunctionType(), M.getDataLayout());
672 if (SeenTypeIds.insert(TId).second)
673 IndirectCalls.push_back({&F, std::move(TId)});
674 }
675 }
676 }
677
678 if (FunctionInfos.empty() && DirectCallEdges.empty() && !HasLDSUses &&
679 !HasNamedBarriers && AddrTakenTypeIds.empty() && IndirectCalls.empty())
680 return;
681
682 AMDGPU::InfoSectionData Data;
683 Data.Funcs = std::move(FunctionInfos);
684
685 for (auto &[F, TypeId] : AddrTakenTypeIds) {
686 MCSymbol *Sym = getSymbol(F);
687 Data.TypeIds.push_back({Sym, TypeId});
688 }
689
690 for (auto &[CallerSym, CalleeSym] : DirectCallEdges)
691 Data.Calls.push_back({CallerSym, CalleeSym});
692 DirectCallEdges.clear();
693
694 if (HasLDSUses) {
695 for (const MDNode *N : LDSMD->operands()) {
696 auto *Func = mdconst::extract<Function>(N->getOperand(0));
697 auto *LdsVar = mdconst::extract<GlobalVariable>(N->getOperand(1));
698 Data.Uses.push_back({getSymbol(Func), getSymbol(LdsVar)});
699 }
700 }
701
702 if (HasNamedBarriers) {
703 for (const MDNode *N : BarMD->operands()) {
704 auto *BarVar = mdconst::extract<GlobalVariable>(N->getOperand(0));
705 MCSymbol *BarSym = getSymbol(BarVar);
706 for (unsigned I = 1, E = N->getNumOperands(); I < E; ++I) {
707 auto *Func = mdconst::extract<Function>(N->getOperand(I));
708 Data.Uses.push_back({getSymbol(Func), BarSym});
709 }
710 }
711 }
712
713 for (auto &[Caller, Enc] : IndirectCalls) {
714 MCSymbol *CallerSym = getSymbol(Caller);
715 Data.IndirectCalls.push_back({CallerSym, Enc});
716 }
717
719}
720
722 const Triple &TT = M.getTargetTriple();
723
724 // Pad with s_code_end to help tools and guard against instruction prefetch
725 // causing stale data in caches. Arguably this should be done by the linker,
726 // which is why this isn't done for Mesa.
727 // Don't do it if there is no code.
728 const MCSubtargetInfo &STI = *getGlobalSTI();
729 if ((AMDGPU::isGFX10Plus(STI) || AMDGPU::isGFX90A(STI)) &&
730 (TT.getOS() == Triple::AMDHSA || TT.getOS() == Triple::AMDPAL)) {
732 if (TextSect->hasInstructions()) {
733 OutStreamer->switchSection(TextSect);
735 }
736 }
737
738 // Emit the unified .amdgpu.info section (per-function resources, call graph,
739 // LDS/named-barrier use edges, indirect calls, and address-taken type IDs).
740 emitAMDGPUInfo(M);
741
742 // Assign expressions which can only be resolved when all other functions are
743 // known.
744 RI.finalize(OutContext);
745
746 // Switch section and emit all GPR maximums within the processed module.
747 OutStreamer->pushSection();
748 MCSectionELF *MaxGPRSection =
749 OutContext.getELFSection(".AMDGPU.gpr_maximums", ELF::SHT_PROGBITS, 0);
750 OutStreamer->switchSection(MaxGPRSection);
752 RI.getMaxVGPRSymbol(OutContext), RI.getMaxAGPRSymbol(OutContext),
753 RI.getMaxSGPRSymbol(OutContext), RI.getMaxNamedBarrierSymbol(OutContext));
754 OutStreamer->popSection();
755
756 // In the object-linking pipeline per-function resource MCExprs reference
757 // external callee symbols that cannot be evaluated here, so cross-TU limit
758 // checks would silently no-op for every non-leaf function. Defer resource
759 // sanity checking to the linker, which re-validates against the aggregated
760 // call graph in the combined .amdgpu.info metadata.
762 for (Function &F : M.functions())
763 validateMCResourceInfo(F);
764 }
765
766 RI.reset();
767
769}
770
771SmallString<128> AMDGPUAsmPrinter::getMCExprStr(const MCExpr *Value) {
773 raw_svector_ostream OSS(Str);
775 auto &Context = Streamer.getContext();
776 const MCExpr *New = foldAMDGPUMCExpr(Value, Context);
777 printAMDGPUMCExpr(New, OSS, &MAI);
778 return Str;
779}
780
781// Print comments that apply to both callable functions and entry points.
782void AMDGPUAsmPrinter::emitCommonFunctionComments(
783 const MCExpr *NumVGPR, const MCExpr *NumAGPR, const MCExpr *TotalNumVGPR,
784 const MCExpr *NumSGPR, const MCExpr *ScratchSize, uint64_t CodeSize,
785 const AMDGPUMachineFunctionInfo *MFI) {
786 OutStreamer->emitRawComment(" codeLenInByte = " + Twine(CodeSize), false);
787 OutStreamer->emitRawComment(" TotalNumSgprs: " + getMCExprStr(NumSGPR),
788 false);
789 OutStreamer->emitRawComment(" NumVgprs: " + getMCExprStr(NumVGPR), false);
790 if (NumAGPR && TotalNumVGPR) {
791 OutStreamer->emitRawComment(" NumAgprs: " + getMCExprStr(NumAGPR), false);
792 OutStreamer->emitRawComment(" TotalNumVgprs: " + getMCExprStr(TotalNumVGPR),
793 false);
794 }
795 OutStreamer->emitRawComment(" ScratchSize: " + getMCExprStr(ScratchSize),
796 false);
797 OutStreamer->emitRawComment(" MemoryBound: " + Twine(MFI->isMemoryBound()),
798 false);
799}
800
801const MCExpr *AMDGPUAsmPrinter::getAmdhsaKernelCodeProperties(
802 const MachineFunction &MF) const {
803 const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
804 MCContext &Ctx = MF.getContext();
805 uint16_t KernelCodeProperties = 0;
806 const GCNUserSGPRUsageInfo &UserSGPRInfo = MFI.getUserSGPRInfo();
807
808 if (UserSGPRInfo.hasPrivateSegmentBuffer()) {
809 KernelCodeProperties |=
810 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER;
811 }
812 if (UserSGPRInfo.hasDispatchPtr()) {
813 KernelCodeProperties |=
814 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR;
815 }
816 if (UserSGPRInfo.hasQueuePtr()) {
817 KernelCodeProperties |= amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR;
818 }
819 if (UserSGPRInfo.hasKernargSegmentPtr()) {
820 KernelCodeProperties |=
821 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR;
822 }
823 if (UserSGPRInfo.hasDispatchID()) {
824 KernelCodeProperties |=
825 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID;
826 }
827 if (UserSGPRInfo.hasFlatScratchInit()) {
828 KernelCodeProperties |=
829 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT;
830 }
831 if (UserSGPRInfo.hasPrivateSegmentSize()) {
832 KernelCodeProperties |=
833 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE;
834 }
835 if (MF.getSubtarget<GCNSubtarget>().isWave32()) {
836 KernelCodeProperties |=
837 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32;
838 }
839
840 // CurrentProgramInfo.DynamicCallStack is a MCExpr and could be
841 // un-evaluatable at this point so it cannot be conditionally checked here.
842 // Instead, we'll directly shift the possibly unknown MCExpr into its place
843 // and bitwise-or it into KernelCodeProperties.
844 const MCExpr *KernelCodePropExpr =
845 MCConstantExpr::create(KernelCodeProperties, Ctx);
846 const MCExpr *OrValue = MCConstantExpr::create(
847 amdhsa::KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK_SHIFT, Ctx);
848 OrValue = MCBinaryExpr::createShl(CurrentProgramInfo.DynamicCallStack,
849 OrValue, Ctx);
850 KernelCodePropExpr = MCBinaryExpr::createOr(KernelCodePropExpr, OrValue, Ctx);
851
852 return KernelCodePropExpr;
853}
854
855MCKernelDescriptor
856AMDGPUAsmPrinter::getAmdhsaKernelDescriptor(const MachineFunction &MF,
857 const SIProgramInfo &PI) const {
858 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
859 const Function &F = MF.getFunction();
860 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
861 MCContext &Ctx = MF.getContext();
862
863 MCKernelDescriptor KernelDescriptor;
864
865 KernelDescriptor.group_segment_fixed_size =
867 KernelDescriptor.private_segment_fixed_size = PI.ScratchSize;
868
869 Align MaxKernArgAlign;
870 KernelDescriptor.kernarg_size = MCConstantExpr::create(
871 STM.getKernArgSegmentSize(F, MaxKernArgAlign), Ctx);
872
873 KernelDescriptor.compute_pgm_rsrc1 = PI.getComputePGMRSrc1(STM, Ctx);
874 KernelDescriptor.compute_pgm_rsrc2 = PI.getComputePGMRSrc2(STM, Ctx);
875 KernelDescriptor.kernel_code_properties = getAmdhsaKernelCodeProperties(MF);
876
877 int64_t PGM_Rsrc3 = 1;
878 bool EvaluatableRsrc3 =
879 CurrentProgramInfo.ComputePGMRSrc3->evaluateAsAbsolute(PGM_Rsrc3);
880 (void)PGM_Rsrc3;
881 (void)EvaluatableRsrc3;
883 STM.hasGFX90AInsts() || STM.hasGFX1250Insts() || !EvaluatableRsrc3 ||
884 static_cast<uint64_t>(PGM_Rsrc3) == 0);
885 KernelDescriptor.compute_pgm_rsrc3 = CurrentProgramInfo.ComputePGMRSrc3;
886
887 KernelDescriptor.kernarg_preload = MCConstantExpr::create(
888 AMDGPU::hasKernargPreload(STM) ? Info->getNumKernargPreloadedSGPRs() : 0,
889 Ctx);
890
891 return KernelDescriptor;
892}
893
895 // Init target streamer lazily on the first function so that previous passes
896 // can set metadata.
898 initTargetStreamer(*MF.getFunction().getParent());
899
900 ResourceUsage = GetResourceUsage(MF);
901 CurrentProgramInfo.reset(MF);
902
903 const AMDGPUMachineFunctionInfo *MFI =
904 MF.getInfo<AMDGPUMachineFunctionInfo>();
905 MCContext &Ctx = MF.getContext();
906
907 // The starting address of all shader programs must be 256 bytes aligned.
908 // Regular functions just need the basic required instruction alignment.
909 MF.ensureAlignment(MFI->isEntryFunction() ? Align(256) : Align(4));
910
912
913 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
915 // FIXME: This should be an explicit check for Mesa.
916 if (!STM.isAmdHsaOS() && !STM.isAmdPalOS()) {
917 MCSectionELF *ConfigSection =
918 Context.getELFSection(".AMDGPU.config", ELF::SHT_PROGBITS, 0);
919 OutStreamer->switchSection(ConfigSection);
920 }
921
922 RI.gatherResourceInfo(MF, *ResourceUsage, OutContext);
923
926 *ResourceUsage;
927 FunctionInfos.push_back(
928 {/*NumSGPR=*/static_cast<uint32_t>(RU.NumExplicitSGPR),
929 /*NumArchVGPR=*/static_cast<uint32_t>(RU.NumVGPR),
930 /*NumAccVGPR=*/static_cast<uint32_t>(RU.NumAGPR),
931 /*PrivateSegmentSize=*/static_cast<uint32_t>(RU.PrivateSegmentSize),
932 /*UsesVCC=*/RU.UsesVCC,
933 /*UsesFlatScratch=*/RU.UsesFlatScratch,
934 /*HasDynStack=*/RU.HasDynamicallySizedStack,
935 /*Sym=*/getSymbol(&MF.getFunction())});
936 }
937
938 if (MFI->isModuleEntryFunction()) {
939 getSIProgramInfo(CurrentProgramInfo, MF);
940 }
941
942 if (STM.isAmdPalOS()) {
943 if (MFI->isEntryFunction())
944 EmitPALMetadata(MF, CurrentProgramInfo);
945 else if (MFI->isModuleEntryFunction())
946 emitPALFunctionMetadata(MF);
947 } else if (!STM.isAmdHsaOS()) {
948 EmitProgramInfoSI(MF, CurrentProgramInfo);
949 }
950
951 DumpCodeInstEmitter = nullptr;
952 if (STM.dumpCode()) {
953 // For -dumpcode, get the assembler out of the streamer. This only works
954 // with -filetype=obj.
955 MCAssembler *Assembler = OutStreamer->getAssemblerPtr();
956 if (Assembler)
957 DumpCodeInstEmitter = Assembler->getEmitterPtr();
958 }
959
960 DisasmLines.clear();
961 HexLines.clear();
963
965
966 emitResourceUsageRemarks(MF, CurrentProgramInfo, MFI->isModuleEntryFunction(),
967 STM.hasMAIInsts());
968
969 {
972 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_NumVGPR, OutContext),
973 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_NumAGPR, OutContext),
974 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_NumSGPR, OutContext),
975 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_NumNamedBarrier,
976 OutContext),
977 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_PrivateSegSize,
978 OutContext),
979 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_UsesVCC, OutContext),
980 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_UsesFlatScratch,
981 OutContext),
982 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_HasDynSizedStack,
983 OutContext),
984 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_HasRecursion,
985 OutContext),
986 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_HasIndirectCall,
987 OutContext));
988 }
989
990 // Emit _dvgpr$ symbol when appropriate.
991 emitDVgprSymbol(MF);
992
993 if (isVerbose()) {
994 MCSectionELF *CommentSection =
995 Context.getELFSection(".AMDGPU.csdata", ELF::SHT_PROGBITS, 0);
996 OutStreamer->switchSection(CommentSection);
997
998 if (!MFI->isEntryFunction()) {
1000 OutStreamer->emitRawComment(" Function info:", false);
1001
1002 emitCommonFunctionComments(
1003 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_NumVGPR, OutContext)
1004 ->getVariableValue(),
1005 STM.hasMAIInsts() ? RI.getSymbol(CurrentFnSym->getName(),
1006 RIK::RIK_NumAGPR, OutContext)
1007 ->getVariableValue()
1008 : nullptr,
1009 RI.createTotalNumVGPRs(MF, Ctx),
1010 RI.createTotalNumSGPRs(
1011 MF,
1012 MF.getSubtarget<GCNSubtarget>().getTargetID().isXnackOnOrAny(),
1013 Ctx),
1014 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_PrivateSegSize,
1015 OutContext)
1016 ->getVariableValue(),
1017 CurrentProgramInfo.getFunctionCodeSize(MF), MFI);
1018 return false;
1019 }
1020
1021 OutStreamer->emitRawComment(" Kernel info:", false);
1022 emitCommonFunctionComments(
1023 CurrentProgramInfo.NumArchVGPR,
1024 STM.hasMAIInsts() ? CurrentProgramInfo.NumAccVGPR : nullptr,
1025 CurrentProgramInfo.NumVGPR, CurrentProgramInfo.NumSGPR,
1026 CurrentProgramInfo.ScratchSize,
1027 CurrentProgramInfo.getFunctionCodeSize(MF), MFI);
1028
1029 OutStreamer->emitRawComment(
1030 " FloatMode: " + Twine(CurrentProgramInfo.FloatMode), false);
1031 OutStreamer->emitRawComment(
1032 " IeeeMode: " + Twine(CurrentProgramInfo.IEEEMode), false);
1033 OutStreamer->emitRawComment(
1034 " LDSByteSize: " + Twine(CurrentProgramInfo.LDSSize) +
1035 " bytes/workgroup (compile time only)",
1036 false);
1037
1038 OutStreamer->emitRawComment(
1039 " SGPRBlocks: " + getMCExprStr(CurrentProgramInfo.SGPRBlocks), false);
1040
1041 OutStreamer->emitRawComment(
1042 " VGPRBlocks: " + getMCExprStr(CurrentProgramInfo.VGPRBlocks), false);
1043
1044 OutStreamer->emitRawComment(
1045 " NumSGPRsForWavesPerEU: " +
1046 getMCExprStr(CurrentProgramInfo.NumSGPRsForWavesPerEU),
1047 false);
1048 OutStreamer->emitRawComment(
1049 " NumVGPRsForWavesPerEU: " +
1050 getMCExprStr(CurrentProgramInfo.NumVGPRsForWavesPerEU),
1051 false);
1052
1053 if (STM.hasGFX90AInsts()) {
1054 const MCExpr *AdjustedAccum = MCBinaryExpr::createAdd(
1055 CurrentProgramInfo.AccumOffset, MCConstantExpr::create(1, Ctx), Ctx);
1056 AdjustedAccum = MCBinaryExpr::createMul(
1057 AdjustedAccum, MCConstantExpr::create(4, Ctx), Ctx);
1058 OutStreamer->emitRawComment(
1059 " AccumOffset: " + getMCExprStr(AdjustedAccum), false);
1060 }
1061
1062 if (STM.hasGFX1250Insts())
1063 OutStreamer->emitRawComment(
1064 " NamedBarCnt: " + getMCExprStr(CurrentProgramInfo.NamedBarCnt),
1065 false);
1066
1067 OutStreamer->emitRawComment(
1068 " Occupancy: " + getMCExprStr(CurrentProgramInfo.Occupancy), false);
1069
1070 OutStreamer->emitRawComment(
1071 " WaveLimiterHint : " + Twine(MFI->needsWaveLimiter()), false);
1072
1073 OutStreamer->emitRawComment(
1074 " COMPUTE_PGM_RSRC2:SCRATCH_EN: " +
1075 getMCExprStr(CurrentProgramInfo.ScratchEnable),
1076 false);
1077 OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:USER_SGPR: " +
1078 Twine(CurrentProgramInfo.UserSGPR),
1079 false);
1080 OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TRAP_HANDLER: " +
1081 Twine(CurrentProgramInfo.TrapHandlerEnable),
1082 false);
1083 OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TGID_X_EN: " +
1084 Twine(CurrentProgramInfo.TGIdXEnable),
1085 false);
1086 OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TGID_Y_EN: " +
1087 Twine(CurrentProgramInfo.TGIdYEnable),
1088 false);
1089 OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TGID_Z_EN: " +
1090 Twine(CurrentProgramInfo.TGIdZEnable),
1091 false);
1092 OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TIDIG_COMP_CNT: " +
1093 Twine(CurrentProgramInfo.TIdIGCompCount),
1094 false);
1095
1096 [[maybe_unused]] int64_t PGMRSrc3;
1098 STM.hasGFX90AInsts() || STM.hasGFX1250Insts() ||
1099 (CurrentProgramInfo.ComputePGMRSrc3->evaluateAsAbsolute(PGMRSrc3) &&
1100 static_cast<uint64_t>(PGMRSrc3) == 0));
1101 if (STM.hasGFX90AInsts()) {
1102 OutStreamer->emitRawComment(
1103 " COMPUTE_PGM_RSRC3_GFX90A:ACCUM_OFFSET: " +
1104 getMCExprStr(MCKernelDescriptor::bits_get(
1105 CurrentProgramInfo.ComputePGMRSrc3,
1106 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET_SHIFT,
1107 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET, Ctx)),
1108 false);
1109 OutStreamer->emitRawComment(
1110 " COMPUTE_PGM_RSRC3_GFX90A:TG_SPLIT: " +
1111 getMCExprStr(MCKernelDescriptor::bits_get(
1112 CurrentProgramInfo.ComputePGMRSrc3,
1113 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT_SHIFT,
1114 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT, Ctx)),
1115 false);
1116 }
1117 }
1118
1119 if (DumpCodeInstEmitter) {
1120
1121 OutStreamer->switchSection(
1122 Context.getELFSection(".AMDGPU.disasm", ELF::SHT_PROGBITS, 0));
1123
1124 for (size_t i = 0; i < DisasmLines.size(); ++i) {
1125 std::string Comment = "\n";
1126 if (!HexLines[i].empty()) {
1127 Comment = std::string(DisasmLineMaxLen - DisasmLines[i].size(), ' ');
1128 Comment += " ; " + HexLines[i] + "\n";
1129 }
1130
1131 OutStreamer->emitBytes(StringRef(DisasmLines[i]));
1132 OutStreamer->emitBytes(StringRef(Comment));
1133 }
1134 }
1135
1136 return false;
1137}
1138
1139// When appropriate, add a _dvgpr$ symbol, with the value of the function
1140// symbol, plus an offset encoding one less than the number of VGPR blocks used
1141// by the function in bits 5..3 of the symbol value. A "VGPR block" can be
1142// either 16 VGPRs (for a max of 128), or 32 VGPRs (for a max of 256). This is
1143// used by a front-end to have functions that are chained rather than called,
1144// and a dispatcher that dynamically resizes the VGPR count before dispatching
1145// to a function.
1146void AMDGPUAsmPrinter::emitDVgprSymbol(MachineFunction &MF) {
1148 if (MFI.isDynamicVGPREnabled() &&
1150 MCContext &Ctx = MF.getContext();
1151 unsigned BlockSize = MFI.getDynamicVGPRBlockSize();
1152
1153 const MCExpr *EncodedBlocks;
1154 MCValue NumVGPRs;
1155 if (CurrentProgramInfo.NumVGPRsForWavesPerEU->evaluateAsRelocatable(
1156 NumVGPRs, nullptr) &&
1157 NumVGPRs.isAbsolute()) {
1158
1159 // Calculate number of VGPR blocks.
1160 // Treat 0 VGPRs as 1 VGPR to avoid underflowing.
1161 unsigned NumBlocks =
1162 divideCeil(std::max(unsigned(NumVGPRs.getConstant()), 1U), BlockSize);
1163
1164 if (NumBlocks > AMDGPU::IsaInfo::MaxDynamicVGPRBlocks) {
1166 {}, "DVGPR block count " + Twine(NumBlocks) +
1167 " exceeds maximum of " +
1169 " for __dvgpr$ symbol for '" +
1170 Twine(CurrentFnSym->getName()) + "'");
1171 return;
1172 }
1173 unsigned EncodedNumBlocks = (NumBlocks - 1) << 3;
1174 EncodedBlocks = MCConstantExpr::create(EncodedNumBlocks, Ctx);
1175 } else {
1176 // Value not yet available so build a symbolic MCExpr:
1177 // ((alignTo(max(NumVGPRs, 1), BlockSize) / BlockSize - 1) << 3
1178 const MCExpr *One = MCConstantExpr::create(1, Ctx);
1179 const MCExpr *BlockSizeConst = MCConstantExpr::create(BlockSize, Ctx);
1180 const MCExpr *MaxVGPRs = AMDGPUMCExpr::createMax(
1181 {CurrentProgramInfo.NumVGPRsForWavesPerEU, One}, Ctx);
1182 const MCExpr *NumBlocks = MCBinaryExpr::createDiv(
1183 AMDGPUMCExpr::createAlignTo(MaxVGPRs, BlockSizeConst, Ctx),
1184 BlockSizeConst, Ctx);
1185 EncodedBlocks =
1187 MCConstantExpr::create(3, Ctx), Ctx);
1188 }
1189
1190 // Add to function symbol to create _dvgpr$ symbol.
1191 const MCExpr *DVgprFuncVal = MCBinaryExpr::createAdd(
1192 MCSymbolRefExpr::create(CurrentFnSym, Ctx), EncodedBlocks, Ctx);
1193 MCSymbol *DVgprFuncSym =
1194 Ctx.getOrCreateSymbol(Twine("_dvgpr$") + CurrentFnSym->getName());
1195 OutStreamer->emitAssignment(DVgprFuncSym, DVgprFuncVal);
1196 emitVisibility(DVgprFuncSym, MF.getFunction().getVisibility());
1197 emitLinkage(&MF.getFunction(), DVgprFuncSym);
1198 }
1199}
1200
1201// TODO: Fold this into emitFunctionBodyStart.
1202void AMDGPUAsmPrinter::initializeTargetID(const Module &M) {
1204
1205 auto &TSTargetID = getTargetStreamer()->getTargetID();
1206
1207 // Error if -mattr specified xnack or sramecc.
1208 // TODO: Remove this when subtarget features removed.
1209 StringRef FeatureString = getGlobalSTI()->getFeatureString();
1210 if (FeatureString.contains("xnack")) {
1211 M.getContext().diagnose(DiagnosticInfoGeneric(
1212 "xnack/sramecc should be specified via module flags. "
1213 "Use module flag 'amdgpu.xnack' instead of subtarget feature",
1214 DS_Error));
1215 }
1216 if (FeatureString.contains("sramecc")) {
1217 M.getContext().diagnose(DiagnosticInfoGeneric(
1218 "xnack/sramecc should be specified via module flags. "
1219 "Use module flag 'amdgpu.sramecc' instead of subtarget feature",
1220 DS_Error));
1221 }
1222
1223 // Apply xnack/sramecc settings from module flags.
1224 if (getGlobalSTI()->getFeatureBits().test(AMDGPU::FeatureXNACKOnOffModes)) {
1225 AMDGPU::TargetIDSetting Setting =
1227 if (Setting != AMDGPU::TargetIDSetting::Any)
1228 TSTargetID->setXnackSetting(Setting);
1229 }
1230
1231 if (getGlobalSTI()->getFeatureBits().test(AMDGPU::FeatureSupportsSRAMECC)) {
1232 AMDGPU::TargetIDSetting Setting =
1234 if (Setting != AMDGPU::TargetIDSetting::Any)
1235 TSTargetID->setSramEccSetting(Setting);
1236 }
1237}
1238
1239// AccumOffset computed for the MCExpr equivalent of:
1240// alignTo(std::max(1, NumVGPR), 4) / 4 - 1;
1241static const MCExpr *computeAccumOffset(const MCExpr *NumVGPR, MCContext &Ctx) {
1242 const MCExpr *ConstFour = MCConstantExpr::create(4, Ctx);
1243 const MCExpr *ConstOne = MCConstantExpr::create(1, Ctx);
1244
1245 // Can't be lower than 1 for subsequent alignTo.
1246 const MCExpr *MaximumTaken =
1247 AMDGPUMCExpr::createMax({ConstOne, NumVGPR}, Ctx);
1248
1249 // Practically, it's computing divideCeil(MaximumTaken, 4).
1250 const MCExpr *DivCeil = MCBinaryExpr::createDiv(
1251 AMDGPUMCExpr::createAlignTo(MaximumTaken, ConstFour, Ctx), ConstFour,
1252 Ctx);
1253
1254 return MCBinaryExpr::createSub(DivCeil, ConstOne, Ctx);
1255}
1256
1257static unsigned getLDSEncodingGranule(const GCNSubtarget &ST) {
1258 unsigned Granule =
1259 AMDGPU::getLDSEncodingGranule(ST.getTargetID().getGPUKind());
1260 // The legacy generic targets have no encoding granularity feature. Preserve
1261 // the default used for code generation when no GPU is specified.
1262 return Granule ? Granule : 256;
1263}
1264
1265void AMDGPUAsmPrinter::getSIProgramInfo(SIProgramInfo &ProgInfo,
1266 const MachineFunction &MF) {
1267 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
1268 MCContext &Ctx = MF.getContext();
1269
1270 auto CreateExpr = [&Ctx](int64_t Value) {
1271 return MCConstantExpr::create(Value, Ctx);
1272 };
1273
1274 auto TryGetMCExprValue = [](const MCExpr *Value, uint64_t &Res) -> bool {
1275 int64_t Val;
1276 if (Value->evaluateAsAbsolute(Val)) {
1277 Res = Val;
1278 return true;
1279 }
1280 return false;
1281 };
1282
1283 auto GetSymRefExpr =
1284 [&](MCResourceInfo::ResourceInfoKind RIK) -> const MCExpr * {
1285 MCSymbol *Sym = RI.getSymbol(CurrentFnSym->getName(), RIK, OutContext);
1286 return MCSymbolRefExpr::create(Sym, Ctx);
1287 };
1288
1290 ProgInfo.NumArchVGPR = GetSymRefExpr(RIK::RIK_NumVGPR);
1291 ProgInfo.NumAccVGPR = GetSymRefExpr(RIK::RIK_NumAGPR);
1293 ProgInfo.NumAccVGPR, ProgInfo.NumArchVGPR, Ctx);
1294
1295 ProgInfo.AccumOffset = computeAccumOffset(ProgInfo.NumArchVGPR, Ctx);
1296 ProgInfo.TgSplit =
1297 STM.hasTgSplitSupport() && AMDGPU::isTgSplitEnabled(MF.getFunction());
1298 ProgInfo.NumSGPR = GetSymRefExpr(RIK::RIK_NumSGPR);
1299 ProgInfo.ScratchSize = GetSymRefExpr(RIK::RIK_PrivateSegSize);
1300 ProgInfo.VCCUsed = GetSymRefExpr(RIK::RIK_UsesVCC);
1301 ProgInfo.FlatUsed = GetSymRefExpr(RIK::RIK_UsesFlatScratch);
1302 ProgInfo.DynamicCallStack =
1303 MCBinaryExpr::createOr(GetSymRefExpr(RIK::RIK_HasDynSizedStack),
1304 GetSymRefExpr(RIK::RIK_HasRecursion), Ctx);
1305
1306 const MCExpr *BarBlkConst = MCConstantExpr::create(4, Ctx);
1307 const MCExpr *AlignToBlk = AMDGPUMCExpr::createAlignTo(
1308 GetSymRefExpr(RIK::RIK_NumNamedBarrier), BarBlkConst, Ctx);
1309 ProgInfo.NamedBarCnt = MCBinaryExpr::createDiv(AlignToBlk, BarBlkConst, Ctx);
1310
1311 const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1312
1313 // The calculations related to SGPR/VGPR blocks are
1314 // duplicated in part in AMDGPUAsmParser::calculateGPRBlocks, and could be
1315 // unified.
1316 const MCExpr *ExtraSGPRs = AMDGPUMCExpr::createExtraSGPRs(
1317 ProgInfo.VCCUsed, ProgInfo.FlatUsed,
1318 getTargetStreamer()->getTargetID()->isXnackOnOrAny(), Ctx);
1319
1320 // Check the addressable register limit before we add ExtraSGPRs.
1322 !STM.hasSGPRInitBug()) {
1323 unsigned MaxAddressableNumSGPRs = STM.getAddressableNumSGPRs();
1324 uint64_t NumSgpr;
1325 if (TryGetMCExprValue(ProgInfo.NumSGPR, NumSgpr) &&
1326 NumSgpr > MaxAddressableNumSGPRs) {
1327 // This can happen due to a compiler bug or when using inline asm.
1328 LLVMContext &Ctx = MF.getFunction().getContext();
1329 Ctx.diagnose(DiagnosticInfoResourceLimit(
1330 MF.getFunction(), "addressable scalar registers", NumSgpr,
1331 MaxAddressableNumSGPRs, DS_Error, DK_ResourceLimit));
1332 ProgInfo.NumSGPR = CreateExpr(MaxAddressableNumSGPRs - 1);
1333 }
1334 }
1335
1336 // Account for extra SGPRs and VGPRs reserved for debugger use.
1337 ProgInfo.NumSGPR = MCBinaryExpr::createAdd(ProgInfo.NumSGPR, ExtraSGPRs, Ctx);
1338
1339 const Function &F = MF.getFunction();
1340
1341 // Ensure there are enough SGPRs and VGPRs for wave dispatch, where wave
1342 // dispatch registers as function args.
1343 unsigned WaveDispatchNumSGPR = MFI->getNumWaveDispatchSGPRs(),
1344 WaveDispatchNumVGPR = MFI->getNumWaveDispatchVGPRs();
1345
1346 if (WaveDispatchNumSGPR) {
1348 {ProgInfo.NumSGPR,
1349 MCBinaryExpr::createAdd(CreateExpr(WaveDispatchNumSGPR), ExtraSGPRs,
1350 Ctx)},
1351 Ctx);
1352 }
1353
1354 if (WaveDispatchNumVGPR) {
1356 {ProgInfo.NumArchVGPR, CreateExpr(WaveDispatchNumVGPR)}, Ctx);
1357
1359 ProgInfo.NumAccVGPR, ProgInfo.NumArchVGPR, Ctx);
1360 }
1361
1362 // Adjust number of registers used to meet default/requested minimum/maximum
1363 // number of waves per execution unit request.
1364 unsigned MaxWaves = MFI->getMaxWavesPerEU();
1365 ProgInfo.NumSGPRsForWavesPerEU =
1366 AMDGPUMCExpr::createMax({ProgInfo.NumSGPR, CreateExpr(1ul),
1367 CreateExpr(STM.getMinNumSGPRs(MaxWaves))},
1368 Ctx);
1369 ProgInfo.NumVGPRsForWavesPerEU =
1370 AMDGPUMCExpr::createMax({ProgInfo.NumVGPR, CreateExpr(1ul),
1371 CreateExpr(STM.getMinNumVGPRs(
1372 MaxWaves, MFI->getDynamicVGPRBlockSize()))},
1373 Ctx);
1374
1376 STM.hasSGPRInitBug()) {
1377 unsigned MaxAddressableNumSGPRs = STM.getAddressableNumSGPRs();
1378 uint64_t NumSgpr;
1379 if (TryGetMCExprValue(ProgInfo.NumSGPR, NumSgpr) &&
1380 NumSgpr > MaxAddressableNumSGPRs) {
1381 // This can happen due to a compiler bug or when using inline asm to use
1382 // the registers which are usually reserved for vcc etc.
1383 LLVMContext &Ctx = MF.getFunction().getContext();
1384 Ctx.diagnose(DiagnosticInfoResourceLimit(
1385 MF.getFunction(), "scalar registers", NumSgpr, MaxAddressableNumSGPRs,
1387 ProgInfo.NumSGPR = CreateExpr(MaxAddressableNumSGPRs);
1388 ProgInfo.NumSGPRsForWavesPerEU = CreateExpr(MaxAddressableNumSGPRs);
1389 }
1390 }
1391
1392 if (STM.hasSGPRInitBug()) {
1393 ProgInfo.NumSGPR =
1395 ProgInfo.NumSGPRsForWavesPerEU =
1397 }
1398
1399 if (MFI->getNumUserSGPRs() > STM.getMaxNumUserSGPRs()) {
1400 LLVMContext &Ctx = MF.getFunction().getContext();
1401 Ctx.diagnose(DiagnosticInfoResourceLimit(
1402 MF.getFunction(), "user SGPRs", MFI->getNumUserSGPRs(),
1404 }
1405
1406 if (MFI->getLDSSize() > STM.getAddressableLocalMemorySize()) {
1407 LLVMContext &Ctx = MF.getFunction().getContext();
1408 Ctx.diagnose(DiagnosticInfoResourceLimit(
1409 MF.getFunction(), "local memory", MFI->getLDSSize(),
1411 }
1412 // The MCExpr equivalent of getNumSGPRBlocks/getNumVGPRBlocks:
1413 // (alignTo(max(1u, NumGPR), GPREncodingGranule) / GPREncodingGranule) - 1
1414 auto GetNumGPRBlocks = [&CreateExpr, &Ctx](const MCExpr *NumGPR,
1415 unsigned Granule) {
1416 const MCExpr *OneConst = CreateExpr(1ul);
1417 const MCExpr *GranuleConst = CreateExpr(Granule);
1418 const MCExpr *MaxNumGPR = AMDGPUMCExpr::createMax({NumGPR, OneConst}, Ctx);
1419 const MCExpr *AlignToGPR =
1420 AMDGPUMCExpr::createAlignTo(MaxNumGPR, GranuleConst, Ctx);
1421 const MCExpr *DivGPR =
1422 MCBinaryExpr::createDiv(AlignToGPR, GranuleConst, Ctx);
1423 const MCExpr *SubGPR = MCBinaryExpr::createSub(DivGPR, OneConst, Ctx);
1424 return SubGPR;
1425 };
1426 // GFX10+ will always allocate 128 SGPRs and this field must be 0
1428 ProgInfo.SGPRBlocks = CreateExpr(0ul);
1429 } else {
1430 ProgInfo.SGPRBlocks = GetNumGPRBlocks(ProgInfo.NumSGPRsForWavesPerEU,
1432 }
1433 ProgInfo.VGPRBlocks = GetNumGPRBlocks(ProgInfo.NumVGPRsForWavesPerEU,
1435
1436 const SIModeRegisterDefaults Mode = MFI->getMode();
1437
1438 // Set the value to initialize FP_ROUND and FP_DENORM parts of the mode
1439 // register.
1440 ProgInfo.FloatMode = getFPMode(Mode);
1441
1442 ProgInfo.IEEEMode = Mode.IEEE;
1443
1444 // Make clamp modifier on NaN input returns 0.
1445 ProgInfo.DX10Clamp = Mode.DX10Clamp;
1446 ProgInfo.SGPRSpill = MFI->getNumSpilledSGPRs();
1447 ProgInfo.VGPRSpill = MFI->getNumSpilledVGPRs();
1448
1449 ProgInfo.LDSSize = MFI->getLDSSize();
1450
1451 unsigned LDSGranularityBytes = getLDSEncodingGranule(STM);
1452 ProgInfo.LDSBlocks =
1453 alignTo(ProgInfo.LDSSize, LDSGranularityBytes) / LDSGranularityBytes;
1454
1455 // The MCExpr equivalent of divideCeil.
1456 auto DivideCeil = [&Ctx](const MCExpr *Numerator, const MCExpr *Denominator) {
1457 const MCExpr *Ceil =
1458 AMDGPUMCExpr::createAlignTo(Numerator, Denominator, Ctx);
1459 return MCBinaryExpr::createDiv(Ceil, Denominator, Ctx);
1460 };
1461
1462 // Scratch is allocated in 64-dword or 256-dword blocks.
1463 unsigned ScratchAlignShift =
1464 STM.getGeneration() >= AMDGPUSubtarget::GFX11 ? 8 : 10;
1465 // We need to program the hardware with the amount of scratch memory that
1466 // is used by the entire wave. ProgInfo.ScratchSize is the amount of
1467 // scratch memory used per thread.
1468 ProgInfo.ScratchBlocks = DivideCeil(
1470 CreateExpr(STM.getWavefrontSize()), Ctx),
1471 CreateExpr(1ULL << ScratchAlignShift));
1472
1473 if (STM.hasSupportsWGP()) {
1474 ProgInfo.WgpMode = STM.isCuModeEnabled() ? 0 : 1;
1475 }
1476
1477 if (getIsaVersion(getGlobalSTI()->getCPU()).Major >= 10) {
1478 ProgInfo.MemOrdered = 1;
1479 ProgInfo.FwdProgress = !F.hasFnAttribute("amdgpu-no-fwd-progress");
1480 }
1481
1482 // 0 = X, 1 = XY, 2 = XYZ
1483 unsigned TIDIGCompCnt = 0;
1484 if (MFI->hasWorkItemIDZ())
1485 TIDIGCompCnt = 2;
1486 else if (MFI->hasWorkItemIDY())
1487 TIDIGCompCnt = 1;
1488
1489 // The private segment wave byte offset is the last of the system SGPRs. We
1490 // initially assumed it was allocated, and may have used it. It shouldn't harm
1491 // anything to disable it if we know the stack isn't used here. We may still
1492 // have emitted code reading it to initialize scratch, but if that's unused
1493 // reading garbage should be OK.
1496 MCConstantExpr::create(0, Ctx), Ctx),
1497 ProgInfo.DynamicCallStack, Ctx);
1498
1499 ProgInfo.UserSGPR = MFI->getNumUserSGPRs();
1500 // For AMDHSA, TRAP_HANDLER must be zero, as it is populated by the CP.
1501 ProgInfo.TrapHandlerEnable = STM.isAmdHsaOS() ? 0 : STM.hasTrapHandler();
1502 ProgInfo.TGIdXEnable = MFI->hasWorkGroupIDX();
1503 ProgInfo.TGIdYEnable = MFI->hasWorkGroupIDY();
1504 ProgInfo.TGIdZEnable = MFI->hasWorkGroupIDZ();
1505 ProgInfo.TGSizeEnable = MFI->hasWorkGroupInfo();
1506 ProgInfo.TIdIGCompCount = TIDIGCompCnt;
1507 ProgInfo.EXCPEnMSB = 0;
1508 // For AMDHSA, LDS_SIZE must be zero, as it is populated by the CP.
1509 ProgInfo.LdsSize = STM.isAmdHsaOS() ? 0 : ProgInfo.LDSBlocks;
1510 ProgInfo.EXCPEnable = 0;
1511
1512 if (STM.hasGFX90AInsts()) {
1513 ProgInfo.ComputePGMRSrc3 =
1514 setBits(ProgInfo.ComputePGMRSrc3, ProgInfo.AccumOffset,
1515 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET,
1516 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET_SHIFT, Ctx);
1517 ProgInfo.ComputePGMRSrc3 =
1518 setBits(ProgInfo.ComputePGMRSrc3, CreateExpr(ProgInfo.TgSplit),
1519 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT,
1520 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT_SHIFT, Ctx);
1521 }
1522
1523 if (STM.hasGFX1250Insts())
1524 ProgInfo.ComputePGMRSrc3 =
1525 setBits(ProgInfo.ComputePGMRSrc3, ProgInfo.NamedBarCnt,
1526 amdhsa::COMPUTE_PGM_RSRC3_GFX125_NAMED_BAR_CNT,
1527 amdhsa::COMPUTE_PGM_RSRC3_GFX125_NAMED_BAR_CNT_SHIFT, Ctx);
1528
1529 ProgInfo.Occupancy = createOccupancy(
1530 STM.computeOccupancy(F, ProgInfo.LDSSize).second,
1532 MFI->getDynamicVGPRBlockSize(), STM, Ctx);
1533
1534 const auto [MinWEU, MaxWEU] =
1535 AMDGPU::getIntegerPairAttribute(F, "amdgpu-waves-per-eu", {0, 0}, true);
1536 uint64_t Occupancy;
1537 if (TryGetMCExprValue(ProgInfo.Occupancy, Occupancy) && Occupancy < MinWEU) {
1538 DiagnosticInfoOptimizationFailure Diag(
1539 F, F.getSubprogram(),
1540 "failed to meet occupancy target given by 'amdgpu-waves-per-eu' in "
1541 "'" +
1542 F.getName() + "': desired occupancy was " + Twine(MinWEU) +
1543 ", final occupancy is " + Twine(Occupancy));
1544 F.getContext().diagnose(Diag);
1545 }
1546}
1547
1548static unsigned getRsrcReg(CallingConv::ID CallConv) {
1549 switch (CallConv) {
1550 default:
1551 [[fallthrough]];
1566 }
1567}
1568
1569void AMDGPUAsmPrinter::EmitProgramInfoSI(
1570 const MachineFunction &MF, const SIProgramInfo &CurrentProgramInfo) {
1571 const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1572 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
1573 unsigned RsrcReg = getRsrcReg(MF.getFunction().getCallingConv());
1574 MCContext &Ctx = MF.getContext();
1575
1576 // (((Value) & Mask) << Shift)
1577 auto SetBits = [&Ctx](const MCExpr *Value, uint32_t Mask, uint32_t Shift) {
1578 const MCExpr *msk = MCConstantExpr::create(Mask, Ctx);
1579 const MCExpr *shft = MCConstantExpr::create(Shift, Ctx);
1581 shft, Ctx);
1582 };
1583
1584 auto EmitResolvedOrExpr = [this](const MCExpr *Value, unsigned Size) {
1585 int64_t Val;
1586 if (Value->evaluateAsAbsolute(Val))
1587 OutStreamer->emitIntValue(static_cast<uint64_t>(Val), Size);
1588 else
1589 OutStreamer->emitValue(Value, Size);
1590 };
1591
1592 if (AMDGPU::isCompute(MF.getFunction().getCallingConv())) {
1594
1595 EmitResolvedOrExpr(CurrentProgramInfo.getComputePGMRSrc1(STM, Ctx),
1596 /*Size=*/4);
1597
1599 EmitResolvedOrExpr(CurrentProgramInfo.getComputePGMRSrc2(STM, Ctx),
1600 /*Size=*/4);
1601
1603
1604 // Sets bits according to S_0286E8_WAVESIZE_* mask and shift values for the
1605 // appropriate generation.
1606 if (STM.getGeneration() >= AMDGPUSubtarget::GFX12) {
1607 EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1608 /*Mask=*/0x3FFFF, /*Shift=*/12),
1609 /*Size=*/4);
1610 } else if (STM.getGeneration() == AMDGPUSubtarget::GFX11) {
1611 EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1612 /*Mask=*/0x7FFF, /*Shift=*/12),
1613 /*Size=*/4);
1614 } else {
1615 EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1616 /*Mask=*/0x1FFF, /*Shift=*/12),
1617 /*Size=*/4);
1618 }
1619
1620 // TODO: Should probably note flat usage somewhere. SC emits a "FlatPtr32 =
1621 // 0" comment but I don't see a corresponding field in the register spec.
1622 } else {
1623 OutStreamer->emitInt32(RsrcReg);
1624
1625 const MCExpr *GPRBlocks = MCBinaryExpr::createOr(
1626 SetBits(CurrentProgramInfo.VGPRBlocks, /*Mask=*/0x3F, /*Shift=*/0),
1627 SetBits(CurrentProgramInfo.SGPRBlocks, /*Mask=*/0x0F, /*Shift=*/6),
1628 MF.getContext());
1629 EmitResolvedOrExpr(GPRBlocks, /*Size=*/4);
1631
1632 // Sets bits according to S_0286E8_WAVESIZE_* mask and shift values for the
1633 // appropriate generation.
1634 if (STM.getGeneration() >= AMDGPUSubtarget::GFX12) {
1635 EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1636 /*Mask=*/0x3FFFF, /*Shift=*/12),
1637 /*Size=*/4);
1638 } else if (STM.getGeneration() == AMDGPUSubtarget::GFX11) {
1639 EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1640 /*Mask=*/0x7FFF, /*Shift=*/12),
1641 /*Size=*/4);
1642 } else {
1643 EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1644 /*Mask=*/0x1FFF, /*Shift=*/12),
1645 /*Size=*/4);
1646 }
1647 }
1648
1649 if (MF.getFunction().getCallingConv() == CallingConv::AMDGPU_PS) {
1651 unsigned ExtraLDSSize = STM.getGeneration() >= AMDGPUSubtarget::GFX11
1652 ? divideCeil(CurrentProgramInfo.LDSBlocks, 2)
1653 : CurrentProgramInfo.LDSBlocks;
1654 OutStreamer->emitInt32(S_00B02C_EXTRA_LDS_SIZE(ExtraLDSSize));
1656 OutStreamer->emitInt32(MFI->getPSInputEnable());
1658 OutStreamer->emitInt32(MFI->getPSInputAddr());
1659 }
1660
1661 OutStreamer->emitInt32(R_SPILLED_SGPRS);
1662 OutStreamer->emitInt32(MFI->getNumSpilledSGPRs());
1663 OutStreamer->emitInt32(R_SPILLED_VGPRS);
1664 OutStreamer->emitInt32(MFI->getNumSpilledVGPRs());
1665}
1666
1667// Helper function to add common PAL Metadata 3.0+
1669 const SIProgramInfo &CurrentProgramInfo,
1670 CallingConv::ID CC, const GCNSubtarget &ST,
1671 unsigned DynamicVGPRBlockSize) {
1672 if (ST.hasFeature(AMDGPU::FeatureDX10ClampAndIEEEMode))
1673 MD->setHwStage(CC, ".ieee_mode", (bool)CurrentProgramInfo.IEEEMode);
1674
1675 MD->setHwStage(CC, ".wgp_mode", (bool)CurrentProgramInfo.WgpMode);
1676 MD->setHwStage(CC, ".mem_ordered", (bool)CurrentProgramInfo.MemOrdered);
1677 MD->setHwStage(CC, ".forward_progress", (bool)CurrentProgramInfo.FwdProgress);
1678
1679 if (AMDGPU::isCompute(CC)) {
1680 MD->setHwStage(CC, ".trap_present",
1681 (bool)CurrentProgramInfo.TrapHandlerEnable);
1682 MD->setHwStage(CC, ".excp_en", CurrentProgramInfo.EXCPEnable);
1683
1684 if (DynamicVGPRBlockSize != 0)
1685 MD->setComputeRegisters(".dynamic_vgpr_en", true);
1686 }
1687
1689 CC, ".lds_size",
1690 (unsigned)(CurrentProgramInfo.LdsSize * getLDSEncodingGranule(ST)));
1691}
1692
1693// This is the equivalent of EmitProgramInfoSI above, but for when the OS type
1694// is AMDPAL. It stores each compute/SPI register setting and other PAL
1695// metadata items into the PALMD::Metadata, combining with any provided by the
1696// frontend as LLVM metadata. Once all functions are written, the PAL metadata
1697// is then written as a single block in the .note section.
1698void AMDGPUAsmPrinter::EmitPALMetadata(
1699 const MachineFunction &MF, const SIProgramInfo &CurrentProgramInfo) {
1700 const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1701 auto CC = MF.getFunction().getCallingConv();
1702 auto *MD = getTargetStreamer()->getPALMetadata();
1703 auto &Ctx = MF.getContext();
1704
1705 MD->setEntryPoint(CC, MF.getFunction().getName());
1706 MD->setNumUsedVgprs(CC, CurrentProgramInfo.NumVGPRsForWavesPerEU, Ctx);
1707
1708 // For targets that support dynamic VGPRs, set the number of saved dynamic
1709 // VGPRs (if any) in the PAL metadata.
1710 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
1711 if (MFI->isDynamicVGPREnabled() &&
1713 MD->setHwStage(CC, ".dynamic_vgpr_saved_count",
1715
1716 // Only set AGPRs for supported devices
1717 if (STM.hasMAIInsts()) {
1718 MD->setNumUsedAgprs(CC, CurrentProgramInfo.NumAccVGPR);
1719 }
1720
1721 MD->setNumUsedSgprs(CC, CurrentProgramInfo.NumSGPRsForWavesPerEU, Ctx);
1722 if (MD->getPALMajorVersion() < 3) {
1723 MD->setRsrc1(CC, CurrentProgramInfo.getPGMRSrc1(CC, STM, Ctx), Ctx);
1724 if (AMDGPU::isCompute(CC)) {
1725 MD->setRsrc2(CC, CurrentProgramInfo.getComputePGMRSrc2(STM, Ctx), Ctx);
1726 } else {
1727 const MCExpr *HasScratchBlocks =
1728 MCBinaryExpr::createGT(CurrentProgramInfo.ScratchBlocks,
1729 MCConstantExpr::create(0, Ctx), Ctx);
1730 auto [Shift, Mask] = getShiftMask(C_00B84C_SCRATCH_EN);
1731 MD->setRsrc2(CC, maskShiftSet(HasScratchBlocks, Mask, Shift, Ctx), Ctx);
1732 }
1733 } else {
1734 MD->setHwStage(CC, ".debug_mode", (bool)CurrentProgramInfo.DebugMode);
1735 MD->setHwStage(CC, ".scratch_en", msgpack::Type::Boolean,
1736 CurrentProgramInfo.ScratchEnable);
1737 EmitPALMetadataCommon(MD, CurrentProgramInfo, CC, STM,
1739 }
1740
1741 // ScratchSize is in bytes, 16 aligned.
1742 MD->setScratchSize(
1743 CC,
1744 AMDGPUMCExpr::createAlignTo(CurrentProgramInfo.ScratchSize,
1745 MCConstantExpr::create(16, Ctx), Ctx),
1746 Ctx);
1747
1748 if (MF.getFunction().getCallingConv() == CallingConv::AMDGPU_PS) {
1749 unsigned ExtraLDSSize = STM.getGeneration() >= AMDGPUSubtarget::GFX11
1750 ? divideCeil(CurrentProgramInfo.LDSBlocks, 2)
1751 : CurrentProgramInfo.LDSBlocks;
1752 if (MD->getPALMajorVersion() < 3) {
1753 MD->setRsrc2(
1754 CC,
1756 Ctx);
1757 MD->setSpiPsInputEna(MFI->getPSInputEnable());
1758 MD->setSpiPsInputAddr(MFI->getPSInputAddr());
1759 } else {
1760 // Graphics registers
1761 const unsigned ExtraLdsDwGranularity =
1762 STM.getGeneration() >= AMDGPUSubtarget::GFX11 ? 256 : 128;
1763 MD->setGraphicsRegisters(
1764 ".ps_extra_lds_size",
1765 (unsigned)(ExtraLDSSize * ExtraLdsDwGranularity * sizeof(uint32_t)));
1766
1767 // Set PsInputEna and PsInputAddr .spi_ps_input_ena and .spi_ps_input_addr
1768 static StringLiteral const PsInputFields[] = {
1769 ".persp_sample_ena", ".persp_center_ena",
1770 ".persp_centroid_ena", ".persp_pull_model_ena",
1771 ".linear_sample_ena", ".linear_center_ena",
1772 ".linear_centroid_ena", ".line_stipple_tex_ena",
1773 ".pos_x_float_ena", ".pos_y_float_ena",
1774 ".pos_z_float_ena", ".pos_w_float_ena",
1775 ".front_face_ena", ".ancillary_ena",
1776 ".sample_coverage_ena", ".pos_fixed_pt_ena"};
1777 unsigned PSInputEna = MFI->getPSInputEnable();
1778 unsigned PSInputAddr = MFI->getPSInputAddr();
1779 for (auto [Idx, Field] : enumerate(PsInputFields)) {
1780 MD->setGraphicsRegisters(".spi_ps_input_ena", Field,
1781 (bool)((PSInputEna >> Idx) & 1));
1782 MD->setGraphicsRegisters(".spi_ps_input_addr", Field,
1783 (bool)((PSInputAddr >> Idx) & 1));
1784 }
1785 }
1786 }
1787
1788 // For version 3 and above the wave front size is already set in the metadata
1789 if (MD->getPALMajorVersion() < 3 && STM.isWave32())
1790 MD->setWave32(MF.getFunction().getCallingConv());
1791}
1792
1793void AMDGPUAsmPrinter::emitPALFunctionMetadata(const MachineFunction &MF) {
1794 auto *MD = getTargetStreamer()->getPALMetadata();
1795 const MachineFrameInfo &MFI = MF.getFrameInfo();
1796 StringRef FnName = MF.getFunction().getName();
1797 MD->setFunctionScratchSize(FnName, MFI.getStackSize());
1798 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
1799 MCContext &Ctx = MF.getContext();
1800
1801 if (MD->getPALMajorVersion() < 3) {
1802 // Set compute registers
1803 MD->setRsrc1(
1805 CurrentProgramInfo.getPGMRSrc1(CallingConv::AMDGPU_CS, ST, Ctx), Ctx);
1806 MD->setRsrc2(CallingConv::AMDGPU_CS,
1807 CurrentProgramInfo.getComputePGMRSrc2(ST, Ctx), Ctx);
1808 } else {
1810 MD, CurrentProgramInfo, CallingConv::AMDGPU_CS, ST,
1811 MF.getInfo<SIMachineFunctionInfo>()->getDynamicVGPRBlockSize());
1812 }
1813
1814 // Set optional info
1815 MD->setFunctionLdsSize(FnName, CurrentProgramInfo.LDSSize);
1816 MD->setFunctionNumUsedVgprs(FnName, CurrentProgramInfo.NumVGPRsForWavesPerEU);
1817 MD->setFunctionNumUsedSgprs(FnName, CurrentProgramInfo.NumSGPRsForWavesPerEU);
1818}
1819
1820// This is supposed to be log2(Size)
1822 switch (Size) {
1823 case 4:
1824 return AMD_ELEMENT_4_BYTES;
1825 case 8:
1826 return AMD_ELEMENT_8_BYTES;
1827 case 16:
1828 return AMD_ELEMENT_16_BYTES;
1829 default:
1830 llvm_unreachable("invalid private_element_size");
1831 }
1832}
1833
1834void AMDGPUAsmPrinter::getAmdKernelCode(AMDGPUMCKernelCodeT &Out,
1835 const SIProgramInfo &CurrentProgramInfo,
1836 const MachineFunction &MF) const {
1837 const Function &F = MF.getFunction();
1838 assert(F.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
1839 F.getCallingConv() == CallingConv::SPIR_KERNEL);
1840
1841 const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1842 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
1843 MCContext &Ctx = MF.getContext();
1844
1845 Out.initDefault(STM, Ctx, /*InitMCExpr=*/false);
1846
1847 Out.compute_pgm_resource1_registers =
1848 CurrentProgramInfo.getComputePGMRSrc1(STM, Ctx);
1849 Out.compute_pgm_resource2_registers =
1850 CurrentProgramInfo.getComputePGMRSrc2(STM, Ctx);
1851 Out.code_properties |= AMD_CODE_PROPERTY_IS_PTR64;
1852
1853 Out.is_dynamic_callstack = CurrentProgramInfo.DynamicCallStack;
1854
1856 getElementByteSizeValue(STM.getMaxPrivateElementSize(true)));
1857
1858 const GCNUserSGPRUsageInfo &UserSGPRInfo = MFI->getUserSGPRInfo();
1859 if (UserSGPRInfo.hasPrivateSegmentBuffer()) {
1861 }
1862
1863 if (UserSGPRInfo.hasDispatchPtr())
1865
1866 if (UserSGPRInfo.hasQueuePtr())
1868
1869 if (UserSGPRInfo.hasKernargSegmentPtr())
1871
1872 if (UserSGPRInfo.hasDispatchID())
1874
1875 if (UserSGPRInfo.hasFlatScratchInit())
1877
1878 if (UserSGPRInfo.hasPrivateSegmentSize())
1880
1881 if (STM.isXNACKEnabled())
1882 Out.code_properties |= AMD_CODE_PROPERTY_IS_XNACK_SUPPORTED;
1883
1884 Align MaxKernArgAlign;
1885 Out.kernarg_segment_byte_size = STM.getKernArgSegmentSize(F, MaxKernArgAlign);
1886 Out.wavefront_sgpr_count = CurrentProgramInfo.NumSGPR;
1887 Out.workitem_vgpr_count = CurrentProgramInfo.NumVGPR;
1888 Out.workitem_private_segment_byte_size = CurrentProgramInfo.ScratchSize;
1889 Out.workgroup_group_segment_byte_size = CurrentProgramInfo.LDSSize;
1890
1891 // kernarg_segment_alignment is specified as log of the alignment.
1892 // The minimum alignment is 16.
1893 // FIXME: The metadata treats the minimum as 4?
1894 Out.kernarg_segment_alignment = Log2(std::max(Align(16), MaxKernArgAlign));
1895}
1896
1898 const char *ExtraCode, raw_ostream &O) {
1899 // First try the generic code, which knows about modifiers like 'c' and 'n'.
1900 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O))
1901 return false;
1902
1903 if (ExtraCode && ExtraCode[0]) {
1904 if (ExtraCode[1] != 0)
1905 return true; // Unknown modifier.
1906
1907 switch (ExtraCode[0]) {
1908 case 'r':
1909 break;
1910 default:
1911 return true;
1912 }
1913 }
1914
1915 // TODO: Should be able to support other operand types like globals.
1916 const MachineOperand &MO = MI->getOperand(OpNo);
1917 if (MO.isReg()) {
1919 *MF->getSubtarget().getRegisterInfo());
1920 return false;
1921 }
1922 if (MO.isImm()) {
1923 int64_t Val = MO.getImm();
1925 O << Val;
1926 } else if (isUInt<16>(Val)) {
1927 O << format("0x%" PRIx16, static_cast<uint16_t>(Val));
1928 } else if (isUInt<32>(Val)) {
1929 O << format("0x%" PRIx32, static_cast<uint32_t>(Val));
1930 } else {
1931 O << format("0x%" PRIx64, static_cast<uint64_t>(Val));
1932 }
1933 return false;
1934 }
1935 return true;
1936}
1937
1945
1946void AMDGPUAsmPrinter::emitResourceUsageRemarks(
1947 const MachineFunction &MF, const SIProgramInfo &CurrentProgramInfo,
1948 bool isModuleEntryFunction, bool hasMAIInsts) {
1949 if (!ORE)
1950 return;
1951
1952 const char *Name = "kernel-resource-usage";
1953 const char *Indent = " ";
1954
1955 // If the remark is not specifically enabled, do not output to yaml
1957 if (!Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(Name))
1958 return;
1959
1960 // Currently non-kernel functions have no resources to emit.
1962 return;
1963
1964 auto EmitResourceUsageRemark = [&](StringRef RemarkName,
1965 StringRef RemarkLabel, auto Argument) {
1966 // Add an indent for every line besides the line with the kernel name. This
1967 // makes it easier to tell which resource usage go with which kernel since
1968 // the kernel name will always be displayed first.
1969 std::string LabelStr = RemarkLabel.str() + ": ";
1970 if (RemarkName != "FunctionName")
1971 LabelStr = Indent + LabelStr;
1972
1973 ORE->emit([&]() {
1974 return MachineOptimizationRemarkAnalysis(Name, RemarkName,
1976 &MF.front())
1977 << LabelStr << ore::NV(RemarkName, Argument);
1978 });
1979 };
1980
1981 // FIXME: Formatting here is pretty nasty because clang does not accept
1982 // newlines from diagnostics. This forces us to emit multiple diagnostic
1983 // remarks to simulate newlines. If and when clang does accept newlines, this
1984 // formatting should be aggregated into one remark with newlines to avoid
1985 // printing multiple diagnostic location and diag opts.
1986 EmitResourceUsageRemark("FunctionName", "Function Name",
1987 MF.getFunction().getName());
1988 EmitResourceUsageRemark("NumSGPR", "TotalSGPRs",
1989 getMCExprStr(CurrentProgramInfo.NumSGPR));
1990 EmitResourceUsageRemark("NumVGPR", "VGPRs",
1991 getMCExprStr(CurrentProgramInfo.NumArchVGPR));
1992 if (hasMAIInsts) {
1993 EmitResourceUsageRemark("NumAGPR", "AGPRs",
1994 getMCExprStr(CurrentProgramInfo.NumAccVGPR));
1995 }
1996 EmitResourceUsageRemark("ScratchSize", "ScratchSize [bytes/lane]",
1997 getMCExprStr(CurrentProgramInfo.ScratchSize));
1998 int64_t DynStack;
1999 bool DynStackEvaluatable =
2000 CurrentProgramInfo.DynamicCallStack->evaluateAsAbsolute(DynStack);
2001 StringRef DynamicStackStr =
2002 DynStackEvaluatable && DynStack ? "True" : "False";
2003 EmitResourceUsageRemark("DynamicStack", "Dynamic Stack", DynamicStackStr);
2004 EmitResourceUsageRemark("Occupancy", "Occupancy [waves/SIMD]",
2005 getMCExprStr(CurrentProgramInfo.Occupancy));
2006 EmitResourceUsageRemark("SGPRSpill", "SGPRs Spill",
2007 CurrentProgramInfo.SGPRSpill);
2008 EmitResourceUsageRemark("VGPRSpill", "VGPRs Spill",
2009 CurrentProgramInfo.VGPRSpill);
2010 if (isModuleEntryFunction)
2011 EmitResourceUsageRemark("BytesLDS", "LDS Size [bytes/block]",
2012 CurrentProgramInfo.LDSSize);
2013}
2014
2024
2040
2049
2050char AMDGPUAsmPrinter::ID = 0;
2051
2052INITIALIZE_PASS(AMDGPUAsmPrinter, "amdgpu-asm-printer",
2053 "AMDGPU Assembly Printer", false, false)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static void EmitPALMetadataCommon(AMDGPUPALMetadata *MD, const SIProgramInfo &CurrentProgramInfo, CallingConv::ID CC, const GCNSubtarget &ST, unsigned DynamicVGPRBlockSize)
const AMDGPUMCExpr * createOccupancy(unsigned InitOcc, const MCExpr *NumSGPRs, const MCExpr *NumVGPRs, unsigned DynamicVGPRBlockSize, const GCNSubtarget &STM, MCContext &Ctx)
Mimics GCNSubtarget::computeOccupancy for MCExpr.
static unsigned getRsrcReg(CallingConv::ID CallConv)
LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAMDGPUAsmPrinter()
static amd_element_byte_size_t getElementByteSizeValue(unsigned Size)
static const MCExpr * setBits(const MCExpr *Dst, const MCExpr *Value, uint32_t Mask, uint32_t Shift, MCContext &Ctx)
Set bits in a kernel descriptor MCExpr field: return ((Dst & ~Mask) | (Value << Shift))
static uint32_t getFPMode(SIModeRegisterDefaults Mode)
static std::string computeTypeId(const FunctionType *FTy, const DataLayout &DL)
static const MCExpr * computeAccumOffset(const MCExpr *NumVGPR, MCContext &Ctx)
static void appendTypeEncoding(std::string &Enc, Type *Ty, const DataLayout &DL, bool IsReturnType)
static AsmPrinter * createAMDGPUAsmPrinterPass(TargetMachine &tm, std::unique_ptr< MCStreamer > &&Streamer)
AMDGPU Assembly printer class.
unsigned uint64_t
AMDGPU HSA Metadata Streamer.
AMDHSA kernel descriptor MCExpr struct for use in MC layer.
MC infrastructure to propagate the function level resource usage info.
Analyzes how many registers and other resources are used by functions.
The AMDGPU TargetMachine interface definition for hw codegen targets.
AMDHSA kernel descriptor definitions.
MC layer struct for AMDGPUMCKernelCodeT, provides MCExpr functionality where required.
amd_element_byte_size_t
The values used to define the number of bytes to use for the swizzle element size.
@ AMD_ELEMENT_8_BYTES
@ AMD_ELEMENT_16_BYTES
@ AMD_ELEMENT_4_BYTES
#define AMD_HSA_BITS_SET(dst, mask, val)
@ AMD_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID
@ AMD_CODE_PROPERTY_PRIVATE_ELEMENT_SIZE
@ AMD_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR
@ AMD_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR
@ AMD_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE
@ AMD_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER
@ AMD_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR
@ AMD_CODE_PROPERTY_IS_XNACK_SUPPORTED
@ AMD_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT
@ AMD_CODE_PROPERTY_IS_PTR64
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static const Function * getParent(const Value *V)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_ABI
Definition Compiler.h:215
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
AMD GCN specific subclass of TargetSubtarget.
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
===- MachineOptimizationRemarkEmitter.h - Opt Diagnostics -*- C++ -*-—===//
modulo schedule test
OptimizedStructLayoutField Field
ModuleAnalysisManager MAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
R600 Assembly printer class.
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
#define R_00B028_SPI_SHADER_PGM_RSRC1_PS
Definition SIDefines.h:1378
#define R_0286E8_SPI_TMPRING_SIZE
Definition SIDefines.h:1520
#define FP_ROUND_MODE_DP(x)
Definition SIDefines.h:1502
#define C_00B84C_SCRATCH_EN
Definition SIDefines.h:1414
#define FP_ROUND_ROUND_TO_NEAREST
Definition SIDefines.h:1494
#define R_0286D0_SPI_PS_INPUT_ADDR
Definition SIDefines.h:1453
#define R_00B860_COMPUTE_TMPRING_SIZE
Definition SIDefines.h:1515
#define R_00B428_SPI_SHADER_PGM_RSRC1_HS
Definition SIDefines.h:1401
#define R_00B328_SPI_SHADER_PGM_RSRC1_ES
Definition SIDefines.h:1400
#define R_00B528_SPI_SHADER_PGM_RSRC1_LS
Definition SIDefines.h:1409
#define R_0286CC_SPI_PS_INPUT_ENA
Definition SIDefines.h:1452
#define R_00B128_SPI_SHADER_PGM_RSRC1_VS
Definition SIDefines.h:1387
#define FP_DENORM_MODE_DP(x)
Definition SIDefines.h:1513
#define R_00B848_COMPUTE_PGM_RSRC1
Definition SIDefines.h:1455
#define R_SPILLED_SGPRS
Definition SIDefines.h:1534
#define FP_ROUND_MODE_SP(x)
Definition SIDefines.h:1501
#define FP_DENORM_MODE_SP(x)
Definition SIDefines.h:1512
#define R_00B228_SPI_SHADER_PGM_RSRC1_GS
Definition SIDefines.h:1392
#define R_SPILLED_VGPRS
Definition SIDefines.h:1535
#define S_00B02C_EXTRA_LDS_SIZE(x)
Definition SIDefines.h:1386
#define R_00B84C_COMPUTE_PGM_RSRC2
Definition SIDefines.h:1411
#define R_00B02C_SPI_SHADER_PGM_RSRC2_PS
Definition SIDefines.h:1385
std::unique_ptr< MCStreamer > && Streamer
static const int BlockSize
Definition TarWriter.cpp:33
static cl::opt< unsigned > CacheLineSize("cache-line-size", cl::init(0), cl::Hidden, cl::desc("Use this to override the target cache line size when " "specified by the user."))
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
void emitFunctionEntryLabel() override
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
const MCSubtargetInfo * getGlobalSTI() const
void emitImplicitDef(const MachineInstr *MI) const override
Targets can override this to customize the output of IMPLICIT_DEF instructions in verbose mode.
std::vector< std::string > DisasmLines
std::function< const AMDGPUResourceUsageAnalysisImpl::SIFunctionResourceInfo *(MachineFunction &)> GetResourceUsage
void emitStartOfAsmFile(Module &M) override
This virtual method can be overridden by targets that want to emit something at the start of their fi...
void endFunction(const MachineFunction *MF)
StringRef getPassName() const override
getPassName - Return a nice clean name for a pass.
std::vector< std::string > HexLines
void emitGlobalVariable(const GlobalVariable *GV) override
Emit the specified global variable to the .s file.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &O) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
bool doFinalization(Module &M) override
doFinalization - Virtual method overriden by subclasses to do any necessary clean up after all passes...
void emitEndOfAsmFile(Module &M) override
This virtual method can be overridden by targets that want to emit something at the end of their file...
AMDGPUAsmPrinter(TargetMachine &TM, std::unique_ptr< MCStreamer > Streamer)
bool doInitialization(Module &M) override
doInitialization - Virtual method overridden by subclasses to do any necessary initialization before ...
void emitFunctionBodyStart() override
Targets can override this to emit stuff before the first basic block in the function.
void emitBasicBlockStart(const MachineBasicBlock &MBB) override
Targets can override this to emit stuff at the start of a basic block.
AMDGPUTargetStreamer * getTargetStreamer() const
static void printRegOperand(MCRegister Reg, raw_ostream &O, const MCRegisterInfo &MRI)
AMDGPU target specific MCExpr operations.
static const AMDGPUMCExpr * createInstPrefSize(const MCExpr *CodeSizeBytes, MCContext &Ctx)
Create an expression for instruction prefetch size computation: min(divideCeil(CodeSizeBytes,...
static const AMDGPUMCExpr * createMax(ArrayRef< const MCExpr * > Args, MCContext &Ctx)
static const AMDGPUMCExpr * createTotalNumVGPR(const MCExpr *NumAGPR, const MCExpr *NumVGPR, MCContext &Ctx)
static const AMDGPUMCExpr * create(VariantKind Kind, ArrayRef< const MCExpr * > Args, MCContext &Ctx)
static const AMDGPUMCExpr * createExtraSGPRs(const MCExpr *VCCUsed, const MCExpr *FlatScrUsed, bool XNACKUsed, MCContext &Ctx)
Allow delayed MCExpr resolve of ExtraSGPRs (in case VCCUsed or FlatScrUsed are unresolvable but neede...
static const AMDGPUMCExpr * createAlignTo(const MCExpr *Value, const MCExpr *Align, MCContext &Ctx)
void setHwStage(unsigned CC, StringRef field, unsigned Val)
void updateHwStageMaximum(unsigned CC, StringRef field, unsigned Val)
void setComputeRegisters(StringRef field, unsigned Val)
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 getAddressableLocalMemorySize() const
Return the maximum number of bytes of LDS that can be allocated to a single workgroup.
unsigned getKernArgSegmentSize(const Function &F, Align &MaxAlign) const
unsigned getWavefrontSize() const
virtual void EmitAmdhsaKernelDescriptor(const MCSubtargetInfo &STI, StringRef KernelName, const AMDGPU::MCKernelDescriptor &KernelDescriptor, const MCExpr *NextVGPR, const MCExpr *NextSGPR, const MCExpr *ReserveVCC, const MCExpr *ReserveFlatScr)
virtual void emitAMDGPUInfo(const AMDGPU::InfoSectionData &Data)
AMDGPUPALMetadata * getPALMetadata()
void initializeTargetID(const MCSubtargetInfo &STI, bool ApplyFeatureString=false)
virtual void EmitDirectiveAMDHSACodeObjectVersion(unsigned COV)
virtual void EmitMCResourceInfo(const MCSymbol *NumVGPR, const MCSymbol *NumAGPR, const MCSymbol *NumExplicitSGPR, const MCSymbol *NumNamedBarrier, const MCSymbol *PrivateSegmentSize, const MCSymbol *UsesVCC, const MCSymbol *UsesFlatScratch, const MCSymbol *HasDynamicallySizedStack, const MCSymbol *HasRecursion, const MCSymbol *HasIndirectCall)
virtual bool EmitCodeEnd(const MCSubtargetInfo &STI)
virtual void EmitAMDGPUSymbolType(StringRef SymbolName, unsigned Type)
const std::optional< AMDGPU::TargetID > & getTargetID() const
virtual void EmitAMDKernelCodeT(AMDGPU::AMDGPUMCKernelCodeT &Header)
virtual void EmitMCResourceMaximums(const MCSymbol *MaxVGPR, const MCSymbol *MaxAGPR, const MCSymbol *MaxSGPR, const MCSymbol *MaxNamedBarrier)
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
This class represents an incoming formal argument to a Function.
Definition Argument.h:32
Collects and handles AsmPrinter objects required to build debug or EH information.
This class is intended to be used as a driving class for all asm writers.
Definition AsmPrinter.h:91
const TargetLoweringObjectFile & getObjFileLowering() const
Return information about object file lowering.
MCSymbol * getSymbol(const GlobalValue *GV) const
virtual void emitGlobalVariable(const GlobalVariable *GV)
Emit the specified global variable to the .s file.
TargetMachine & TM
Target machine description.
Definition AsmPrinter.h:94
MachineFunction * MF
The current machine function.
Definition AsmPrinter.h:109
virtual void SetupMachineFunction(MachineFunction &MF)
This should be called when a new MachineFunction is being processed from runOnMachineFunction.
void emitFunctionBody()
This method emits the body and trailer for a function.
virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const
Return true if the basic block has exactly one predecessor and the control transfer mechanism between...
bool doInitialization(Module &M) override
Set up the AsmPrinter when we are working on a new module.
virtual void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const
This emits linkage information about GVSym based on GV, if this is supported by the target.
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
unsigned getFunctionNumber() const
Return a unique ID for the current function.
MachineOptimizationRemarkEmitter * ORE
Optimization remark emitter.
Definition AsmPrinter.h:121
AsmPrinter(TargetMachine &TM, std::unique_ptr< MCStreamer > Streamer, char &ID=AsmPrinter::ID)
MCSymbol * CurrentFnSym
The symbol for the current function.
Definition AsmPrinter.h:128
MachineModuleInfo * MMI
This is a pointer to the current MachineModuleInfo.
Definition AsmPrinter.h:112
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition AsmPrinter.h:101
bool doFinalization(Module &M) override
Shut down the asmprinter.
virtual void emitBasicBlockStart(const MachineBasicBlock &MBB)
Targets can override this to emit stuff at the start of a basic block.
void emitVisibility(MCSymbol *Sym, unsigned Visibility, bool IsDefinition=true) const
This emits visibility information about symbol, if this is supported by the target.
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
Definition AsmPrinter.h:453
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition AsmPrinter.h:106
const MCAsmInfo & MAI
Target Asm Printer information.
Definition AsmPrinter.h:97
std::function< MachineModuleInfo *()> GetMMI
Definition AsmPrinter.h:176
bool isVerbose() const
Return true if assembly output should contain comments.
Definition AsmPrinter.h:310
MCSymbol * getFunctionEnd() const
Definition AsmPrinter.h:320
void getNameWithPrefix(SmallVectorImpl< char > &Name, const GlobalValue *GV) const
virtual void emitFunctionEntryLabel()
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
void addAsmPrinterHandler(std::unique_ptr< AsmPrinterHandler > Handler)
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
bool empty() const
Definition DenseMap.h:206
DISubprogram * getSubprogram() const
Get the attached subprogram.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition Function.h:273
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:356
unsigned getMinNumSGPRs(unsigned WavesPerEU) const
unsigned getTotalNumVGPRs() const
unsigned getMinNumVGPRs(unsigned WavesPerEU, unsigned DynamicVGPRBlockSize) const
bool hasInstPrefSize() const
bool isCuModeEnabled() const
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 ...
const AMDGPU::TargetID & getTargetID() const
bool isWave32() const
void getInstPrefSizeArgs(uint32_t &Mask, uint32_t &Shift, uint32_t &Width, uint32_t &CacheLineSize) const
unsigned getMaxNumUserSGPRs() const
unsigned getMaxWavesPerEU() const
Generation getGeneration() const
unsigned getAddressableNumSGPRs() const
unsigned getMaxWaveScratchSize() const
static AMDGPU::TargetIDSetting getTargetIDSettingFromModuleFlag(const Module &M, StringRef FlagName)
Get xnack/sramecc setting from module flag or cl::opt (for testing).
bool hasPrivateSegmentBuffer() const
VisibilityTypes getVisibility() const
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition Globals.cpp:408
unsigned getAddressSpace() const
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
Definition Globals.cpp:205
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
bool hasInitializer() const
Definitions have initializers, declarations don't.
MaybeAlign getAlign() const
Returns the alignment of the given variable.
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
Definition Globals.cpp:640
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
MCCodeEmitter * getEmitterPtr() const
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:342
static const MCBinaryExpr * createAnd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:347
static const MCBinaryExpr * createOr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:407
static const MCBinaryExpr * createLOr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:377
static const MCBinaryExpr * createMul(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:397
static const MCBinaryExpr * createGT(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:362
static const MCBinaryExpr * createDiv(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:352
static const MCBinaryExpr * createShl(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:412
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:427
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Context object for machine code objects.
Definition MCContext.h:83
LLVM_ABI void reportError(SMLoc L, const Twine &Msg)
LLVM_ABI MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
LLVM_ABI bool evaluateAsRelocatable(MCValue &Res, const MCAssembler *Asm) const
Try to evaluate the expression to a relocatable value, i.e.
Definition MCExpr.cpp:450
MCSection * getTextSection() const
MCContext & getContext() const
This represents a section on linux, lots of unix variants and some bare metal systems.
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Definition MCSection.h:580
bool hasInstructions() const
Definition MCSection.h:676
Generic base class for all target subtargets.
StringRef getFeatureString() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
bool isDefined() const
isDefined - Check if this symbol is defined (i.e., it has an address).
Definition MCSymbol.h:233
StringRef getName() const
getName - Get the symbol name.
Definition MCSymbol.h:188
bool isVariable() const
isVariable - Check if this is a variable symbol.
Definition MCSymbol.h:267
void redefineIfPossible()
Prepare this symbol to be redefined.
Definition MCSymbol.h:212
const MCExpr * getVariableValue() const
Get the expression of the variable symbol.
Definition MCSymbol.h:270
MCStreamer & getStreamer()
Definition MCStreamer.h:103
static const MCUnaryExpr * createNot(const MCExpr *Expr, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:272
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
MCContext & getContext() const
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...
const MachineBasicBlock & front() const
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
Register getReg() const
getReg - Returns the register number.
Diagnostic information for optimization analysis remarks.
LLVM_ABI void emit(DiagnosticInfoOptimizationBase &OptDiag)
Emit an optimization remark.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
LLVM_ABI unsigned getNumOperands() const
iterator_range< op_iterator > operands()
Definition Metadata.h:1863
AnalysisType * getAnalysisIfAvailable() const
getAnalysisIfAvailable<AnalysisType>() - Subclasses use this function to get analysis information tha...
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
Wrapper class representing virtual and physical registers.
Definition Register.h:20
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
GCNUserSGPRUsageInfo & getUserSGPRInfo()
SIModeRegisterDefaults getMode() const
unsigned getScratchReservedForDynamicVGPRs() const
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
void push_back(const T &Elt)
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
Definition StringRef.h:446
std::pair< typename Base::iterator, bool > insert(StringRef key)
Definition StringSet.h:39
Primary interface to the complete machine description for the target machine.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM Value Representation.
Definition Value.h:75
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
A raw_ostream that writes to an SmallVector or SmallString.
StringRef str() const
Return a StringRef for the vector contents.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ LOCAL_ADDRESS
Address space for local memory.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
bool isSGPROccupancyLimited(const MCSubtargetInfo &STI)
unsigned getVGPREncodingGranule(const MCSubtargetInfo &STI, std::optional< bool > EnableWavefrontSize32)
static constexpr unsigned MaxDynamicVGPRBlocks
Maximum number of VGPR blocks that can be allocated in dynamic VGPR mode.
unsigned getSGPREncodingGranule(const MCSubtargetInfo &STI)
unsigned getNumExtraSGPRs(const MCSubtargetInfo &STI, bool VCCUsed, bool FlatScrUsed, bool XNACKUsed)
unsigned getVGPRAllocGranule(const MCSubtargetInfo &STI, unsigned DynamicVGPRBlockSize, std::optional< bool > EnableWavefrontSize32)
LLVM_ABI unsigned getLDSEncodingGranule(GPUKind AK)
void printAMDGPUMCExpr(const MCExpr *Expr, raw_ostream &OS, const MCAsmInfo *MAI)
LLVM_READNONE constexpr bool isModuleEntryFunctionCC(CallingConv::ID CC)
LLVM_ABI IsaVersion getIsaVersion(StringRef GPU)
LLVM_ABI unsigned getTotalNumVGPRs(GPUKind AK, bool IsWave32)
LLVM_ABI unsigned getTotalNumSGPRs(GPUKind AK)
const MCExpr * maskShiftSet(const MCExpr *Val, uint32_t Mask, uint32_t Shift, MCContext &Ctx)
Provided with the MCExpr * Val, uint32 Mask and Shift, will return the masked and left shifted,...
unsigned getAMDHSACodeObjectVersion(const Module &M)
bool isTgSplitEnabled(const Function &F)
GPUKind
GPU kinds supported by the AMDGPU target.
bool isGFX90A(const MCSubtargetInfo &STI)
LLVM_READNONE constexpr bool isKernel(CallingConv::ID CC)
LLVM_ABI unsigned getSGPRAllocGranule(GPUKind AK)
LLVM_READNONE constexpr bool isEntryFunctionCC(CallingConv::ID CC)
LLVM_READNONE constexpr bool isCompute(CallingConv::ID CC)
bool hasMAIInsts(const MCSubtargetInfo &STI)
LLVM_ABI Triple::SubArchType getSubArch(GPUKind AK)
LLVM_READNONE bool isInlinableIntLiteral(int64_t Literal)
Is this literal inlinable, and not one of the values intended for floating point values.
LLVM_ABI GPUKind parseArchAMDGCN(StringRef CPU)
const MCExpr * foldAMDGPUMCExpr(const MCExpr *Expr, MCContext &Ctx)
bool isGFX10Plus(const MCSubtargetInfo &STI)
constexpr std::pair< unsigned, unsigned > getShiftMask(unsigned Value)
Deduce the least significant bit aligned shift and mask values for a binary Complement Value (as they...
unsigned hasKernargPreload(const MCSubtargetInfo &STI)
std::pair< unsigned, unsigned > getIntegerPairAttribute(const Function &F, StringRef Name, std::pair< unsigned, unsigned > Default, bool OnlyFirstRequired)
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ AMDGPU_CS
Used for Mesa/AMDPAL compute shaders.
@ AMDGPU_VS
Used for Mesa vertex shaders, or AMDPAL last shader stage before rasterization (vertex shader if tess...
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ AMDGPU_HS
Used for Mesa/AMDPAL hull shaders (= tessellation control shaders).
@ AMDGPU_GS
Used for Mesa/AMDPAL geometry shaders.
@ AMDGPU_CS_Chain
Used on AMDGPUs to give the middle-end more control over argument placement.
@ AMDGPU_PS
Used for Mesa/AMDPAL pixel shaders.
@ SPIR_KERNEL
Used for SPIR kernel functions.
@ AMDGPU_ES
Used for AMDPAL shader stage before geometry shader if geometry is in use.
@ AMDGPU_LS
Used for AMDPAL vertex shader if tessellation is in use.
@ SHT_PROGBITS
Definition ELF.h:1157
@ STT_AMDGPU_HSA_KERNEL
Definition ELF.h:1441
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
Definition Metadata.h:679
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< FuncNode * > Func
Definition RDFGraph.h:393
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
OuterAnalysisManagerProxy< ModuleAnalysisManager, MachineFunction > ModuleAnalysisManagerMachineFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2570
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
static StringRef getCPU(StringRef CPU)
Processes a CPU name.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
Target & getTheR600Target()
The target for R600 GPUs.
@ DK_ResourceLimit
AsmPrinter * createR600AsmPrinterPass(TargetMachine &TM, std::unique_ptr< MCStreamer > &&Streamer)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
LLVM_ABI void setupModuleAsmPrinter(Module &M, ModuleAnalysisManager &MAM, AsmPrinter &AsmPrinter)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition Format.h:102
@ Success
The lock was released successfully.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:389
Target & getTheGCNTarget()
The target for GCN GPUs.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1933
LLVM_ABI void setupMachineFunctionAsmPrinter(MachineFunctionAnalysisManager &MFAM, MachineFunction &MF, AsmPrinter &AsmPrinter)
Target & getTheGCNLegacyTarget()
The target for GCN GPUs, registered under the legacy "amdgcn" architecture name for use with -march.
unsigned Log2(Align A)
Returns the log2 of the alignment.
Definition Alignment.h:197
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.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:177
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
#define N
AMDGPUResourceUsageAnalysisImpl::SIFunctionResourceInfo FunctionResourceInfo
void validate(const MCSubtargetInfo *STI, MCContext &Ctx)
static const MCExpr * bits_get(const MCExpr *Src, uint32_t Shift, uint32_t Mask, MCContext &Ctx)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Track resource usage for kernels / entry functions.
const MCExpr * NumSGPR
const MCExpr * NumArchVGPR
const MCExpr * VGPRBlocks
const MCExpr * ScratchBlocks
const MCExpr * ComputePGMRSrc3
const MCExpr * getComputePGMRSrc1(const GCNSubtarget &ST, MCContext &Ctx) const
Compute the value of the ComputePGMRsrc1 register.
const MCExpr * VCCUsed
const MCExpr * FlatUsed
const MCExpr * NamedBarCnt
const MCExpr * ScratchEnable
const MCExpr * AccumOffset
const MCExpr * NumAccVGPR
const MCExpr * DynamicCallStack
const MCExpr * SGPRBlocks
const MCExpr * NumVGPRsForWavesPerEU
const MCExpr * NumVGPR
const MCExpr * Occupancy
const MCExpr * ScratchSize
const MCExpr * NumSGPRsForWavesPerEU
const MCExpr * getComputePGMRSrc2(const GCNSubtarget &ST, MCContext &Ctx) const
Compute the value of the ComputePGMRsrc2 register.
static void RegisterAsmPrinter(Target &T, Target::AsmPrinterCtorTy Fn)
RegisterAsmPrinter - Register an AsmPrinter implementation for the given target.