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");
121 // AMDGPU describes a pointer's address space with its own attribute rather
122 // than DW_AT_address_class.
123 TypeAddressSpaceAttribute = dwarf::DW_AT_LLVM_address_space;
126 if (auto *ResourceUsageW =
128 return &ResourceUsageW->getResourceInfo();
129 return nullptr;
130 };
131}
132
134 return "AMDGPU Assembly Printer";
135}
136
138 return &TM.getMCSubtargetInfo();
139}
140
142 if (!OutStreamer)
143 return nullptr;
144 return static_cast<AMDGPUTargetStreamer *>(OutStreamer->getTargetStreamer());
145}
146
150
151void AMDGPUAsmPrinter::initTargetStreamer(Module &M) {
153
154 // TODO: Which one is called first, emitStartOfAsmFile or
155 // emitFunctionBodyStart?
156 if (getTargetStreamer() && !getTargetStreamer()->getTargetID())
157 initializeTargetID(M);
158
159 const Triple &TT = M.getTargetTriple();
160 if (TT.getOS() != Triple::AMDHSA && TT.getOS() != Triple::AMDPAL)
161 return;
162
164
165 if (TT.getOS() == Triple::AMDHSA) {
167 CodeObjectVersion);
168 HSAMetadataStream->begin(M, *getTargetStreamer()->getTargetID());
169 }
170
171 if (TT.getOS() == Triple::AMDPAL)
173}
174
176 // Init target streamer if it has not yet happened
178 initTargetStreamer(M);
179
180 const Triple &TT = M.getTargetTriple();
181 if (TT.getOS() != Triple::AMDHSA)
183
184 // Emit HSA Metadata (NT_AMD_AMDGPU_HSA_METADATA).
185 // Emit HSA Metadata (NT_AMD_HSA_METADATA).
186 if (TT.getOS() == Triple::AMDHSA) {
187 HSAMetadataStream->end();
188 bool Success = HSAMetadataStream->emitTo(*getTargetStreamer());
189 (void)Success;
190 assert(Success && "Malformed HSA Metadata");
191 }
192}
193
195 const SIMachineFunctionInfo &MFI = *MF->getInfo<SIMachineFunctionInfo>();
196 const GCNSubtarget &STM = MF->getSubtarget<GCNSubtarget>();
197 const Function &F = MF->getFunction();
198
199 // TODO: We're checking this late, would be nice to check it earlier.
200 if (STM.requiresCodeObjectV6() && CodeObjectVersion < AMDGPU::AMDHSA_COV6) {
202 STM.getCPU() + " is only available on code object version 6 or better");
203 }
204
205 // TODO: Which one is called first, emitStartOfAsmFile or
206 // emitFunctionBodyStart?
207 if (!getTargetStreamer()->getTargetID())
208 initializeTargetID(*F.getParent());
209
210 if (!MFI.isEntryFunction())
211 return;
212
213 if (STM.isMesaKernel(F) &&
214 (F.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
215 F.getCallingConv() == CallingConv::SPIR_KERNEL)) {
216 AMDGPUMCKernelCodeT KernelCode;
217 getAmdKernelCode(KernelCode, CurrentProgramInfo, *MF);
218 KernelCode.validate(&STM, MF->getContext());
220 }
221
222 if (STM.isAmdHsaOS())
223 HSAMetadataStream->emitKernel(*MF, CurrentProgramInfo);
224}
225
226/// Set bits in a kernel descriptor MCExpr field:
227/// return ((Dst & ~Mask) | (Value << Shift))
228static const MCExpr *setBits(const MCExpr *Dst, const MCExpr *Value,
229 uint32_t Mask, uint32_t Shift, MCContext &Ctx) {
230 const auto *Shft = MCConstantExpr::create(Shift, Ctx);
231 const auto *Msk = MCConstantExpr::create(Mask, Ctx);
232 Dst = MCBinaryExpr::createAnd(Dst, MCUnaryExpr::createNot(Msk, Ctx), Ctx);
234 Ctx);
235 return Dst;
236}
237
239 const SIMachineFunctionInfo &MFI = *MF->getInfo<SIMachineFunctionInfo>();
240 if (!MFI.isEntryFunction())
241 return;
242
243 assert(TM.getTargetTriple().getOS() == Triple::AMDHSA);
244
245 const GCNSubtarget &STM = MF->getSubtarget<GCNSubtarget>();
246 MCContext &Ctx = MF->getContext();
247
249 getAmdhsaKernelDescriptor(*MF, CurrentProgramInfo);
250
251 // Compute inst_pref_size using MCExpr label subtraction for exact code
252 // size. At this point .Lfunc_end has been emitted (by the base AsmPrinter)
253 // right after the function code, so (Lfunc_end - func_sym) gives the
254 // exact function code size in bytes.
255 if (STM.hasInstPrefSize()) {
256 const MCExpr *CodeSizeExpr = MCBinaryExpr::createSub(
259
260 uint32_t Mask, Shift, Width, CacheLineSize;
261 STM.getInstPrefSizeArgs(Mask, Shift, Width, CacheLineSize);
262 const MCExpr *InstPrefSize =
263 AMDGPUMCExpr::createInstPrefSize(CodeSizeExpr, Ctx);
265 setBits(KD.compute_pgm_rsrc3, InstPrefSize, Mask, Shift, Ctx);
266 }
267
269 auto &Context = Streamer.getContext();
270 auto &ObjectFileInfo = *Context.getObjectFileInfo();
271 auto &ReadOnlySection = *ObjectFileInfo.getReadOnlySection();
272
273 Streamer.pushSection();
274 Streamer.switchSection(&ReadOnlySection);
275
276 // CP microcode requires the kernel descriptor to be allocated on 64 byte
277 // alignment.
278 Streamer.emitValueToAlignment(Align(64), 0, 1, 0);
279 ReadOnlySection.ensureMinAlignment(Align(64));
280
281 SmallString<128> KernelName;
282 getNameWithPrefix(KernelName, &MF->getFunction());
284 STM, KernelName, KD, CurrentProgramInfo.NumVGPRsForWavesPerEU,
286 CurrentProgramInfo.NumSGPRsForWavesPerEU,
288 CurrentProgramInfo.VCCUsed, CurrentProgramInfo.FlatUsed,
289 getTargetStreamer()->getTargetID()->isXnackOnOrAny(), Context),
290 Context),
291 CurrentProgramInfo.VCCUsed, CurrentProgramInfo.FlatUsed);
292
293 Streamer.popSection();
294}
295
297 Register RegNo = MI->getOperand(0).getReg();
298
300 raw_svector_ostream OS(Str);
301 OS << "implicit-def: "
302 << printReg(RegNo, MF->getSubtarget().getRegisterInfo());
303
304 if (MI->getAsmPrinterFlags() & AMDGPU::SGPR_SPILL)
305 OS << " : SGPR spill to VGPR lane";
306
307 OutStreamer->AddComment(OS.str());
308 OutStreamer->addBlankLine();
309}
310
312 if (TM.getTargetTriple().getOS() == Triple::AMDHSA) {
314 return;
315 }
316
317 const SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>();
318 const GCNSubtarget &STM = MF->getSubtarget<GCNSubtarget>();
319 if (MFI->isEntryFunction() && STM.isAmdHsaOrMesa(MF->getFunction())) {
320 SmallString<128> SymbolName;
321 getNameWithPrefix(SymbolName, &MF->getFunction()),
324 }
325 if (DumpCodeInstEmitter) {
326 // Disassemble function name label to text.
327 DisasmLines.push_back(MF->getName().str() + ":");
328 DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLines.back().size());
329 HexLines.emplace_back("");
330 }
331
333}
334
336 if (DumpCodeInstEmitter && !isBlockOnlyReachableByFallthrough(&MBB)) {
337 // Write a line for the basic block label if it is not only fallthrough.
338 DisasmLines.push_back((Twine("BB") + Twine(getFunctionNumber()) + "_" +
339 Twine(MBB.getNumber()) + ":")
340 .str());
341 DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLines.back().size());
342 HexLines.emplace_back("");
343 }
345}
346
349 if (GV->hasInitializer() && !isa<UndefValue>(GV->getInitializer())) {
350 OutContext.reportError({},
351 Twine(GV->getName()) +
352 ": unsupported initializer for address space");
353 return;
354 }
355
356 const Triple::OSType OS = TM.getTargetTriple().getOS();
357 if (OS == Triple::AMDHSA || OS == Triple::AMDPAL) {
359 return;
360 // With object linking, LDS definitions should have been externalized
361 // by earlier passes (e.g. LDS lowering, named barrier lowering).
362 // Only declarations reach here, emitted as SHN_AMDGPU_LDS symbols
363 // so the linker can assign their offsets.
364 assert(GV->isDeclaration() &&
365 "LDS definitions should have been externalized when object "
366 "linking is enabled");
367 }
368
369 MCSymbol *GVSym = getSymbol(GV);
370
371 GVSym->redefineIfPossible();
372 if (GVSym->isDefined() || GVSym->isVariable())
373 report_fatal_error("symbol '" + Twine(GVSym->getName()) +
374 "' is already defined");
375
376 const DataLayout &DL = GV->getDataLayout();
377 uint64_t Size = GV->getGlobalSize(DL);
378 Align Alignment = GV->getAlign().value_or(Align(4));
379
380 emitVisibility(GVSym, GV->getVisibility(), !GV->isDeclaration());
381 emitLinkage(GV, GVSym);
382 auto *TS = getTargetStreamer();
383 TS->emitAMDGPULDS(GVSym, Size, Alignment);
384 return;
385 }
386
388}
389
391 const Triple &TT = M.getTargetTriple();
392 if (TT.getSubArch() == Triple::NoSubArch) {
393 Triple::SubArchType SubArch =
395 if (SubArch != Triple::NoSubArch) {
396 Triple Fixed(TT);
397 Fixed.setArch(Triple::amdgpu, SubArch);
398 M.getContext().diagnose(DiagnosticInfoGeneric(
399 "codegen with no subarch in the target triple is deprecated and will "
400 "become an error; use the target triple '" +
401 Fixed.str() + "' instead",
402 DS_Warning));
403 } else {
404 M.getContext().diagnose(DiagnosticInfoGeneric(
405 "codegen with no subarch in the target triple is deprecated and will "
406 "become an error",
407 DS_Warning));
408 }
409 }
410
411 CodeObjectVersion = AMDGPU::getAMDHSACodeObjectVersion(M);
412
413 if (TT.getOS() == Triple::AMDHSA) {
414 const AMDGPUOptions &CLOpts =
415 static_cast<const AMDGPUTargetMachine &>(TM).getCLOpts();
416 switch (CodeObjectVersion) {
418 HSAMetadataStream =
419 std::make_unique<HSAMD::MetadataStreamerMsgPackV4>(CLOpts);
420 break;
422 HSAMetadataStream =
423 std::make_unique<HSAMD::MetadataStreamerMsgPackV5>(CLOpts);
424 break;
426 HSAMetadataStream =
427 std::make_unique<HSAMD::MetadataStreamerMsgPackV6>(CLOpts);
428 break;
429 default:
430 reportFatalUsageError("unsupported code object version");
431 }
432
433 addAsmPrinterHandler(std::make_unique<AMDGPUAsmPrinterHandler>(this));
434 }
435
437}
438
439/// Mimics GCNSubtarget::computeOccupancy for MCExpr.
440///
441/// Remove dependency on GCNSubtarget and depend only only the necessary values
442/// for said occupancy computation. Should match computeOccupancy implementation
443/// without passing \p STM on.
444const AMDGPUMCExpr *createOccupancy(unsigned InitOcc, const MCExpr *NumSGPRs,
445 const MCExpr *NumVGPRs,
446 unsigned DynamicVGPRBlockSize,
447 const GCNSubtarget &STM, MCContext &Ctx) {
448 unsigned MaxWaves = STM.getMaxWavesPerEU();
449 unsigned Granule = IsaInfo::getVGPRAllocGranule(STM, DynamicVGPRBlockSize);
450 unsigned TargetTotalNumVGPRs = STM.getTotalNumVGPRs();
451
452 // Bake the per-function SGPR budget into the operands so the late-evaluated
453 // MCExpr stays arithmetic. The trap reservation in particular is implicit on
454 // amdhsa and lives on STM, not on the assembler's MCSubtargetInfo.
456 unsigned SGPRTotal = AMDGPU::getTotalNumSGPRs(Kind);
457 unsigned SGPRGranule = AMDGPU::getSGPRAllocGranule(Kind);
458 unsigned SGPRTrapReserve = STM.hasTrapHandler() ? IsaInfo::TRAP_NUM_SGPRS : 0;
459
460 auto CreateExpr = [&Ctx](unsigned Value) {
461 return MCConstantExpr::create(Value, Ctx);
462 };
463
464 // Zero SGPR count when SGPRs don't limit occupancy, so the MCExpr skips the
465 // SGPR term without having to test the generation itself.
466 const MCExpr *SGPRArg =
467 IsaInfo::isSGPROccupancyLimited(STM) ? NumSGPRs : CreateExpr(0);
468
470 {CreateExpr(MaxWaves), CreateExpr(Granule),
471 CreateExpr(TargetTotalNumVGPRs),
472 CreateExpr(InitOcc), CreateExpr(SGPRTotal),
473 CreateExpr(SGPRGranule),
474 CreateExpr(SGPRTrapReserve), SGPRArg, NumVGPRs},
475 Ctx);
476}
477
478void AMDGPUAsmPrinter::validateMCResourceInfo(Function &F) {
479 if (F.isDeclaration() || !AMDGPU::isModuleEntryFunctionCC(F.getCallingConv()))
480 return;
481
483 const GCNSubtarget &STM = TM.getSubtarget<GCNSubtarget>(F);
484 MCSymbol *FnSym = TM.getSymbol(&F);
485
486 auto TryGetMCExprValue = [](const MCExpr *Value, uint64_t &Res) -> bool {
487 int64_t Val;
488 if (Value->evaluateAsAbsolute(Val)) {
489 Res = Val;
490 return true;
491 }
492 return false;
493 };
494
495 const uint64_t MaxScratchPerWorkitem =
497 MCSymbol *ScratchSizeSymbol =
498 RI.getSymbol(FnSym->getName(), RIK::RIK_PrivateSegSize, OutContext);
499 uint64_t ScratchSize;
500 if (ScratchSizeSymbol->isVariable() &&
501 TryGetMCExprValue(ScratchSizeSymbol->getVariableValue(), ScratchSize) &&
502 ScratchSize > MaxScratchPerWorkitem) {
503 DiagnosticInfoStackSize DiagStackSize(F, ScratchSize, MaxScratchPerWorkitem,
504 DS_Error);
505 F.getContext().diagnose(DiagStackSize);
506 }
507
508 // Validate addressable scalar registers (i.e., prior to added implicit
509 // SGPRs).
510 MCSymbol *NumSGPRSymbol =
511 RI.getSymbol(FnSym->getName(), RIK::RIK_NumSGPR, OutContext);
513 !STM.hasSGPRInitBug()) {
514 unsigned MaxAddressableNumSGPRs = STM.getAddressableNumSGPRs();
515 uint64_t NumSgpr;
516 if (NumSGPRSymbol->isVariable() &&
517 TryGetMCExprValue(NumSGPRSymbol->getVariableValue(), NumSgpr) &&
518 NumSgpr > MaxAddressableNumSGPRs) {
519 F.getContext().diagnose(DiagnosticInfoResourceLimit(
520 F, "addressable scalar registers", NumSgpr, MaxAddressableNumSGPRs,
522 return;
523 }
524 }
525
526 MCSymbol *VCCUsedSymbol =
527 RI.getSymbol(FnSym->getName(), RIK::RIK_UsesVCC, OutContext);
528 MCSymbol *FlatUsedSymbol =
529 RI.getSymbol(FnSym->getName(), RIK::RIK_UsesFlatScratch, OutContext);
530 uint64_t VCCUsed, FlatUsed, NumSgpr;
531
532 if (NumSGPRSymbol->isVariable() && VCCUsedSymbol->isVariable() &&
533 FlatUsedSymbol->isVariable() &&
534 TryGetMCExprValue(NumSGPRSymbol->getVariableValue(), NumSgpr) &&
535 TryGetMCExprValue(VCCUsedSymbol->getVariableValue(), VCCUsed) &&
536 TryGetMCExprValue(FlatUsedSymbol->getVariableValue(), FlatUsed)) {
537
538 // Recomputes NumSgprs + implicit SGPRs but all symbols should now be
539 // resolvable.
540 NumSgpr += IsaInfo::getNumExtraSGPRs(
541 STM, VCCUsed, FlatUsed,
542 getTargetStreamer()->getTargetID()->isXnackOnOrAny());
544 STM.hasSGPRInitBug()) {
545 unsigned MaxAddressableNumSGPRs = STM.getAddressableNumSGPRs();
546 if (NumSgpr > MaxAddressableNumSGPRs) {
547 F.getContext().diagnose(DiagnosticInfoResourceLimit(
548 F, "scalar registers", NumSgpr, MaxAddressableNumSGPRs, DS_Error,
550 return;
551 }
552 }
553
554 MCSymbol *NumVgprSymbol =
555 RI.getSymbol(FnSym->getName(), RIK::RIK_NumVGPR, OutContext);
556 MCSymbol *NumAgprSymbol =
557 RI.getSymbol(FnSym->getName(), RIK::RIK_NumAGPR, OutContext);
558 uint64_t NumVgpr, NumAgpr;
559
560 MachineModuleInfo &MMI = *GetMMI();
561 MachineFunction *MF = MMI.getMachineFunction(F);
562 if (MF && NumVgprSymbol->isVariable() && NumAgprSymbol->isVariable() &&
563 TryGetMCExprValue(NumVgprSymbol->getVariableValue(), NumVgpr) &&
564 TryGetMCExprValue(NumAgprSymbol->getVariableValue(), NumAgpr)) {
565 const SIMachineFunctionInfo &MFI = *MF->getInfo<SIMachineFunctionInfo>();
566 unsigned MaxWaves = MFI.getMaxWavesPerEU();
567 uint64_t TotalNumVgpr =
568 getTotalNumVGPRs(STM.hasGFX90AInsts(), NumAgpr, NumVgpr);
569 uint64_t NumVGPRsForWavesPerEU =
570 std::max({TotalNumVgpr, (uint64_t)1,
572 MaxWaves, MFI.getDynamicVGPRBlockSize())});
573 uint64_t NumSGPRsForWavesPerEU = std::max(
574 {NumSgpr, (uint64_t)1, (uint64_t)STM.getMinNumSGPRs(MaxWaves)});
575 const MCExpr *OccupancyExpr = createOccupancy(
576 STM.getOccupancyWithWorkGroupSizes(*MF).second,
577 MCConstantExpr::create(NumSGPRsForWavesPerEU, OutContext),
578 MCConstantExpr::create(NumVGPRsForWavesPerEU, OutContext),
580 uint64_t Occupancy;
581
582 const auto [MinWEU, MaxWEU] = AMDGPU::getIntegerPairAttribute(
583 F, "amdgpu-waves-per-eu", {0, 0}, true);
584
585 if (TryGetMCExprValue(OccupancyExpr, Occupancy) && Occupancy < MinWEU) {
586 DiagnosticInfoOptimizationFailure Diag(
587 F, F.getSubprogram(),
588 "failed to meet occupancy target given by 'amdgpu-waves-per-eu' in "
589 "'" +
590 F.getName() + "': desired occupancy was " + Twine(MinWEU) +
591 ", final occupancy is " + Twine(Occupancy));
592 F.getContext().diagnose(Diag);
593 return;
594 }
595 }
596 }
597}
598
599static void appendTypeEncoding(std::string &Enc, Type *Ty, const DataLayout &DL,
600 bool IsReturnType) {
601 if (Ty->isVoidTy()) {
602 Enc += 'v';
603 return;
604 }
605 unsigned Bits = DL.getTypeSizeInBits(Ty);
606 // Zero-sized non-void types (e.g. `{}` or `[0 x i8]`) consume no ABI
607 // registers. For returns, emit the same no-result marker as void so the
608 // parameter encoding still has an explicit return-type prefix.
609 if (Bits == 0) {
610 if (IsReturnType)
611 Enc += 'v';
612 return;
613 }
614 if (Bits <= 32)
615 Enc += 'i';
616 else if (Bits <= 64)
617 Enc += 'l';
618 else
619 Enc.append(divideCeil(Bits, 32), 'i');
620}
621
622static std::string computeTypeId(const FunctionType *FTy,
623 const DataLayout &DL) {
624 std::string Enc;
625 appendTypeEncoding(Enc, FTy->getReturnType(), DL, /*IsReturnType=*/true);
626 for (Type *ParamTy : FTy->params())
627 appendTypeEncoding(Enc, ParamTy, DL, /*IsReturnType=*/false);
628 return Enc;
629}
630
631void AMDGPUAsmPrinter::collectCallEdge(const MachineInstr &MI) {
633 return;
634 const SIInstrInfo *TII = MF->getSubtarget<GCNSubtarget>().getInstrInfo();
635 const MachineOperand *Callee =
636 TII->getNamedOperand(MI, AMDGPU::OpName::callee);
637 if (!Callee || !Callee->isGlobal())
638 return;
639 DirectCallEdges.insert(
640 {getSymbol(&MF->getFunction()), getSymbol(Callee->getGlobal())});
641}
642
643void AMDGPUAsmPrinter::emitAMDGPUInfo(Module &M) {
645 return;
646
647 const NamedMDNode *LDSMD = M.getNamedMetadata("amdgpu.lds.uses");
648 bool HasLDSUses = LDSMD && LDSMD->getNumOperands() > 0;
649
650 const NamedMDNode *BarMD = M.getNamedMetadata("amdgpu.named_barrier.uses");
651 bool HasNamedBarriers = BarMD && BarMD->getNumOperands() > 0;
652
653 // Collect address-taken functions (with type IDs) and indirect call sites.
654 DenseMap<const Function *, std::string> AddrTakenTypeIds;
655 using IndirectCallInfo = std::pair<const Function *, std::string>;
657
658 for (const Function &F : M) {
659 bool IsKernel = AMDGPU::isKernel(F.getCallingConv());
660
661 if (!IsKernel && F.hasAddressTaken(/*PutOffender=*/nullptr,
662 /*IgnoreCallbackUses=*/false,
663 /*IgnoreAssumeLikeCalls=*/true,
664 /*IgnoreLLVMUsed=*/true)) {
665 AddrTakenTypeIds[&F] =
666 computeTypeId(F.getFunctionType(), M.getDataLayout());
667 }
668
669 if (F.isDeclaration())
670 continue;
671
672 StringSet<> SeenTypeIds;
673 for (const BasicBlock &BB : F) {
674 for (const Instruction &I : BB) {
675 const auto *CB = dyn_cast<CallBase>(&I);
676 if (!CB || !CB->isIndirectCall())
677 continue;
678 std::string TId =
679 computeTypeId(CB->getFunctionType(), M.getDataLayout());
680 if (SeenTypeIds.insert(TId).second)
681 IndirectCalls.push_back({&F, std::move(TId)});
682 }
683 }
684 }
685
686 if (FunctionInfos.empty() && DirectCallEdges.empty() && !HasLDSUses &&
687 !HasNamedBarriers && AddrTakenTypeIds.empty() && IndirectCalls.empty())
688 return;
689
690 AMDGPU::InfoSectionData Data;
691 Data.Funcs = std::move(FunctionInfos);
692
693 for (auto &[F, TypeId] : AddrTakenTypeIds) {
694 MCSymbol *Sym = getSymbol(F);
695 Data.TypeIds.push_back({Sym, TypeId});
696 }
697
698 for (auto &[CallerSym, CalleeSym] : DirectCallEdges)
699 Data.Calls.push_back({CallerSym, CalleeSym});
700 DirectCallEdges.clear();
701
702 if (HasLDSUses) {
703 for (const MDNode *N : LDSMD->operands()) {
704 auto *Func = mdconst::extract<Function>(N->getOperand(0));
705 auto *LdsVar = mdconst::extract<GlobalVariable>(N->getOperand(1));
706 Data.Uses.push_back({getSymbol(Func), getSymbol(LdsVar)});
707 }
708 }
709
710 if (HasNamedBarriers) {
711 for (const MDNode *N : BarMD->operands()) {
712 auto *BarVar = mdconst::extract<GlobalVariable>(N->getOperand(0));
713 MCSymbol *BarSym = getSymbol(BarVar);
714 for (unsigned I = 1, E = N->getNumOperands(); I < E; ++I) {
715 auto *Func = mdconst::extract<Function>(N->getOperand(I));
716 Data.Uses.push_back({getSymbol(Func), BarSym});
717 }
718 }
719 }
720
721 for (auto &[Caller, Enc] : IndirectCalls) {
722 MCSymbol *CallerSym = getSymbol(Caller);
723 Data.IndirectCalls.push_back({CallerSym, Enc});
724 }
725
727}
728
730 const Triple &TT = M.getTargetTriple();
731
732 // Pad with s_code_end to help tools and guard against instruction prefetch
733 // causing stale data in caches. Arguably this should be done by the linker,
734 // which is why this isn't done for Mesa.
735 // Don't do it if there is no code.
736 const MCSubtargetInfo &STI = *getGlobalSTI();
737 if ((AMDGPU::isGFX10Plus(STI) || AMDGPU::isGFX90A(STI)) &&
738 (TT.getOS() == Triple::AMDHSA || TT.getOS() == Triple::AMDPAL)) {
740 if (TextSect->hasInstructions()) {
741 OutStreamer->switchSection(TextSect);
743 }
744 }
745
746 // Emit the unified .amdgpu.info section (per-function resources, call graph,
747 // LDS/named-barrier use edges, indirect calls, and address-taken type IDs).
748 emitAMDGPUInfo(M);
749
750 // Assign expressions which can only be resolved when all other functions are
751 // known.
752 RI.finalize(OutContext);
753
754 // Switch section and emit all GPR maximums within the processed module.
755 OutStreamer->pushSection();
756 MCSectionELF *MaxGPRSection =
757 OutContext.getELFSection(".AMDGPU.gpr_maximums", ELF::SHT_PROGBITS, 0);
758 OutStreamer->switchSection(MaxGPRSection);
760 RI.getMaxVGPRSymbol(OutContext), RI.getMaxAGPRSymbol(OutContext),
761 RI.getMaxSGPRSymbol(OutContext), RI.getMaxNamedBarrierSymbol(OutContext));
762 OutStreamer->popSection();
763
764 // In the object-linking pipeline per-function resource MCExprs reference
765 // external callee symbols that cannot be evaluated here, so cross-TU limit
766 // checks would silently no-op for every non-leaf function. Defer resource
767 // sanity checking to the linker, which re-validates against the aggregated
768 // call graph in the combined .amdgpu.info metadata.
770 for (Function &F : M.functions())
771 validateMCResourceInfo(F);
772 }
773
774 RI.reset();
775
777}
778
779SmallString<128> AMDGPUAsmPrinter::getMCExprStr(const MCExpr *Value) {
781 raw_svector_ostream OSS(Str);
783 auto &Context = Streamer.getContext();
784 const MCExpr *New = foldAMDGPUMCExpr(Value, Context);
785 printAMDGPUMCExpr(New, OSS, &MAI);
786 return Str;
787}
788
789// Print comments that apply to both callable functions and entry points.
790void AMDGPUAsmPrinter::emitCommonFunctionComments(
791 const MCExpr *NumVGPR, const MCExpr *NumAGPR, const MCExpr *TotalNumVGPR,
792 const MCExpr *NumSGPR, const MCExpr *ScratchSize, uint64_t CodeSize,
793 const AMDGPUMachineFunctionInfo *MFI) {
794 OutStreamer->emitRawComment(" codeLenInByte = " + Twine(CodeSize), false);
795 OutStreamer->emitRawComment(" TotalNumSgprs: " + getMCExprStr(NumSGPR),
796 false);
797 OutStreamer->emitRawComment(" NumVgprs: " + getMCExprStr(NumVGPR), false);
798 if (NumAGPR && TotalNumVGPR) {
799 OutStreamer->emitRawComment(" NumAgprs: " + getMCExprStr(NumAGPR), false);
800 OutStreamer->emitRawComment(" TotalNumVgprs: " + getMCExprStr(TotalNumVGPR),
801 false);
802 }
803 OutStreamer->emitRawComment(" ScratchSize: " + getMCExprStr(ScratchSize),
804 false);
805 OutStreamer->emitRawComment(" MemoryBound: " + Twine(MFI->isMemoryBound()),
806 false);
807}
808
809const MCExpr *AMDGPUAsmPrinter::getAmdhsaKernelCodeProperties(
810 const MachineFunction &MF) const {
811 const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
812 MCContext &Ctx = MF.getContext();
813 uint16_t KernelCodeProperties = 0;
814 const GCNUserSGPRUsageInfo &UserSGPRInfo = MFI.getUserSGPRInfo();
815
816 if (UserSGPRInfo.hasPrivateSegmentBuffer()) {
817 KernelCodeProperties |=
818 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER;
819 }
820 if (UserSGPRInfo.hasDispatchPtr()) {
821 KernelCodeProperties |=
822 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR;
823 }
824 if (UserSGPRInfo.hasQueuePtr()) {
825 KernelCodeProperties |= amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR;
826 }
827 if (UserSGPRInfo.hasKernargSegmentPtr()) {
828 KernelCodeProperties |=
829 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR;
830 }
831 if (UserSGPRInfo.hasDispatchID()) {
832 KernelCodeProperties |=
833 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID;
834 }
835 if (UserSGPRInfo.hasFlatScratchInit()) {
836 KernelCodeProperties |=
837 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT;
838 }
839 if (UserSGPRInfo.hasPrivateSegmentSize()) {
840 KernelCodeProperties |=
841 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE;
842 }
843 if (MF.getSubtarget<GCNSubtarget>().isWave32()) {
844 KernelCodeProperties |=
845 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32;
846 }
847
848 // CurrentProgramInfo.DynamicCallStack is a MCExpr and could be
849 // un-evaluatable at this point so it cannot be conditionally checked here.
850 // Instead, we'll directly shift the possibly unknown MCExpr into its place
851 // and bitwise-or it into KernelCodeProperties.
852 const MCExpr *KernelCodePropExpr =
853 MCConstantExpr::create(KernelCodeProperties, Ctx);
854 const MCExpr *OrValue = MCConstantExpr::create(
855 amdhsa::KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK_SHIFT, Ctx);
856 OrValue = MCBinaryExpr::createShl(CurrentProgramInfo.DynamicCallStack,
857 OrValue, Ctx);
858 KernelCodePropExpr = MCBinaryExpr::createOr(KernelCodePropExpr, OrValue, Ctx);
859
860 return KernelCodePropExpr;
861}
862
863MCKernelDescriptor
864AMDGPUAsmPrinter::getAmdhsaKernelDescriptor(const MachineFunction &MF,
865 const SIProgramInfo &PI) const {
866 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
867 const Function &F = MF.getFunction();
868 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
869 MCContext &Ctx = MF.getContext();
870
871 MCKernelDescriptor KernelDescriptor;
872
873 KernelDescriptor.group_segment_fixed_size =
875 KernelDescriptor.private_segment_fixed_size = PI.ScratchSize;
876
877 Align MaxKernArgAlign;
878 KernelDescriptor.kernarg_size = MCConstantExpr::create(
879 STM.getKernArgSegmentSize(F, MaxKernArgAlign), Ctx);
880
881 KernelDescriptor.compute_pgm_rsrc1 = PI.getComputePGMRSrc1(STM, Ctx);
882 KernelDescriptor.compute_pgm_rsrc2 = PI.getComputePGMRSrc2(STM, Ctx);
883 KernelDescriptor.kernel_code_properties = getAmdhsaKernelCodeProperties(MF);
884
885 int64_t PGM_Rsrc3 = 1;
886 bool EvaluatableRsrc3 =
887 CurrentProgramInfo.ComputePGMRSrc3->evaluateAsAbsolute(PGM_Rsrc3);
888 (void)PGM_Rsrc3;
889 (void)EvaluatableRsrc3;
891 STM.hasGFX90AInsts() || STM.hasGFX1250Insts() || !EvaluatableRsrc3 ||
892 static_cast<uint64_t>(PGM_Rsrc3) == 0);
893 KernelDescriptor.compute_pgm_rsrc3 = CurrentProgramInfo.ComputePGMRSrc3;
894
895 KernelDescriptor.kernarg_preload = MCConstantExpr::create(
896 AMDGPU::hasKernargPreload(STM) ? Info->getNumKernargPreloadedSGPRs() : 0,
897 Ctx);
898
899 return KernelDescriptor;
900}
901
903 // Init target streamer lazily on the first function so that previous passes
904 // can set metadata.
906 initTargetStreamer(*MF.getFunction().getParent());
907
908 ResourceUsage = GetResourceUsage(MF);
909 CurrentProgramInfo.reset(MF);
910
911 const AMDGPUMachineFunctionInfo *MFI =
912 MF.getInfo<AMDGPUMachineFunctionInfo>();
913 MCContext &Ctx = MF.getContext();
914
915 // The starting address of all shader programs must be 256 bytes aligned.
916 // Regular functions just need the basic required instruction alignment.
917 MF.ensureAlignment(MFI->isEntryFunction() ? Align(256) : Align(4));
918
920
921 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
923 // FIXME: This should be an explicit check for Mesa.
924 if (!STM.isAmdHsaOS() && !STM.isAmdPalOS()) {
925 MCSectionELF *ConfigSection =
926 Context.getELFSection(".AMDGPU.config", ELF::SHT_PROGBITS, 0);
927 OutStreamer->switchSection(ConfigSection);
928 }
929
930 RI.gatherResourceInfo(MF, *ResourceUsage, OutContext);
931
934 *ResourceUsage;
935 FunctionInfos.push_back(
936 {/*NumSGPR=*/static_cast<uint32_t>(RU.NumExplicitSGPR),
937 /*NumArchVGPR=*/static_cast<uint32_t>(RU.NumVGPR),
938 /*NumAccVGPR=*/static_cast<uint32_t>(RU.NumAGPR),
939 /*PrivateSegmentSize=*/static_cast<uint32_t>(RU.PrivateSegmentSize),
940 /*UsesVCC=*/RU.UsesVCC,
941 /*UsesFlatScratch=*/RU.UsesFlatScratch,
942 /*HasDynStack=*/RU.HasDynamicallySizedStack,
943 /*Sym=*/getSymbol(&MF.getFunction())});
944 }
945
946 if (MFI->isModuleEntryFunction()) {
947 getSIProgramInfo(CurrentProgramInfo, MF);
948 }
949
950 if (STM.isAmdPalOS()) {
951 if (MFI->isEntryFunction())
952 EmitPALMetadata(MF, CurrentProgramInfo);
953 else if (MFI->isModuleEntryFunction())
954 emitPALFunctionMetadata(MF);
955 } else if (!STM.isAmdHsaOS()) {
956 EmitProgramInfoSI(MF, CurrentProgramInfo);
957 }
958
959 DumpCodeInstEmitter = nullptr;
960 if (STM.dumpCode()) {
961 // For -dumpcode, get the assembler out of the streamer. This only works
962 // with -filetype=obj.
963 MCAssembler *Assembler = OutStreamer->getAssemblerPtr();
964 if (Assembler)
965 DumpCodeInstEmitter = Assembler->getEmitterPtr();
966 }
967
968 DisasmLines.clear();
969 HexLines.clear();
971
973
974 emitResourceUsageRemarks(MF, CurrentProgramInfo, MFI->isModuleEntryFunction(),
975 STM.hasMAIInsts());
976
977 {
980 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_NumVGPR, OutContext),
981 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_NumAGPR, OutContext),
982 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_NumSGPR, OutContext),
983 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_NumNamedBarrier,
984 OutContext),
985 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_PrivateSegSize,
986 OutContext),
987 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_UsesVCC, OutContext),
988 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_UsesFlatScratch,
989 OutContext),
990 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_HasDynSizedStack,
991 OutContext),
992 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_HasRecursion,
993 OutContext),
994 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_HasIndirectCall,
995 OutContext));
996 }
997
998 // Emit _dvgpr$ symbol when appropriate.
999 emitDVgprSymbol(MF);
1000
1001 if (isVerbose()) {
1002 MCSectionELF *CommentSection =
1003 Context.getELFSection(".AMDGPU.csdata", ELF::SHT_PROGBITS, 0);
1004 OutStreamer->switchSection(CommentSection);
1005
1006 if (!MFI->isEntryFunction()) {
1008 OutStreamer->emitRawComment(" Function info:", false);
1009
1010 emitCommonFunctionComments(
1011 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_NumVGPR, OutContext)
1012 ->getVariableValue(),
1013 STM.hasMAIInsts() ? RI.getSymbol(CurrentFnSym->getName(),
1014 RIK::RIK_NumAGPR, OutContext)
1015 ->getVariableValue()
1016 : nullptr,
1017 RI.createTotalNumVGPRs(MF, Ctx),
1018 RI.createTotalNumSGPRs(
1019 MF,
1020 MF.getSubtarget<GCNSubtarget>().getTargetID().isXnackOnOrAny(),
1021 Ctx),
1022 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_PrivateSegSize,
1023 OutContext)
1024 ->getVariableValue(),
1025 CurrentProgramInfo.getFunctionCodeSize(MF), MFI);
1026 return false;
1027 }
1028
1029 OutStreamer->emitRawComment(" Kernel info:", false);
1030 emitCommonFunctionComments(
1031 CurrentProgramInfo.NumArchVGPR,
1032 STM.hasMAIInsts() ? CurrentProgramInfo.NumAccVGPR : nullptr,
1033 CurrentProgramInfo.NumVGPR, CurrentProgramInfo.NumSGPR,
1034 CurrentProgramInfo.ScratchSize,
1035 CurrentProgramInfo.getFunctionCodeSize(MF), MFI);
1036
1037 OutStreamer->emitRawComment(
1038 " FloatMode: " + Twine(CurrentProgramInfo.FloatMode), false);
1039 OutStreamer->emitRawComment(
1040 " IeeeMode: " + Twine(CurrentProgramInfo.IEEEMode), false);
1041 OutStreamer->emitRawComment(
1042 " LDSByteSize: " + Twine(CurrentProgramInfo.LDSSize) +
1043 " bytes/workgroup (compile time only)",
1044 false);
1045
1046 OutStreamer->emitRawComment(
1047 " SGPRBlocks: " + getMCExprStr(CurrentProgramInfo.SGPRBlocks), false);
1048
1049 OutStreamer->emitRawComment(
1050 " VGPRBlocks: " + getMCExprStr(CurrentProgramInfo.VGPRBlocks), false);
1051
1052 OutStreamer->emitRawComment(
1053 " NumSGPRsForWavesPerEU: " +
1054 getMCExprStr(CurrentProgramInfo.NumSGPRsForWavesPerEU),
1055 false);
1056 OutStreamer->emitRawComment(
1057 " NumVGPRsForWavesPerEU: " +
1058 getMCExprStr(CurrentProgramInfo.NumVGPRsForWavesPerEU),
1059 false);
1060
1061 if (STM.hasGFX90AInsts()) {
1062 const MCExpr *AdjustedAccum = MCBinaryExpr::createAdd(
1063 CurrentProgramInfo.AccumOffset, MCConstantExpr::create(1, Ctx), Ctx);
1064 AdjustedAccum = MCBinaryExpr::createMul(
1065 AdjustedAccum, MCConstantExpr::create(4, Ctx), Ctx);
1066 OutStreamer->emitRawComment(
1067 " AccumOffset: " + getMCExprStr(AdjustedAccum), false);
1068 }
1069
1070 if (STM.hasGFX1250Insts())
1071 OutStreamer->emitRawComment(
1072 " NamedBarCnt: " + getMCExprStr(CurrentProgramInfo.NamedBarCnt),
1073 false);
1074
1075 OutStreamer->emitRawComment(
1076 " Occupancy: " + getMCExprStr(CurrentProgramInfo.Occupancy), false);
1077
1078 OutStreamer->emitRawComment(
1079 " WaveLimiterHint : " + Twine(MFI->needsWaveLimiter()), false);
1080
1081 OutStreamer->emitRawComment(
1082 " COMPUTE_PGM_RSRC2:SCRATCH_EN: " +
1083 getMCExprStr(CurrentProgramInfo.ScratchEnable),
1084 false);
1085 OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:USER_SGPR: " +
1086 Twine(CurrentProgramInfo.UserSGPR),
1087 false);
1088 OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TRAP_HANDLER: " +
1089 Twine(CurrentProgramInfo.TrapHandlerEnable),
1090 false);
1091 OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TGID_X_EN: " +
1092 Twine(CurrentProgramInfo.TGIdXEnable),
1093 false);
1094 OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TGID_Y_EN: " +
1095 Twine(CurrentProgramInfo.TGIdYEnable),
1096 false);
1097 OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TGID_Z_EN: " +
1098 Twine(CurrentProgramInfo.TGIdZEnable),
1099 false);
1100 OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TIDIG_COMP_CNT: " +
1101 Twine(CurrentProgramInfo.TIdIGCompCount),
1102 false);
1103
1104 [[maybe_unused]] int64_t PGMRSrc3;
1106 STM.hasGFX90AInsts() || STM.hasGFX1250Insts() ||
1107 (CurrentProgramInfo.ComputePGMRSrc3->evaluateAsAbsolute(PGMRSrc3) &&
1108 static_cast<uint64_t>(PGMRSrc3) == 0));
1109 if (STM.hasGFX90AInsts()) {
1110 OutStreamer->emitRawComment(
1111 " COMPUTE_PGM_RSRC3_GFX90A:ACCUM_OFFSET: " +
1112 getMCExprStr(MCKernelDescriptor::bits_get(
1113 CurrentProgramInfo.ComputePGMRSrc3,
1114 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET_SHIFT,
1115 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET, Ctx)),
1116 false);
1117 OutStreamer->emitRawComment(
1118 " COMPUTE_PGM_RSRC3_GFX90A:TG_SPLIT: " +
1119 getMCExprStr(MCKernelDescriptor::bits_get(
1120 CurrentProgramInfo.ComputePGMRSrc3,
1121 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT_SHIFT,
1122 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT, Ctx)),
1123 false);
1124 }
1125 }
1126
1127 if (DumpCodeInstEmitter) {
1128
1129 OutStreamer->switchSection(
1130 Context.getELFSection(".AMDGPU.disasm", ELF::SHT_PROGBITS, 0));
1131
1132 for (size_t i = 0; i < DisasmLines.size(); ++i) {
1133 std::string Comment = "\n";
1134 if (!HexLines[i].empty()) {
1135 Comment = std::string(DisasmLineMaxLen - DisasmLines[i].size(), ' ');
1136 Comment += " ; " + HexLines[i] + "\n";
1137 }
1138
1139 OutStreamer->emitBytes(StringRef(DisasmLines[i]));
1140 OutStreamer->emitBytes(StringRef(Comment));
1141 }
1142 }
1143
1144 return false;
1145}
1146
1147// When appropriate, add a _dvgpr$ symbol, with the value of the function
1148// symbol, plus an offset encoding one less than the number of VGPR blocks used
1149// by the function in bits 5..3 of the symbol value. A "VGPR block" can be
1150// either 16 VGPRs (for a max of 128), or 32 VGPRs (for a max of 256). This is
1151// used by a front-end to have functions that are chained rather than called,
1152// and a dispatcher that dynamically resizes the VGPR count before dispatching
1153// to a function.
1154void AMDGPUAsmPrinter::emitDVgprSymbol(MachineFunction &MF) {
1156 if (MFI.isDynamicVGPREnabled() &&
1158 MCContext &Ctx = MF.getContext();
1159 unsigned BlockSize = MFI.getDynamicVGPRBlockSize();
1160
1161 const MCExpr *EncodedBlocks;
1162 MCValue NumVGPRs;
1163 if (CurrentProgramInfo.NumVGPRsForWavesPerEU->evaluateAsRelocatable(
1164 NumVGPRs, nullptr) &&
1165 NumVGPRs.isAbsolute()) {
1166
1167 // Calculate number of VGPR blocks.
1168 // Treat 0 VGPRs as 1 VGPR to avoid underflowing.
1169 unsigned NumBlocks =
1170 divideCeil(std::max(unsigned(NumVGPRs.getConstant()), 1U), BlockSize);
1171
1172 if (NumBlocks > AMDGPU::IsaInfo::MaxDynamicVGPRBlocks) {
1174 {}, "DVGPR block count " + Twine(NumBlocks) +
1175 " exceeds maximum of " +
1177 " for __dvgpr$ symbol for '" +
1178 Twine(CurrentFnSym->getName()) + "'");
1179 return;
1180 }
1181 unsigned EncodedNumBlocks = (NumBlocks - 1) << 3;
1182 EncodedBlocks = MCConstantExpr::create(EncodedNumBlocks, Ctx);
1183 } else {
1184 // Value not yet available so build a symbolic MCExpr:
1185 // ((alignTo(max(NumVGPRs, 1), BlockSize) / BlockSize - 1) << 3
1186 const MCExpr *One = MCConstantExpr::create(1, Ctx);
1187 const MCExpr *BlockSizeConst = MCConstantExpr::create(BlockSize, Ctx);
1188 const MCExpr *MaxVGPRs = AMDGPUMCExpr::createMax(
1189 {CurrentProgramInfo.NumVGPRsForWavesPerEU, One}, Ctx);
1190 const MCExpr *NumBlocks = MCBinaryExpr::createDiv(
1191 AMDGPUMCExpr::createAlignTo(MaxVGPRs, BlockSizeConst, Ctx),
1192 BlockSizeConst, Ctx);
1193 EncodedBlocks =
1195 MCConstantExpr::create(3, Ctx), Ctx);
1196 }
1197
1198 // Add to function symbol to create _dvgpr$ symbol.
1199 const MCExpr *DVgprFuncVal = MCBinaryExpr::createAdd(
1200 MCSymbolRefExpr::create(CurrentFnSym, Ctx), EncodedBlocks, Ctx);
1201 MCSymbol *DVgprFuncSym =
1202 Ctx.getOrCreateSymbol(Twine("_dvgpr$") + CurrentFnSym->getName());
1203 OutStreamer->emitAssignment(DVgprFuncSym, DVgprFuncVal);
1204 emitVisibility(DVgprFuncSym, MF.getFunction().getVisibility());
1205 emitLinkage(&MF.getFunction(), DVgprFuncSym);
1206 }
1207}
1208
1209// TODO: Fold this into emitFunctionBodyStart.
1210void AMDGPUAsmPrinter::initializeTargetID(const Module &M) {
1212
1213 auto &TSTargetID = getTargetStreamer()->getTargetID();
1214
1215 // Error if -mattr specified xnack or sramecc.
1216 // TODO: Remove this when subtarget features removed.
1217 StringRef FeatureString = getGlobalSTI()->getFeatureString();
1218 if (FeatureString.contains("xnack")) {
1219 M.getContext().diagnose(DiagnosticInfoGeneric(
1220 "xnack/sramecc should be specified via module flags. "
1221 "Use module flag 'amdgpu.xnack' instead of subtarget feature",
1222 DS_Error));
1223 }
1224 if (FeatureString.contains("sramecc")) {
1225 M.getContext().diagnose(DiagnosticInfoGeneric(
1226 "xnack/sramecc should be specified via module flags. "
1227 "Use module flag 'amdgpu.sramecc' instead of subtarget feature",
1228 DS_Error));
1229 }
1230
1231 // Apply xnack/sramecc settings from module flags.
1232 const auto &GCNTM = static_cast<const GCNTargetMachine &>(TM);
1233 if (getGlobalSTI()->getFeatureBits().test(AMDGPU::FeatureXNACKOnOffModes)) {
1234 AMDGPU::TargetIDSetting Setting =
1235 GCNTM.getTargetIDSettingFromModuleFlag(M, "amdgpu.xnack");
1236 if (Setting != AMDGPU::TargetIDSetting::Any)
1237 TSTargetID->setXnackSetting(Setting);
1238 }
1239
1240 if (getGlobalSTI()->getFeatureBits().test(AMDGPU::FeatureSRAMECCOnOffModes)) {
1241 AMDGPU::TargetIDSetting Setting =
1242 GCNTM.getTargetIDSettingFromModuleFlag(M, "amdgpu.sramecc");
1243 if (Setting != AMDGPU::TargetIDSetting::Any)
1244 TSTargetID->setSramEccSetting(Setting);
1245 }
1246}
1247
1248// AccumOffset computed for the MCExpr equivalent of:
1249// alignTo(std::max(1, NumVGPR), 4) / 4 - 1;
1250static const MCExpr *computeAccumOffset(const MCExpr *NumVGPR, MCContext &Ctx) {
1251 const MCExpr *ConstFour = MCConstantExpr::create(4, Ctx);
1252 const MCExpr *ConstOne = MCConstantExpr::create(1, Ctx);
1253
1254 // Can't be lower than 1 for subsequent alignTo.
1255 const MCExpr *MaximumTaken =
1256 AMDGPUMCExpr::createMax({ConstOne, NumVGPR}, Ctx);
1257
1258 // Practically, it's computing divideCeil(MaximumTaken, 4).
1259 const MCExpr *DivCeil = MCBinaryExpr::createDiv(
1260 AMDGPUMCExpr::createAlignTo(MaximumTaken, ConstFour, Ctx), ConstFour,
1261 Ctx);
1262
1263 return MCBinaryExpr::createSub(DivCeil, ConstOne, Ctx);
1264}
1265
1266static unsigned getLDSEncodingGranule(const GCNSubtarget &ST) {
1267 unsigned Granule =
1268 AMDGPU::getLDSEncodingGranule(ST.getTargetID().getGPUKind());
1269 // The legacy generic targets have no encoding granularity feature. Preserve
1270 // the default used for code generation when no GPU is specified.
1271 return Granule ? Granule : 256;
1272}
1273
1274void AMDGPUAsmPrinter::getSIProgramInfo(SIProgramInfo &ProgInfo,
1275 const MachineFunction &MF) {
1276 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
1277 MCContext &Ctx = MF.getContext();
1278
1279 auto CreateExpr = [&Ctx](int64_t Value) {
1280 return MCConstantExpr::create(Value, Ctx);
1281 };
1282
1283 auto TryGetMCExprValue = [](const MCExpr *Value, uint64_t &Res) -> bool {
1284 int64_t Val;
1285 if (Value->evaluateAsAbsolute(Val)) {
1286 Res = Val;
1287 return true;
1288 }
1289 return false;
1290 };
1291
1292 auto GetSymRefExpr =
1293 [&](MCResourceInfo::ResourceInfoKind RIK) -> const MCExpr * {
1294 MCSymbol *Sym = RI.getSymbol(CurrentFnSym->getName(), RIK, OutContext);
1295 return MCSymbolRefExpr::create(Sym, Ctx);
1296 };
1297
1299 ProgInfo.NumArchVGPR = GetSymRefExpr(RIK::RIK_NumVGPR);
1300 ProgInfo.NumAccVGPR = GetSymRefExpr(RIK::RIK_NumAGPR);
1302 ProgInfo.NumAccVGPR, ProgInfo.NumArchVGPR, Ctx);
1303
1304 ProgInfo.AccumOffset = computeAccumOffset(ProgInfo.NumArchVGPR, Ctx);
1305 ProgInfo.TgSplit =
1306 STM.hasTgSplitSupport() && AMDGPU::isTgSplitEnabled(MF.getFunction());
1307 ProgInfo.NumSGPR = GetSymRefExpr(RIK::RIK_NumSGPR);
1308 ProgInfo.ScratchSize = GetSymRefExpr(RIK::RIK_PrivateSegSize);
1309 ProgInfo.VCCUsed = GetSymRefExpr(RIK::RIK_UsesVCC);
1310 ProgInfo.FlatUsed = GetSymRefExpr(RIK::RIK_UsesFlatScratch);
1311 ProgInfo.DynamicCallStack =
1312 MCBinaryExpr::createOr(GetSymRefExpr(RIK::RIK_HasDynSizedStack),
1313 GetSymRefExpr(RIK::RIK_HasRecursion), Ctx);
1314
1315 const MCExpr *BarBlkConst = MCConstantExpr::create(4, Ctx);
1316 const MCExpr *AlignToBlk = AMDGPUMCExpr::createAlignTo(
1317 GetSymRefExpr(RIK::RIK_NumNamedBarrier), BarBlkConst, Ctx);
1318 ProgInfo.NamedBarCnt = MCBinaryExpr::createDiv(AlignToBlk, BarBlkConst, Ctx);
1319
1320 const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1321
1322 // The calculations related to SGPR/VGPR blocks are
1323 // duplicated in part in AMDGPUAsmParser::calculateGPRBlocks, and could be
1324 // unified.
1325 const MCExpr *ExtraSGPRs = AMDGPUMCExpr::createExtraSGPRs(
1326 ProgInfo.VCCUsed, ProgInfo.FlatUsed,
1327 getTargetStreamer()->getTargetID()->isXnackOnOrAny(), Ctx);
1328
1329 // Check the addressable register limit before we add ExtraSGPRs.
1331 !STM.hasSGPRInitBug()) {
1332 unsigned MaxAddressableNumSGPRs = STM.getAddressableNumSGPRs();
1333 uint64_t NumSgpr;
1334 if (TryGetMCExprValue(ProgInfo.NumSGPR, NumSgpr) &&
1335 NumSgpr > MaxAddressableNumSGPRs) {
1336 // This can happen due to a compiler bug or when using inline asm.
1337 LLVMContext &Ctx = MF.getFunction().getContext();
1338 Ctx.diagnose(DiagnosticInfoResourceLimit(
1339 MF.getFunction(), "addressable scalar registers", NumSgpr,
1340 MaxAddressableNumSGPRs, DS_Error, DK_ResourceLimit));
1341 ProgInfo.NumSGPR = CreateExpr(MaxAddressableNumSGPRs - 1);
1342 }
1343 }
1344
1345 // Account for extra SGPRs and VGPRs reserved for debugger use.
1346 ProgInfo.NumSGPR = MCBinaryExpr::createAdd(ProgInfo.NumSGPR, ExtraSGPRs, Ctx);
1347
1348 const Function &F = MF.getFunction();
1349
1350 // Ensure there are enough SGPRs and VGPRs for wave dispatch, where wave
1351 // dispatch registers as function args.
1352 unsigned WaveDispatchNumSGPR = MFI->getNumWaveDispatchSGPRs(),
1353 WaveDispatchNumVGPR = MFI->getNumWaveDispatchVGPRs();
1354
1355 if (WaveDispatchNumSGPR) {
1357 {ProgInfo.NumSGPR,
1358 MCBinaryExpr::createAdd(CreateExpr(WaveDispatchNumSGPR), ExtraSGPRs,
1359 Ctx)},
1360 Ctx);
1361 }
1362
1363 if (WaveDispatchNumVGPR) {
1365 {ProgInfo.NumArchVGPR, CreateExpr(WaveDispatchNumVGPR)}, Ctx);
1366
1368 ProgInfo.NumAccVGPR, ProgInfo.NumArchVGPR, Ctx);
1369 }
1370
1371 // Adjust number of registers used to meet default/requested minimum/maximum
1372 // number of waves per execution unit request.
1373 unsigned MaxWaves = MFI->getMaxWavesPerEU();
1374 ProgInfo.NumSGPRsForWavesPerEU =
1375 AMDGPUMCExpr::createMax({ProgInfo.NumSGPR, CreateExpr(1ul),
1376 CreateExpr(STM.getMinNumSGPRs(MaxWaves))},
1377 Ctx);
1378 ProgInfo.NumVGPRsForWavesPerEU =
1379 AMDGPUMCExpr::createMax({ProgInfo.NumVGPR, CreateExpr(1ul),
1380 CreateExpr(STM.getMinNumVGPRs(
1381 MaxWaves, MFI->getDynamicVGPRBlockSize()))},
1382 Ctx);
1383
1385 STM.hasSGPRInitBug()) {
1386 unsigned MaxAddressableNumSGPRs = STM.getAddressableNumSGPRs();
1387 uint64_t NumSgpr;
1388 if (TryGetMCExprValue(ProgInfo.NumSGPR, NumSgpr) &&
1389 NumSgpr > MaxAddressableNumSGPRs) {
1390 // This can happen due to a compiler bug or when using inline asm to use
1391 // the registers which are usually reserved for vcc etc.
1392 LLVMContext &Ctx = MF.getFunction().getContext();
1393 Ctx.diagnose(DiagnosticInfoResourceLimit(
1394 MF.getFunction(), "scalar registers", NumSgpr, MaxAddressableNumSGPRs,
1396 ProgInfo.NumSGPR = CreateExpr(MaxAddressableNumSGPRs);
1397 ProgInfo.NumSGPRsForWavesPerEU = CreateExpr(MaxAddressableNumSGPRs);
1398 }
1399 }
1400
1401 if (STM.hasSGPRInitBug()) {
1402 ProgInfo.NumSGPR =
1404 ProgInfo.NumSGPRsForWavesPerEU =
1406 }
1407
1408 if (MFI->getNumUserSGPRs() > STM.getMaxNumUserSGPRs()) {
1409 LLVMContext &Ctx = MF.getFunction().getContext();
1410 Ctx.diagnose(DiagnosticInfoResourceLimit(
1411 MF.getFunction(), "user SGPRs", MFI->getNumUserSGPRs(),
1413 }
1414
1415 if (MFI->getLDSSize() > STM.getAddressableLocalMemorySize()) {
1416 LLVMContext &Ctx = MF.getFunction().getContext();
1417 Ctx.diagnose(DiagnosticInfoResourceLimit(
1418 MF.getFunction(), "local memory", MFI->getLDSSize(),
1420 }
1421
1422 // When dynamic VGPRs are enabled, entry functions are launched with a single
1423 // VGPR block. The register allocator enforces this constraint, but we also
1424 // need to catch explicit physical registers in inline asm and wave dispatch
1425 // VGPR arguments.
1426 if (MFI->isDynamicVGPREnabled() &&
1427 AMDGPU::isEntryFunctionCC(F.getCallingConv())) {
1428 unsigned BlockSize = MFI->getDynamicVGPRBlockSize();
1429 uint64_t NumVgpr;
1430 if (TryGetMCExprValue(ProgInfo.NumVGPRsForWavesPerEU, NumVgpr) &&
1431 NumVgpr > BlockSize) {
1432 LLVMContext &Ctx = F.getContext();
1433 Ctx.diagnose(DiagnosticInfoResourceLimit(
1434 F, "dynamic VGPR entry point vector registers", NumVgpr, BlockSize,
1436 }
1437 }
1438
1439 // The MCExpr equivalent of getNumSGPRBlocks/getNumVGPRBlocks:
1440 // (alignTo(max(1u, NumGPR), GPREncodingGranule) / GPREncodingGranule) - 1
1441 auto GetNumGPRBlocks = [&CreateExpr, &Ctx](const MCExpr *NumGPR,
1442 unsigned Granule) {
1443 const MCExpr *OneConst = CreateExpr(1ul);
1444 const MCExpr *GranuleConst = CreateExpr(Granule);
1445 const MCExpr *MaxNumGPR = AMDGPUMCExpr::createMax({NumGPR, OneConst}, Ctx);
1446 const MCExpr *AlignToGPR =
1447 AMDGPUMCExpr::createAlignTo(MaxNumGPR, GranuleConst, Ctx);
1448 const MCExpr *DivGPR =
1449 MCBinaryExpr::createDiv(AlignToGPR, GranuleConst, Ctx);
1450 const MCExpr *SubGPR = MCBinaryExpr::createSub(DivGPR, OneConst, Ctx);
1451 return SubGPR;
1452 };
1453 // GFX10+ will always allocate 128 SGPRs and this field must be 0
1455 ProgInfo.SGPRBlocks = CreateExpr(0ul);
1456 } else {
1457 ProgInfo.SGPRBlocks = GetNumGPRBlocks(ProgInfo.NumSGPRsForWavesPerEU,
1459 }
1460 ProgInfo.VGPRBlocks = GetNumGPRBlocks(ProgInfo.NumVGPRsForWavesPerEU,
1462
1463 const SIModeRegisterDefaults Mode = MFI->getMode();
1464
1465 // Set the value to initialize FP_ROUND and FP_DENORM parts of the mode
1466 // register.
1467 ProgInfo.FloatMode = getFPMode(Mode);
1468
1469 ProgInfo.IEEEMode = Mode.IEEE;
1470
1471 // Make clamp modifier on NaN input returns 0.
1472 ProgInfo.DX10Clamp = Mode.DX10Clamp;
1473 ProgInfo.SGPRSpill = MFI->getNumSpilledSGPRs();
1474 ProgInfo.VGPRSpill = MFI->getNumSpilledVGPRs();
1475
1476 ProgInfo.LDSSize = MFI->getLDSSize();
1477
1478 unsigned LDSGranularityBytes = getLDSEncodingGranule(STM);
1479 ProgInfo.LDSBlocks =
1480 alignTo(ProgInfo.LDSSize, LDSGranularityBytes) / LDSGranularityBytes;
1481
1482 // The MCExpr equivalent of divideCeil.
1483 auto DivideCeil = [&Ctx](const MCExpr *Numerator, const MCExpr *Denominator) {
1484 const MCExpr *Ceil =
1485 AMDGPUMCExpr::createAlignTo(Numerator, Denominator, Ctx);
1486 return MCBinaryExpr::createDiv(Ceil, Denominator, Ctx);
1487 };
1488
1489 // Scratch is allocated in 64-dword or 256-dword blocks.
1490 unsigned ScratchAlignShift =
1491 STM.getGeneration() >= AMDGPUSubtarget::GFX11 ? 8 : 10;
1492 // We need to program the hardware with the amount of scratch memory that
1493 // is used by the entire wave. ProgInfo.ScratchSize is the amount of
1494 // scratch memory used per thread.
1495 ProgInfo.ScratchBlocks = DivideCeil(
1497 CreateExpr(STM.getWavefrontSize()), Ctx),
1498 CreateExpr(1ULL << ScratchAlignShift));
1499
1500 if (STM.hasSupportsWGP()) {
1501 ProgInfo.WgpMode = STM.isCuModeEnabled() ? 0 : 1;
1502 }
1503
1504 if (getIsaVersion(getGlobalSTI()->getCPU()).Major >= 10) {
1505 ProgInfo.MemOrdered = 1;
1506 ProgInfo.FwdProgress = !F.hasFnAttribute("amdgpu-no-fwd-progress");
1507 }
1508
1509 // 0 = X, 1 = XY, 2 = XYZ
1510 unsigned TIDIGCompCnt = 0;
1511 if (MFI->hasWorkItemIDZ())
1512 TIDIGCompCnt = 2;
1513 else if (MFI->hasWorkItemIDY())
1514 TIDIGCompCnt = 1;
1515
1516 // The private segment wave byte offset is the last of the system SGPRs. We
1517 // initially assumed it was allocated, and may have used it. It shouldn't harm
1518 // anything to disable it if we know the stack isn't used here. We may still
1519 // have emitted code reading it to initialize scratch, but if that's unused
1520 // reading garbage should be OK.
1523 MCConstantExpr::create(0, Ctx), Ctx),
1524 ProgInfo.DynamicCallStack, Ctx);
1525
1526 ProgInfo.UserSGPR = MFI->getNumUserSGPRs();
1527 // For AMDHSA, TRAP_HANDLER must be zero, as it is populated by the CP.
1528 ProgInfo.TrapHandlerEnable = STM.isAmdHsaOS() ? 0 : STM.hasTrapHandler();
1529 ProgInfo.TGIdXEnable = MFI->hasWorkGroupIDX();
1530 ProgInfo.TGIdYEnable = MFI->hasWorkGroupIDY();
1531 ProgInfo.TGIdZEnable = MFI->hasWorkGroupIDZ();
1532 ProgInfo.TGSizeEnable = MFI->hasWorkGroupInfo();
1533 ProgInfo.TIdIGCompCount = TIDIGCompCnt;
1534 ProgInfo.EXCPEnMSB = 0;
1535 // For AMDHSA, LDS_SIZE must be zero, as it is populated by the CP.
1536 ProgInfo.LdsSize = STM.isAmdHsaOS() ? 0 : ProgInfo.LDSBlocks;
1537 ProgInfo.EXCPEnable = 0;
1538
1539 if (STM.hasGFX90AInsts()) {
1540 ProgInfo.ComputePGMRSrc3 =
1541 setBits(ProgInfo.ComputePGMRSrc3, ProgInfo.AccumOffset,
1542 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET,
1543 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET_SHIFT, Ctx);
1544 ProgInfo.ComputePGMRSrc3 =
1545 setBits(ProgInfo.ComputePGMRSrc3, CreateExpr(ProgInfo.TgSplit),
1546 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT,
1547 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT_SHIFT, Ctx);
1548 }
1549
1550 if (STM.hasGFX1250Insts())
1551 ProgInfo.ComputePGMRSrc3 =
1552 setBits(ProgInfo.ComputePGMRSrc3, ProgInfo.NamedBarCnt,
1553 amdhsa::COMPUTE_PGM_RSRC3_GFX125_NAMED_BAR_CNT,
1554 amdhsa::COMPUTE_PGM_RSRC3_GFX125_NAMED_BAR_CNT_SHIFT, Ctx);
1555
1556 ProgInfo.Occupancy = createOccupancy(
1559 MFI->getDynamicVGPRBlockSize(), STM, Ctx);
1560
1561 const auto [MinWEU, MaxWEU] =
1562 AMDGPU::getIntegerPairAttribute(F, "amdgpu-waves-per-eu", {0, 0}, true);
1563 uint64_t Occupancy;
1564 if (TryGetMCExprValue(ProgInfo.Occupancy, Occupancy) && Occupancy < MinWEU) {
1565 DiagnosticInfoOptimizationFailure Diag(
1566 F, F.getSubprogram(),
1567 "failed to meet occupancy target given by 'amdgpu-waves-per-eu' in "
1568 "'" +
1569 F.getName() + "': desired occupancy was " + Twine(MinWEU) +
1570 ", final occupancy is " + Twine(Occupancy));
1571 F.getContext().diagnose(Diag);
1572 }
1573}
1574
1575static unsigned getRsrcReg(CallingConv::ID CallConv) {
1576 switch (CallConv) {
1577 default:
1578 [[fallthrough]];
1593 }
1594}
1595
1596void AMDGPUAsmPrinter::EmitProgramInfoSI(
1597 const MachineFunction &MF, const SIProgramInfo &CurrentProgramInfo) {
1598 const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1599 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
1600 unsigned RsrcReg = getRsrcReg(MF.getFunction().getCallingConv());
1601 MCContext &Ctx = MF.getContext();
1602
1603 // (((Value) & Mask) << Shift)
1604 auto SetBits = [&Ctx](const MCExpr *Value, uint32_t Mask, uint32_t Shift) {
1605 const MCExpr *msk = MCConstantExpr::create(Mask, Ctx);
1606 const MCExpr *shft = MCConstantExpr::create(Shift, Ctx);
1608 shft, Ctx);
1609 };
1610
1611 auto EmitResolvedOrExpr = [this](const MCExpr *Value, unsigned Size) {
1612 int64_t Val;
1613 if (Value->evaluateAsAbsolute(Val))
1614 OutStreamer->emitIntValue(static_cast<uint64_t>(Val), Size);
1615 else
1616 OutStreamer->emitValue(Value, Size);
1617 };
1618
1619 if (AMDGPU::isCompute(MF.getFunction().getCallingConv())) {
1621
1622 EmitResolvedOrExpr(CurrentProgramInfo.getComputePGMRSrc1(STM, Ctx),
1623 /*Size=*/4);
1624
1626 EmitResolvedOrExpr(CurrentProgramInfo.getComputePGMRSrc2(STM, Ctx),
1627 /*Size=*/4);
1628
1630
1631 // Sets bits according to S_0286E8_WAVESIZE_* mask and shift values for the
1632 // appropriate generation.
1633 if (STM.getGeneration() >= AMDGPUSubtarget::GFX12) {
1634 EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1635 /*Mask=*/0x3FFFF, /*Shift=*/12),
1636 /*Size=*/4);
1637 } else if (STM.getGeneration() == AMDGPUSubtarget::GFX11) {
1638 EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1639 /*Mask=*/0x7FFF, /*Shift=*/12),
1640 /*Size=*/4);
1641 } else {
1642 EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1643 /*Mask=*/0x1FFF, /*Shift=*/12),
1644 /*Size=*/4);
1645 }
1646
1647 // TODO: Should probably note flat usage somewhere. SC emits a "FlatPtr32 =
1648 // 0" comment but I don't see a corresponding field in the register spec.
1649 } else {
1650 OutStreamer->emitInt32(RsrcReg);
1651
1652 const MCExpr *GPRBlocks = MCBinaryExpr::createOr(
1653 SetBits(CurrentProgramInfo.VGPRBlocks, /*Mask=*/0x3F, /*Shift=*/0),
1654 SetBits(CurrentProgramInfo.SGPRBlocks, /*Mask=*/0x0F, /*Shift=*/6),
1655 MF.getContext());
1656 EmitResolvedOrExpr(GPRBlocks, /*Size=*/4);
1658
1659 // Sets bits according to S_0286E8_WAVESIZE_* mask and shift values for the
1660 // appropriate generation.
1661 if (STM.getGeneration() >= AMDGPUSubtarget::GFX12) {
1662 EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1663 /*Mask=*/0x3FFFF, /*Shift=*/12),
1664 /*Size=*/4);
1665 } else if (STM.getGeneration() == AMDGPUSubtarget::GFX11) {
1666 EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1667 /*Mask=*/0x7FFF, /*Shift=*/12),
1668 /*Size=*/4);
1669 } else {
1670 EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1671 /*Mask=*/0x1FFF, /*Shift=*/12),
1672 /*Size=*/4);
1673 }
1674 }
1675
1676 if (MF.getFunction().getCallingConv() == CallingConv::AMDGPU_PS) {
1678 unsigned ExtraLDSSize = STM.getGeneration() >= AMDGPUSubtarget::GFX11
1679 ? divideCeil(CurrentProgramInfo.LDSBlocks, 2)
1680 : CurrentProgramInfo.LDSBlocks;
1681 OutStreamer->emitInt32(S_00B02C_EXTRA_LDS_SIZE(ExtraLDSSize));
1683 OutStreamer->emitInt32(MFI->getPSInputEnable());
1685 OutStreamer->emitInt32(MFI->getPSInputAddr());
1686 }
1687
1688 OutStreamer->emitInt32(R_SPILLED_SGPRS);
1689 OutStreamer->emitInt32(MFI->getNumSpilledSGPRs());
1690 OutStreamer->emitInt32(R_SPILLED_VGPRS);
1691 OutStreamer->emitInt32(MFI->getNumSpilledVGPRs());
1692}
1693
1694// Helper function to add common PAL Metadata 3.0+
1696 const SIProgramInfo &CurrentProgramInfo,
1697 CallingConv::ID CC, const GCNSubtarget &ST,
1698 unsigned DynamicVGPRBlockSize) {
1699 if (ST.hasFeature(AMDGPU::FeatureDX10ClampAndIEEEMode))
1700 MD->setHwStage(CC, ".ieee_mode", (bool)CurrentProgramInfo.IEEEMode);
1701
1702 MD->setHwStage(CC, ".wgp_mode", (bool)CurrentProgramInfo.WgpMode);
1703 MD->setHwStage(CC, ".mem_ordered", (bool)CurrentProgramInfo.MemOrdered);
1704 MD->setHwStage(CC, ".forward_progress", (bool)CurrentProgramInfo.FwdProgress);
1705
1706 if (AMDGPU::isCompute(CC)) {
1707 MD->setHwStage(CC, ".trap_present",
1708 (bool)CurrentProgramInfo.TrapHandlerEnable);
1709 MD->setHwStage(CC, ".excp_en", CurrentProgramInfo.EXCPEnable);
1710
1711 if (DynamicVGPRBlockSize != 0)
1712 MD->setComputeRegisters(".dynamic_vgpr_en", true);
1713 }
1714
1716 CC, ".lds_size",
1717 (unsigned)(CurrentProgramInfo.LdsSize * getLDSEncodingGranule(ST)));
1718}
1719
1720// This is the equivalent of EmitProgramInfoSI above, but for when the OS type
1721// is AMDPAL. It stores each compute/SPI register setting and other PAL
1722// metadata items into the PALMD::Metadata, combining with any provided by the
1723// frontend as LLVM metadata. Once all functions are written, the PAL metadata
1724// is then written as a single block in the .note section.
1725void AMDGPUAsmPrinter::EmitPALMetadata(
1726 const MachineFunction &MF, const SIProgramInfo &CurrentProgramInfo) {
1727 const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1728 auto CC = MF.getFunction().getCallingConv();
1729 auto *MD = getTargetStreamer()->getPALMetadata();
1730 auto &Ctx = MF.getContext();
1731
1732 MD->setEntryPoint(CC, MF.getFunction().getName());
1733 MD->setNumUsedVgprs(CC, CurrentProgramInfo.NumVGPRsForWavesPerEU, Ctx);
1734
1735 // For targets that support dynamic VGPRs, set the number of saved dynamic
1736 // VGPRs (if any) in the PAL metadata.
1737 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
1738 if (MFI->isDynamicVGPREnabled() &&
1740 MD->setHwStage(CC, ".dynamic_vgpr_saved_count",
1742
1743 // Only set AGPRs for supported devices
1744 if (STM.hasMAIInsts()) {
1745 MD->setNumUsedAgprs(CC, CurrentProgramInfo.NumAccVGPR);
1746 }
1747
1748 MD->setNumUsedSgprs(CC, CurrentProgramInfo.NumSGPRsForWavesPerEU, Ctx);
1749 if (MD->getPALMajorVersion() < 3) {
1750 MD->setRsrc1(CC, CurrentProgramInfo.getPGMRSrc1(CC, STM, Ctx), Ctx);
1751 if (AMDGPU::isCompute(CC)) {
1752 MD->setRsrc2(CC, CurrentProgramInfo.getComputePGMRSrc2(STM, Ctx), Ctx);
1753 } else {
1754 const MCExpr *HasScratchBlocks =
1755 MCBinaryExpr::createGT(CurrentProgramInfo.ScratchBlocks,
1756 MCConstantExpr::create(0, Ctx), Ctx);
1757 auto [Shift, Mask] = getShiftMask(C_00B84C_SCRATCH_EN);
1758 MD->setRsrc2(CC, maskShiftSet(HasScratchBlocks, Mask, Shift, Ctx), Ctx);
1759 }
1760 } else {
1761 MD->setHwStage(CC, ".debug_mode", (bool)CurrentProgramInfo.DebugMode);
1762 MD->setHwStage(CC, ".scratch_en", msgpack::Type::Boolean,
1763 CurrentProgramInfo.ScratchEnable);
1764 EmitPALMetadataCommon(MD, CurrentProgramInfo, CC, STM,
1766 }
1767
1768 // ScratchSize is in bytes, 16 aligned.
1769 MD->setScratchSize(
1770 CC,
1771 AMDGPUMCExpr::createAlignTo(CurrentProgramInfo.ScratchSize,
1772 MCConstantExpr::create(16, Ctx), Ctx),
1773 Ctx);
1774
1775 if (MF.getFunction().getCallingConv() == CallingConv::AMDGPU_PS) {
1776 unsigned ExtraLDSSize = STM.getGeneration() >= AMDGPUSubtarget::GFX11
1777 ? divideCeil(CurrentProgramInfo.LDSBlocks, 2)
1778 : CurrentProgramInfo.LDSBlocks;
1779 if (MD->getPALMajorVersion() < 3) {
1780 MD->setRsrc2(
1781 CC,
1783 Ctx);
1784 MD->setSpiPsInputEna(MFI->getPSInputEnable());
1785 MD->setSpiPsInputAddr(MFI->getPSInputAddr());
1786 } else {
1787 // Graphics registers
1788 const unsigned ExtraLdsDwGranularity =
1789 STM.getGeneration() >= AMDGPUSubtarget::GFX11 ? 256 : 128;
1790 MD->setGraphicsRegisters(
1791 ".ps_extra_lds_size",
1792 (unsigned)(ExtraLDSSize * ExtraLdsDwGranularity * sizeof(uint32_t)));
1793
1794 // Set PsInputEna and PsInputAddr .spi_ps_input_ena and .spi_ps_input_addr
1795 static StringLiteral const PsInputFields[] = {
1796 ".persp_sample_ena", ".persp_center_ena",
1797 ".persp_centroid_ena", ".persp_pull_model_ena",
1798 ".linear_sample_ena", ".linear_center_ena",
1799 ".linear_centroid_ena", ".line_stipple_tex_ena",
1800 ".pos_x_float_ena", ".pos_y_float_ena",
1801 ".pos_z_float_ena", ".pos_w_float_ena",
1802 ".front_face_ena", ".ancillary_ena",
1803 ".sample_coverage_ena", ".pos_fixed_pt_ena"};
1804 unsigned PSInputEna = MFI->getPSInputEnable();
1805 unsigned PSInputAddr = MFI->getPSInputAddr();
1806 for (auto [Idx, Field] : enumerate(PsInputFields)) {
1807 MD->setGraphicsRegisters(".spi_ps_input_ena", Field,
1808 (bool)((PSInputEna >> Idx) & 1));
1809 MD->setGraphicsRegisters(".spi_ps_input_addr", Field,
1810 (bool)((PSInputAddr >> Idx) & 1));
1811 }
1812 }
1813 }
1814
1815 // For version 3 and above the wave front size is already set in the metadata
1816 if (MD->getPALMajorVersion() < 3 && STM.isWave32())
1817 MD->setWave32(MF.getFunction().getCallingConv());
1818}
1819
1820void AMDGPUAsmPrinter::emitPALFunctionMetadata(const MachineFunction &MF) {
1821 auto *MD = getTargetStreamer()->getPALMetadata();
1822 const MachineFrameInfo &MFI = MF.getFrameInfo();
1823 StringRef FnName = MF.getFunction().getName();
1824 MD->setFunctionScratchSize(FnName, MFI.getStackSize());
1825 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
1826 MCContext &Ctx = MF.getContext();
1827
1828 if (MD->getPALMajorVersion() < 3) {
1829 // Set compute registers
1830 MD->setRsrc1(
1832 CurrentProgramInfo.getPGMRSrc1(CallingConv::AMDGPU_CS, ST, Ctx), Ctx);
1833 MD->setRsrc2(CallingConv::AMDGPU_CS,
1834 CurrentProgramInfo.getComputePGMRSrc2(ST, Ctx), Ctx);
1835 } else {
1837 MD, CurrentProgramInfo, CallingConv::AMDGPU_CS, ST,
1838 MF.getInfo<SIMachineFunctionInfo>()->getDynamicVGPRBlockSize());
1839 }
1840
1841 // Set optional info
1842 MD->setFunctionLdsSize(FnName, CurrentProgramInfo.LDSSize);
1843 MD->setFunctionNumUsedVgprs(FnName, CurrentProgramInfo.NumVGPRsForWavesPerEU);
1844 MD->setFunctionNumUsedSgprs(FnName, CurrentProgramInfo.NumSGPRsForWavesPerEU);
1845}
1846
1847// This is supposed to be log2(Size)
1849 switch (Size) {
1850 case 4:
1851 return AMD_ELEMENT_4_BYTES;
1852 case 8:
1853 return AMD_ELEMENT_8_BYTES;
1854 case 16:
1855 return AMD_ELEMENT_16_BYTES;
1856 default:
1857 llvm_unreachable("invalid private_element_size");
1858 }
1859}
1860
1861void AMDGPUAsmPrinter::getAmdKernelCode(AMDGPUMCKernelCodeT &Out,
1862 const SIProgramInfo &CurrentProgramInfo,
1863 const MachineFunction &MF) const {
1864 const Function &F = MF.getFunction();
1865 assert(F.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
1866 F.getCallingConv() == CallingConv::SPIR_KERNEL);
1867
1868 const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1869 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
1870 MCContext &Ctx = MF.getContext();
1871
1872 Out.initDefault(STM, Ctx, /*InitMCExpr=*/false);
1873
1874 Out.compute_pgm_resource1_registers =
1875 CurrentProgramInfo.getComputePGMRSrc1(STM, Ctx);
1876 Out.compute_pgm_resource2_registers =
1877 CurrentProgramInfo.getComputePGMRSrc2(STM, Ctx);
1878 Out.code_properties |= AMD_CODE_PROPERTY_IS_PTR64;
1879
1880 Out.is_dynamic_callstack = CurrentProgramInfo.DynamicCallStack;
1881
1883 getElementByteSizeValue(STM.getMaxPrivateElementSize(true)));
1884
1885 const GCNUserSGPRUsageInfo &UserSGPRInfo = MFI->getUserSGPRInfo();
1886 if (UserSGPRInfo.hasPrivateSegmentBuffer()) {
1888 }
1889
1890 if (UserSGPRInfo.hasDispatchPtr())
1892
1893 if (UserSGPRInfo.hasQueuePtr())
1895
1896 if (UserSGPRInfo.hasKernargSegmentPtr())
1898
1899 if (UserSGPRInfo.hasDispatchID())
1901
1902 if (UserSGPRInfo.hasFlatScratchInit())
1904
1905 if (UserSGPRInfo.hasPrivateSegmentSize())
1907
1908 if (STM.isXNACKEnabled())
1909 Out.code_properties |= AMD_CODE_PROPERTY_IS_XNACK_SUPPORTED;
1910
1911 Align MaxKernArgAlign;
1912 Out.kernarg_segment_byte_size = STM.getKernArgSegmentSize(F, MaxKernArgAlign);
1913 Out.wavefront_sgpr_count = CurrentProgramInfo.NumSGPR;
1914 Out.workitem_vgpr_count = CurrentProgramInfo.NumVGPR;
1915 Out.workitem_private_segment_byte_size = CurrentProgramInfo.ScratchSize;
1916 Out.workgroup_group_segment_byte_size = CurrentProgramInfo.LDSSize;
1917
1918 // kernarg_segment_alignment is specified as log of the alignment.
1919 // The minimum alignment is 16.
1920 // FIXME: The metadata treats the minimum as 4?
1921 Out.kernarg_segment_alignment = Log2(std::max(Align(16), MaxKernArgAlign));
1922}
1923
1925 const char *ExtraCode, raw_ostream &O) {
1926 // First try the generic code, which knows about modifiers like 'c' and 'n'.
1927 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O))
1928 return false;
1929
1930 if (ExtraCode && ExtraCode[0]) {
1931 if (ExtraCode[1] != 0)
1932 return true; // Unknown modifier.
1933
1934 switch (ExtraCode[0]) {
1935 case 'r':
1936 break;
1937 default:
1938 return true;
1939 }
1940 }
1941
1942 // TODO: Should be able to support other operand types like globals.
1943 const MachineOperand &MO = MI->getOperand(OpNo);
1944 if (MO.isReg()) {
1946 *MF->getSubtarget().getRegisterInfo());
1947 return false;
1948 }
1949 if (MO.isImm()) {
1950 int64_t Val = MO.getImm();
1952 O << Val;
1953 } else if (isUInt<16>(Val)) {
1954 O << format("0x%" PRIx16, static_cast<uint16_t>(Val));
1955 } else if (isUInt<32>(Val)) {
1956 O << format("0x%" PRIx32, static_cast<uint32_t>(Val));
1957 } else {
1958 O << format("0x%" PRIx64, static_cast<uint64_t>(Val));
1959 }
1960 return false;
1961 }
1962 return true;
1963}
1964
1972
1973void AMDGPUAsmPrinter::emitResourceUsageRemarks(
1974 const MachineFunction &MF, const SIProgramInfo &CurrentProgramInfo,
1975 bool isModuleEntryFunction, bool hasMAIInsts) {
1976 if (!ORE)
1977 return;
1978
1979 const char *Name = "kernel-resource-usage";
1980 const char *Indent = " ";
1981
1982 // If the remark is not specifically enabled, do not output to yaml
1984 if (!Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(Name))
1985 return;
1986
1987 // Currently non-kernel functions have no resources to emit.
1989 return;
1990
1991 auto EmitResourceUsageRemark = [&](StringRef RemarkName,
1992 StringRef RemarkLabel, auto Argument) {
1993 // Add an indent for every line besides the line with the kernel name. This
1994 // makes it easier to tell which resource usage go with which kernel since
1995 // the kernel name will always be displayed first.
1996 std::string LabelStr = RemarkLabel.str() + ": ";
1997 if (RemarkName != "FunctionName")
1998 LabelStr = Indent + LabelStr;
1999
2000 ORE->emit([&]() {
2001 return MachineOptimizationRemarkAnalysis(Name, RemarkName,
2003 &MF.front())
2004 << LabelStr << ore::NV(RemarkName, Argument);
2005 });
2006 };
2007
2008 // FIXME: Formatting here is pretty nasty because clang does not accept
2009 // newlines from diagnostics. This forces us to emit multiple diagnostic
2010 // remarks to simulate newlines. If and when clang does accept newlines, this
2011 // formatting should be aggregated into one remark with newlines to avoid
2012 // printing multiple diagnostic location and diag opts.
2013 EmitResourceUsageRemark("FunctionName", "Function Name",
2014 MF.getFunction().getName());
2015 EmitResourceUsageRemark("NumSGPR", "TotalSGPRs",
2016 getMCExprStr(CurrentProgramInfo.NumSGPR));
2017 EmitResourceUsageRemark("NumVGPR", "VGPRs",
2018 getMCExprStr(CurrentProgramInfo.NumArchVGPR));
2019 if (hasMAIInsts) {
2020 EmitResourceUsageRemark("NumAGPR", "AGPRs",
2021 getMCExprStr(CurrentProgramInfo.NumAccVGPR));
2022 }
2023 EmitResourceUsageRemark("ScratchSize", "ScratchSize [bytes/lane]",
2024 getMCExprStr(CurrentProgramInfo.ScratchSize));
2025 int64_t DynStack;
2026 bool DynStackEvaluatable =
2027 CurrentProgramInfo.DynamicCallStack->evaluateAsAbsolute(DynStack);
2028 StringRef DynamicStackStr =
2029 DynStackEvaluatable && DynStack ? "True" : "False";
2030 EmitResourceUsageRemark("DynamicStack", "Dynamic Stack", DynamicStackStr);
2031 EmitResourceUsageRemark("Occupancy", "Occupancy [waves/SIMD]",
2032 getMCExprStr(CurrentProgramInfo.Occupancy));
2033 EmitResourceUsageRemark("SGPRSpill", "SGPRs Spill",
2034 CurrentProgramInfo.SGPRSpill);
2035 EmitResourceUsageRemark("VGPRSpill", "VGPRs Spill",
2036 CurrentProgramInfo.VGPRSpill);
2037 if (isModuleEntryFunction)
2038 EmitResourceUsageRemark("BytesLDS", "LDS Size [bytes/block]",
2039 CurrentProgramInfo.LDSSize);
2040}
2041
2051
2067
2076
2077char AMDGPUAsmPrinter::ID = 0;
2078
2079INITIALIZE_PASS(AMDGPUAsmPrinter, "amdgpu-asm-printer",
2080 "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.
uint64_t 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:211
#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.
RISCVCC::CondCode CC
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:1387
#define R_0286E8_SPI_TMPRING_SIZE
Definition SIDefines.h:1529
#define FP_ROUND_MODE_DP(x)
Definition SIDefines.h:1511
#define C_00B84C_SCRATCH_EN
Definition SIDefines.h:1423
#define FP_ROUND_ROUND_TO_NEAREST
Definition SIDefines.h:1503
#define R_0286D0_SPI_PS_INPUT_ADDR
Definition SIDefines.h:1462
#define R_00B860_COMPUTE_TMPRING_SIZE
Definition SIDefines.h:1524
#define R_00B428_SPI_SHADER_PGM_RSRC1_HS
Definition SIDefines.h:1410
#define R_00B328_SPI_SHADER_PGM_RSRC1_ES
Definition SIDefines.h:1409
#define R_00B528_SPI_SHADER_PGM_RSRC1_LS
Definition SIDefines.h:1418
#define R_0286CC_SPI_PS_INPUT_ENA
Definition SIDefines.h:1461
#define R_00B128_SPI_SHADER_PGM_RSRC1_VS
Definition SIDefines.h:1396
#define FP_DENORM_MODE_DP(x)
Definition SIDefines.h:1522
#define R_00B848_COMPUTE_PGM_RSRC1
Definition SIDefines.h:1464
#define R_SPILLED_SGPRS
Definition SIDefines.h:1543
#define FP_ROUND_MODE_SP(x)
Definition SIDefines.h:1510
#define FP_DENORM_MODE_SP(x)
Definition SIDefines.h:1521
#define R_00B228_SPI_SHADER_PGM_RSRC1_GS
Definition SIDefines.h:1401
#define R_SPILLED_VGPRS
Definition SIDefines.h:1544
#define S_00B02C_EXTRA_LDS_SIZE(x)
Definition SIDefines.h:1395
#define R_00B84C_COMPUTE_PGM_RSRC2
Definition SIDefines.h:1420
#define R_00B02C_SPI_SHADER_PGM_RSRC2_PS
Definition SIDefines.h:1394
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
void emitDirectiveAMDGCNTargetOnce()
Emit the .amdgcn_target directive unless it has already been emitted to this streamer.
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:95
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.
dwarf::Attribute TypeAddressSpaceAttribute
The attribute used for a pointer type's DWARF address space.
Definition AsmPrinter.h:299
TargetMachine & TM
Target machine description.
Definition AsmPrinter.h:98
MachineFunction * MF
The current machine function.
Definition AsmPrinter.h:113
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:128
AsmPrinter(TargetMachine &TM, std::unique_ptr< MCStreamer > Streamer, char &ID=AsmPrinter::ID)
MCSymbol * CurrentFnSym
The symbol for the current function.
Definition AsmPrinter.h:135
MachineModuleInfo * MMI
This is a pointer to the current MachineModuleInfo.
Definition AsmPrinter.h:116
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition AsmPrinter.h:105
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:478
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition AsmPrinter.h:110
const MCAsmInfo & MAI
Target Asm Printer information.
Definition AsmPrinter.h:101
std::function< MachineModuleInfo *()> GetMMI
Definition AsmPrinter.h:183
bool isVerbose() const
Return true if assembly output should contain comments.
Definition AsmPrinter.h:335
MCSymbol * getFunctionEnd() const
Definition AsmPrinter.h:345
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:716
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:352
unsigned getMinNumSGPRs(unsigned WavesPerEU) const
unsigned getTotalNumVGPRs() const
unsigned getMinNumVGPRs(unsigned WavesPerEU, unsigned DynamicVGPRBlockSize) const
bool hasInstPrefSize() const
bool isCuModeEnabled() const
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
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:76
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:1893
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:28
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:41
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:314
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:965
@ STT_AMDGPU_HSA_KERNEL
Definition ELF.h:1255
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:149
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:202
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:879
#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.