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 switch (CodeObjectVersion) {
416 HSAMetadataStream = std::make_unique<HSAMD::MetadataStreamerMsgPackV4>();
417 break;
419 HSAMetadataStream = std::make_unique<HSAMD::MetadataStreamerMsgPackV5>();
420 break;
422 HSAMetadataStream = std::make_unique<HSAMD::MetadataStreamerMsgPackV6>();
423 break;
424 default:
425 reportFatalUsageError("unsupported code object version");
426 }
427
428 addAsmPrinterHandler(std::make_unique<AMDGPUAsmPrinterHandler>(this));
429 }
430
432}
433
434/// Mimics GCNSubtarget::computeOccupancy for MCExpr.
435///
436/// Remove dependency on GCNSubtarget and depend only only the necessary values
437/// for said occupancy computation. Should match computeOccupancy implementation
438/// without passing \p STM on.
439const AMDGPUMCExpr *createOccupancy(unsigned InitOcc, const MCExpr *NumSGPRs,
440 const MCExpr *NumVGPRs,
441 unsigned DynamicVGPRBlockSize,
442 const GCNSubtarget &STM, MCContext &Ctx) {
443 unsigned MaxWaves = STM.getMaxWavesPerEU();
444 unsigned Granule = IsaInfo::getVGPRAllocGranule(STM, DynamicVGPRBlockSize);
445 unsigned TargetTotalNumVGPRs = STM.getTotalNumVGPRs();
446
447 // Bake the per-function SGPR budget into the operands so the late-evaluated
448 // MCExpr stays arithmetic. The trap reservation in particular is implicit on
449 // amdhsa and lives on STM, not on the assembler's MCSubtargetInfo.
451 unsigned SGPRTotal = AMDGPU::getTotalNumSGPRs(Kind);
452 unsigned SGPRGranule = AMDGPU::getSGPRAllocGranule(Kind);
453 unsigned SGPRTrapReserve = STM.hasTrapHandler() ? IsaInfo::TRAP_NUM_SGPRS : 0;
454
455 auto CreateExpr = [&Ctx](unsigned Value) {
456 return MCConstantExpr::create(Value, Ctx);
457 };
458
459 // Zero SGPR count when SGPRs don't limit occupancy, so the MCExpr skips the
460 // SGPR term without having to test the generation itself.
461 const MCExpr *SGPRArg =
462 IsaInfo::isSGPROccupancyLimited(STM) ? NumSGPRs : CreateExpr(0);
463
465 {CreateExpr(MaxWaves), CreateExpr(Granule),
466 CreateExpr(TargetTotalNumVGPRs),
467 CreateExpr(InitOcc), CreateExpr(SGPRTotal),
468 CreateExpr(SGPRGranule),
469 CreateExpr(SGPRTrapReserve), SGPRArg, NumVGPRs},
470 Ctx);
471}
472
473void AMDGPUAsmPrinter::validateMCResourceInfo(Function &F) {
474 if (F.isDeclaration() || !AMDGPU::isModuleEntryFunctionCC(F.getCallingConv()))
475 return;
476
478 const GCNSubtarget &STM = TM.getSubtarget<GCNSubtarget>(F);
479 MCSymbol *FnSym = TM.getSymbol(&F);
480
481 auto TryGetMCExprValue = [](const MCExpr *Value, uint64_t &Res) -> bool {
482 int64_t Val;
483 if (Value->evaluateAsAbsolute(Val)) {
484 Res = Val;
485 return true;
486 }
487 return false;
488 };
489
490 const uint64_t MaxScratchPerWorkitem =
492 MCSymbol *ScratchSizeSymbol =
493 RI.getSymbol(FnSym->getName(), RIK::RIK_PrivateSegSize, OutContext);
494 uint64_t ScratchSize;
495 if (ScratchSizeSymbol->isVariable() &&
496 TryGetMCExprValue(ScratchSizeSymbol->getVariableValue(), ScratchSize) &&
497 ScratchSize > MaxScratchPerWorkitem) {
498 DiagnosticInfoStackSize DiagStackSize(F, ScratchSize, MaxScratchPerWorkitem,
499 DS_Error);
500 F.getContext().diagnose(DiagStackSize);
501 }
502
503 // Validate addressable scalar registers (i.e., prior to added implicit
504 // SGPRs).
505 MCSymbol *NumSGPRSymbol =
506 RI.getSymbol(FnSym->getName(), RIK::RIK_NumSGPR, OutContext);
508 !STM.hasSGPRInitBug()) {
509 unsigned MaxAddressableNumSGPRs = STM.getAddressableNumSGPRs();
510 uint64_t NumSgpr;
511 if (NumSGPRSymbol->isVariable() &&
512 TryGetMCExprValue(NumSGPRSymbol->getVariableValue(), NumSgpr) &&
513 NumSgpr > MaxAddressableNumSGPRs) {
514 F.getContext().diagnose(DiagnosticInfoResourceLimit(
515 F, "addressable scalar registers", NumSgpr, MaxAddressableNumSGPRs,
517 return;
518 }
519 }
520
521 MCSymbol *VCCUsedSymbol =
522 RI.getSymbol(FnSym->getName(), RIK::RIK_UsesVCC, OutContext);
523 MCSymbol *FlatUsedSymbol =
524 RI.getSymbol(FnSym->getName(), RIK::RIK_UsesFlatScratch, OutContext);
525 uint64_t VCCUsed, FlatUsed, NumSgpr;
526
527 if (NumSGPRSymbol->isVariable() && VCCUsedSymbol->isVariable() &&
528 FlatUsedSymbol->isVariable() &&
529 TryGetMCExprValue(NumSGPRSymbol->getVariableValue(), NumSgpr) &&
530 TryGetMCExprValue(VCCUsedSymbol->getVariableValue(), VCCUsed) &&
531 TryGetMCExprValue(FlatUsedSymbol->getVariableValue(), FlatUsed)) {
532
533 // Recomputes NumSgprs + implicit SGPRs but all symbols should now be
534 // resolvable.
535 NumSgpr += IsaInfo::getNumExtraSGPRs(
536 STM, VCCUsed, FlatUsed,
537 getTargetStreamer()->getTargetID()->isXnackOnOrAny());
539 STM.hasSGPRInitBug()) {
540 unsigned MaxAddressableNumSGPRs = STM.getAddressableNumSGPRs();
541 if (NumSgpr > MaxAddressableNumSGPRs) {
542 F.getContext().diagnose(DiagnosticInfoResourceLimit(
543 F, "scalar registers", NumSgpr, MaxAddressableNumSGPRs, DS_Error,
545 return;
546 }
547 }
548
549 MCSymbol *NumVgprSymbol =
550 RI.getSymbol(FnSym->getName(), RIK::RIK_NumVGPR, OutContext);
551 MCSymbol *NumAgprSymbol =
552 RI.getSymbol(FnSym->getName(), RIK::RIK_NumAGPR, OutContext);
553 uint64_t NumVgpr, NumAgpr;
554
555 MachineModuleInfo &MMI = *GetMMI();
556 MachineFunction *MF = MMI.getMachineFunction(F);
557 if (MF && NumVgprSymbol->isVariable() && NumAgprSymbol->isVariable() &&
558 TryGetMCExprValue(NumVgprSymbol->getVariableValue(), NumVgpr) &&
559 TryGetMCExprValue(NumAgprSymbol->getVariableValue(), NumAgpr)) {
560 const SIMachineFunctionInfo &MFI = *MF->getInfo<SIMachineFunctionInfo>();
561 unsigned MaxWaves = MFI.getMaxWavesPerEU();
562 uint64_t TotalNumVgpr =
563 getTotalNumVGPRs(STM.hasGFX90AInsts(), NumAgpr, NumVgpr);
564 uint64_t NumVGPRsForWavesPerEU =
565 std::max({TotalNumVgpr, (uint64_t)1,
567 MaxWaves, MFI.getDynamicVGPRBlockSize())});
568 uint64_t NumSGPRsForWavesPerEU = std::max(
569 {NumSgpr, (uint64_t)1, (uint64_t)STM.getMinNumSGPRs(MaxWaves)});
570 const MCExpr *OccupancyExpr = createOccupancy(
571 STM.getOccupancyWithWorkGroupSizes(*MF).second,
572 MCConstantExpr::create(NumSGPRsForWavesPerEU, OutContext),
573 MCConstantExpr::create(NumVGPRsForWavesPerEU, OutContext),
575 uint64_t Occupancy;
576
577 const auto [MinWEU, MaxWEU] = AMDGPU::getIntegerPairAttribute(
578 F, "amdgpu-waves-per-eu", {0, 0}, true);
579
580 if (TryGetMCExprValue(OccupancyExpr, Occupancy) && Occupancy < MinWEU) {
581 DiagnosticInfoOptimizationFailure Diag(
582 F, F.getSubprogram(),
583 "failed to meet occupancy target given by 'amdgpu-waves-per-eu' in "
584 "'" +
585 F.getName() + "': desired occupancy was " + Twine(MinWEU) +
586 ", final occupancy is " + Twine(Occupancy));
587 F.getContext().diagnose(Diag);
588 return;
589 }
590 }
591 }
592}
593
594static void appendTypeEncoding(std::string &Enc, Type *Ty, const DataLayout &DL,
595 bool IsReturnType) {
596 if (Ty->isVoidTy()) {
597 Enc += 'v';
598 return;
599 }
600 unsigned Bits = DL.getTypeSizeInBits(Ty);
601 // Zero-sized non-void types (e.g. `{}` or `[0 x i8]`) consume no ABI
602 // registers. For returns, emit the same no-result marker as void so the
603 // parameter encoding still has an explicit return-type prefix.
604 if (Bits == 0) {
605 if (IsReturnType)
606 Enc += 'v';
607 return;
608 }
609 if (Bits <= 32)
610 Enc += 'i';
611 else if (Bits <= 64)
612 Enc += 'l';
613 else
614 Enc.append(divideCeil(Bits, 32), 'i');
615}
616
617static std::string computeTypeId(const FunctionType *FTy,
618 const DataLayout &DL) {
619 std::string Enc;
620 appendTypeEncoding(Enc, FTy->getReturnType(), DL, /*IsReturnType=*/true);
621 for (Type *ParamTy : FTy->params())
622 appendTypeEncoding(Enc, ParamTy, DL, /*IsReturnType=*/false);
623 return Enc;
624}
625
626void AMDGPUAsmPrinter::collectCallEdge(const MachineInstr &MI) {
628 return;
629 const SIInstrInfo *TII = MF->getSubtarget<GCNSubtarget>().getInstrInfo();
630 const MachineOperand *Callee =
631 TII->getNamedOperand(MI, AMDGPU::OpName::callee);
632 if (!Callee || !Callee->isGlobal())
633 return;
634 DirectCallEdges.insert(
635 {getSymbol(&MF->getFunction()), getSymbol(Callee->getGlobal())});
636}
637
638void AMDGPUAsmPrinter::emitAMDGPUInfo(Module &M) {
640 return;
641
642 const NamedMDNode *LDSMD = M.getNamedMetadata("amdgpu.lds.uses");
643 bool HasLDSUses = LDSMD && LDSMD->getNumOperands() > 0;
644
645 const NamedMDNode *BarMD = M.getNamedMetadata("amdgpu.named_barrier.uses");
646 bool HasNamedBarriers = BarMD && BarMD->getNumOperands() > 0;
647
648 // Collect address-taken functions (with type IDs) and indirect call sites.
649 DenseMap<const Function *, std::string> AddrTakenTypeIds;
650 using IndirectCallInfo = std::pair<const Function *, std::string>;
652
653 for (const Function &F : M) {
654 bool IsKernel = AMDGPU::isKernel(F.getCallingConv());
655
656 if (!IsKernel && F.hasAddressTaken(/*PutOffender=*/nullptr,
657 /*IgnoreCallbackUses=*/false,
658 /*IgnoreAssumeLikeCalls=*/true,
659 /*IgnoreLLVMUsed=*/true)) {
660 AddrTakenTypeIds[&F] =
661 computeTypeId(F.getFunctionType(), M.getDataLayout());
662 }
663
664 if (F.isDeclaration())
665 continue;
666
667 StringSet<> SeenTypeIds;
668 for (const BasicBlock &BB : F) {
669 for (const Instruction &I : BB) {
670 const auto *CB = dyn_cast<CallBase>(&I);
671 if (!CB || !CB->isIndirectCall())
672 continue;
673 std::string TId =
674 computeTypeId(CB->getFunctionType(), M.getDataLayout());
675 if (SeenTypeIds.insert(TId).second)
676 IndirectCalls.push_back({&F, std::move(TId)});
677 }
678 }
679 }
680
681 if (FunctionInfos.empty() && DirectCallEdges.empty() && !HasLDSUses &&
682 !HasNamedBarriers && AddrTakenTypeIds.empty() && IndirectCalls.empty())
683 return;
684
685 AMDGPU::InfoSectionData Data;
686 Data.Funcs = std::move(FunctionInfos);
687
688 for (auto &[F, TypeId] : AddrTakenTypeIds) {
689 MCSymbol *Sym = getSymbol(F);
690 Data.TypeIds.push_back({Sym, TypeId});
691 }
692
693 for (auto &[CallerSym, CalleeSym] : DirectCallEdges)
694 Data.Calls.push_back({CallerSym, CalleeSym});
695 DirectCallEdges.clear();
696
697 if (HasLDSUses) {
698 for (const MDNode *N : LDSMD->operands()) {
699 auto *Func = mdconst::extract<Function>(N->getOperand(0));
700 auto *LdsVar = mdconst::extract<GlobalVariable>(N->getOperand(1));
701 Data.Uses.push_back({getSymbol(Func), getSymbol(LdsVar)});
702 }
703 }
704
705 if (HasNamedBarriers) {
706 for (const MDNode *N : BarMD->operands()) {
707 auto *BarVar = mdconst::extract<GlobalVariable>(N->getOperand(0));
708 MCSymbol *BarSym = getSymbol(BarVar);
709 for (unsigned I = 1, E = N->getNumOperands(); I < E; ++I) {
710 auto *Func = mdconst::extract<Function>(N->getOperand(I));
711 Data.Uses.push_back({getSymbol(Func), BarSym});
712 }
713 }
714 }
715
716 for (auto &[Caller, Enc] : IndirectCalls) {
717 MCSymbol *CallerSym = getSymbol(Caller);
718 Data.IndirectCalls.push_back({CallerSym, Enc});
719 }
720
722}
723
725 const Triple &TT = M.getTargetTriple();
726
727 // Pad with s_code_end to help tools and guard against instruction prefetch
728 // causing stale data in caches. Arguably this should be done by the linker,
729 // which is why this isn't done for Mesa.
730 // Don't do it if there is no code.
731 const MCSubtargetInfo &STI = *getGlobalSTI();
732 if ((AMDGPU::isGFX10Plus(STI) || AMDGPU::isGFX90A(STI)) &&
733 (TT.getOS() == Triple::AMDHSA || TT.getOS() == Triple::AMDPAL)) {
735 if (TextSect->hasInstructions()) {
736 OutStreamer->switchSection(TextSect);
738 }
739 }
740
741 // Emit the unified .amdgpu.info section (per-function resources, call graph,
742 // LDS/named-barrier use edges, indirect calls, and address-taken type IDs).
743 emitAMDGPUInfo(M);
744
745 // Assign expressions which can only be resolved when all other functions are
746 // known.
747 RI.finalize(OutContext);
748
749 // Switch section and emit all GPR maximums within the processed module.
750 OutStreamer->pushSection();
751 MCSectionELF *MaxGPRSection =
752 OutContext.getELFSection(".AMDGPU.gpr_maximums", ELF::SHT_PROGBITS, 0);
753 OutStreamer->switchSection(MaxGPRSection);
755 RI.getMaxVGPRSymbol(OutContext), RI.getMaxAGPRSymbol(OutContext),
756 RI.getMaxSGPRSymbol(OutContext), RI.getMaxNamedBarrierSymbol(OutContext));
757 OutStreamer->popSection();
758
759 // In the object-linking pipeline per-function resource MCExprs reference
760 // external callee symbols that cannot be evaluated here, so cross-TU limit
761 // checks would silently no-op for every non-leaf function. Defer resource
762 // sanity checking to the linker, which re-validates against the aggregated
763 // call graph in the combined .amdgpu.info metadata.
765 for (Function &F : M.functions())
766 validateMCResourceInfo(F);
767 }
768
769 RI.reset();
770
772}
773
774SmallString<128> AMDGPUAsmPrinter::getMCExprStr(const MCExpr *Value) {
776 raw_svector_ostream OSS(Str);
778 auto &Context = Streamer.getContext();
779 const MCExpr *New = foldAMDGPUMCExpr(Value, Context);
780 printAMDGPUMCExpr(New, OSS, &MAI);
781 return Str;
782}
783
784// Print comments that apply to both callable functions and entry points.
785void AMDGPUAsmPrinter::emitCommonFunctionComments(
786 const MCExpr *NumVGPR, const MCExpr *NumAGPR, const MCExpr *TotalNumVGPR,
787 const MCExpr *NumSGPR, const MCExpr *ScratchSize, uint64_t CodeSize,
788 const AMDGPUMachineFunctionInfo *MFI) {
789 OutStreamer->emitRawComment(" codeLenInByte = " + Twine(CodeSize), false);
790 OutStreamer->emitRawComment(" TotalNumSgprs: " + getMCExprStr(NumSGPR),
791 false);
792 OutStreamer->emitRawComment(" NumVgprs: " + getMCExprStr(NumVGPR), false);
793 if (NumAGPR && TotalNumVGPR) {
794 OutStreamer->emitRawComment(" NumAgprs: " + getMCExprStr(NumAGPR), false);
795 OutStreamer->emitRawComment(" TotalNumVgprs: " + getMCExprStr(TotalNumVGPR),
796 false);
797 }
798 OutStreamer->emitRawComment(" ScratchSize: " + getMCExprStr(ScratchSize),
799 false);
800 OutStreamer->emitRawComment(" MemoryBound: " + Twine(MFI->isMemoryBound()),
801 false);
802}
803
804const MCExpr *AMDGPUAsmPrinter::getAmdhsaKernelCodeProperties(
805 const MachineFunction &MF) const {
806 const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
807 MCContext &Ctx = MF.getContext();
808 uint16_t KernelCodeProperties = 0;
809 const GCNUserSGPRUsageInfo &UserSGPRInfo = MFI.getUserSGPRInfo();
810
811 if (UserSGPRInfo.hasPrivateSegmentBuffer()) {
812 KernelCodeProperties |=
813 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER;
814 }
815 if (UserSGPRInfo.hasDispatchPtr()) {
816 KernelCodeProperties |=
817 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR;
818 }
819 if (UserSGPRInfo.hasQueuePtr()) {
820 KernelCodeProperties |= amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR;
821 }
822 if (UserSGPRInfo.hasKernargSegmentPtr()) {
823 KernelCodeProperties |=
824 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR;
825 }
826 if (UserSGPRInfo.hasDispatchID()) {
827 KernelCodeProperties |=
828 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID;
829 }
830 if (UserSGPRInfo.hasFlatScratchInit()) {
831 KernelCodeProperties |=
832 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT;
833 }
834 if (UserSGPRInfo.hasPrivateSegmentSize()) {
835 KernelCodeProperties |=
836 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE;
837 }
838 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
839 if (STM.isWave32() &&
840 STM.getFeatureBits().test(AMDGPU::FeatureSupportsWave32) &&
841 STM.getFeatureBits().test(AMDGPU::FeatureSupportsWave64)) {
842 KernelCodeProperties |=
843 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32;
844 }
845
846 // CurrentProgramInfo.DynamicCallStack is a MCExpr and could be
847 // un-evaluatable at this point so it cannot be conditionally checked here.
848 // Instead, we'll directly shift the possibly unknown MCExpr into its place
849 // and bitwise-or it into KernelCodeProperties.
850 const MCExpr *KernelCodePropExpr =
851 MCConstantExpr::create(KernelCodeProperties, Ctx);
852 const MCExpr *OrValue = MCConstantExpr::create(
853 amdhsa::KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK_SHIFT, Ctx);
854 OrValue = MCBinaryExpr::createShl(CurrentProgramInfo.DynamicCallStack,
855 OrValue, Ctx);
856 KernelCodePropExpr = MCBinaryExpr::createOr(KernelCodePropExpr, OrValue, Ctx);
857
858 return KernelCodePropExpr;
859}
860
861MCKernelDescriptor
862AMDGPUAsmPrinter::getAmdhsaKernelDescriptor(const MachineFunction &MF,
863 const SIProgramInfo &PI) const {
864 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
865 const Function &F = MF.getFunction();
866 const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
867 MCContext &Ctx = MF.getContext();
868
869 MCKernelDescriptor KernelDescriptor;
870
871 KernelDescriptor.group_segment_fixed_size =
873 KernelDescriptor.private_segment_fixed_size = PI.ScratchSize;
874
875 Align MaxKernArgAlign;
876 KernelDescriptor.kernarg_size = MCConstantExpr::create(
877 STM.getKernArgSegmentSize(F, MaxKernArgAlign), Ctx);
878
879 KernelDescriptor.compute_pgm_rsrc1 = PI.getComputePGMRSrc1(STM, Ctx);
880 KernelDescriptor.compute_pgm_rsrc2 = PI.getComputePGMRSrc2(STM, Ctx);
881 KernelDescriptor.kernel_code_properties = getAmdhsaKernelCodeProperties(MF);
882
883 int64_t PGM_Rsrc3 = 1;
884 bool EvaluatableRsrc3 =
885 CurrentProgramInfo.ComputePGMRSrc3->evaluateAsAbsolute(PGM_Rsrc3);
886 (void)PGM_Rsrc3;
887 (void)EvaluatableRsrc3;
889 STM.hasGFX90AInsts() || STM.hasGFX1250Insts() || !EvaluatableRsrc3 ||
890 static_cast<uint64_t>(PGM_Rsrc3) == 0);
891 KernelDescriptor.compute_pgm_rsrc3 = CurrentProgramInfo.ComputePGMRSrc3;
892
893 KernelDescriptor.kernarg_preload = MCConstantExpr::create(
894 AMDGPU::hasKernargPreload(STM) ? Info->getNumKernargPreloadedSGPRs() : 0,
895 Ctx);
896
897 return KernelDescriptor;
898}
899
901 // Init target streamer lazily on the first function so that previous passes
902 // can set metadata.
904 initTargetStreamer(*MF.getFunction().getParent());
905
906 ResourceUsage = GetResourceUsage(MF);
907 CurrentProgramInfo.reset(MF);
908
909 const AMDGPUMachineFunctionInfo *MFI =
910 MF.getInfo<AMDGPUMachineFunctionInfo>();
911 MCContext &Ctx = MF.getContext();
912
913 // The starting address of all shader programs must be 256 bytes aligned.
914 // Regular functions just need the basic required instruction alignment.
915 MF.ensureAlignment(MFI->isEntryFunction() ? Align(256) : Align(4));
916
918
919 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
921 // FIXME: This should be an explicit check for Mesa.
922 if (!STM.isAmdHsaOS() && !STM.isAmdPalOS()) {
923 MCSectionELF *ConfigSection =
924 Context.getELFSection(".AMDGPU.config", ELF::SHT_PROGBITS, 0);
925 OutStreamer->switchSection(ConfigSection);
926 }
927
928 RI.gatherResourceInfo(MF, *ResourceUsage, OutContext);
929
932 *ResourceUsage;
933 FunctionInfos.push_back(
934 {/*NumSGPR=*/static_cast<uint32_t>(RU.NumExplicitSGPR),
935 /*NumArchVGPR=*/static_cast<uint32_t>(RU.NumVGPR),
936 /*NumAccVGPR=*/static_cast<uint32_t>(RU.NumAGPR),
937 /*PrivateSegmentSize=*/static_cast<uint32_t>(RU.PrivateSegmentSize),
938 /*UsesVCC=*/RU.UsesVCC,
939 /*UsesFlatScratch=*/RU.UsesFlatScratch,
940 /*HasDynStack=*/RU.HasDynamicallySizedStack,
941 /*Sym=*/getSymbol(&MF.getFunction())});
942 }
943
944 if (MFI->isModuleEntryFunction()) {
945 getSIProgramInfo(CurrentProgramInfo, MF);
946 }
947
948 if (STM.isAmdPalOS()) {
949 if (MFI->isEntryFunction())
950 EmitPALMetadata(MF, CurrentProgramInfo);
951 else if (MFI->isModuleEntryFunction())
952 emitPALFunctionMetadata(MF);
953 } else if (!STM.isAmdHsaOS()) {
954 EmitProgramInfoSI(MF, CurrentProgramInfo);
955 }
956
957 DumpCodeInstEmitter = nullptr;
958 if (STM.dumpCode()) {
959 // For -dumpcode, get the assembler out of the streamer. This only works
960 // with -filetype=obj.
961 MCAssembler *Assembler = OutStreamer->getAssemblerPtr();
962 if (Assembler)
963 DumpCodeInstEmitter = Assembler->getEmitterPtr();
964 }
965
966 DisasmLines.clear();
967 HexLines.clear();
969
971
972 emitResourceUsageRemarks(MF, CurrentProgramInfo, MFI->isModuleEntryFunction(),
973 STM.hasMAIInsts());
974
975 {
978 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_NumVGPR, OutContext),
979 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_NumAGPR, OutContext),
980 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_NumSGPR, OutContext),
981 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_NumNamedBarrier,
982 OutContext),
983 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_PrivateSegSize,
984 OutContext),
985 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_UsesVCC, OutContext),
986 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_UsesFlatScratch,
987 OutContext),
988 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_HasDynSizedStack,
989 OutContext),
990 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_HasRecursion,
991 OutContext),
992 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_HasIndirectCall,
993 OutContext));
994 }
995
996 // Emit _dvgpr$ symbol when appropriate.
997 emitDVgprSymbol(MF);
998
999 if (isVerbose()) {
1000 MCSectionELF *CommentSection =
1001 Context.getELFSection(".AMDGPU.csdata", ELF::SHT_PROGBITS, 0);
1002 OutStreamer->switchSection(CommentSection);
1003
1004 if (!MFI->isEntryFunction()) {
1006 OutStreamer->emitRawComment(" Function info:", false);
1007
1008 emitCommonFunctionComments(
1009 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_NumVGPR, OutContext)
1010 ->getVariableValue(),
1011 STM.hasMAIInsts() ? RI.getSymbol(CurrentFnSym->getName(),
1012 RIK::RIK_NumAGPR, OutContext)
1013 ->getVariableValue()
1014 : nullptr,
1015 RI.createTotalNumVGPRs(MF, Ctx),
1016 RI.createTotalNumSGPRs(
1017 MF,
1018 MF.getSubtarget<GCNSubtarget>().getTargetID().isXnackOnOrAny(),
1019 Ctx),
1020 RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_PrivateSegSize,
1021 OutContext)
1022 ->getVariableValue(),
1023 CurrentProgramInfo.getFunctionCodeSize(MF), MFI);
1024 return false;
1025 }
1026
1027 OutStreamer->emitRawComment(" Kernel info:", false);
1028 emitCommonFunctionComments(
1029 CurrentProgramInfo.NumArchVGPR,
1030 STM.hasMAIInsts() ? CurrentProgramInfo.NumAccVGPR : nullptr,
1031 CurrentProgramInfo.NumVGPR, CurrentProgramInfo.NumSGPR,
1032 CurrentProgramInfo.ScratchSize,
1033 CurrentProgramInfo.getFunctionCodeSize(MF), MFI);
1034
1035 OutStreamer->emitRawComment(
1036 " FloatMode: " + Twine(CurrentProgramInfo.FloatMode), false);
1037 OutStreamer->emitRawComment(
1038 " IeeeMode: " + Twine(CurrentProgramInfo.IEEEMode), false);
1039 OutStreamer->emitRawComment(
1040 " LDSByteSize: " + Twine(CurrentProgramInfo.LDSSize) +
1041 " bytes/workgroup (compile time only)",
1042 false);
1043
1044 OutStreamer->emitRawComment(
1045 " SGPRBlocks: " + getMCExprStr(CurrentProgramInfo.SGPRBlocks), false);
1046
1047 OutStreamer->emitRawComment(
1048 " VGPRBlocks: " + getMCExprStr(CurrentProgramInfo.VGPRBlocks), false);
1049
1050 OutStreamer->emitRawComment(
1051 " NumSGPRsForWavesPerEU: " +
1052 getMCExprStr(CurrentProgramInfo.NumSGPRsForWavesPerEU),
1053 false);
1054 OutStreamer->emitRawComment(
1055 " NumVGPRsForWavesPerEU: " +
1056 getMCExprStr(CurrentProgramInfo.NumVGPRsForWavesPerEU),
1057 false);
1058
1059 if (STM.hasGFX90AInsts()) {
1060 const MCExpr *AdjustedAccum = MCBinaryExpr::createAdd(
1061 CurrentProgramInfo.AccumOffset, MCConstantExpr::create(1, Ctx), Ctx);
1062 AdjustedAccum = MCBinaryExpr::createMul(
1063 AdjustedAccum, MCConstantExpr::create(4, Ctx), Ctx);
1064 OutStreamer->emitRawComment(
1065 " AccumOffset: " + getMCExprStr(AdjustedAccum), false);
1066 }
1067
1068 if (STM.hasGFX1250Insts())
1069 OutStreamer->emitRawComment(
1070 " NamedBarCnt: " + getMCExprStr(CurrentProgramInfo.NamedBarCnt),
1071 false);
1072
1073 OutStreamer->emitRawComment(
1074 " Occupancy: " + getMCExprStr(CurrentProgramInfo.Occupancy), false);
1075
1076 OutStreamer->emitRawComment(
1077 " WaveLimiterHint : " + Twine(MFI->needsWaveLimiter()), false);
1078
1079 OutStreamer->emitRawComment(
1080 " COMPUTE_PGM_RSRC2:SCRATCH_EN: " +
1081 getMCExprStr(CurrentProgramInfo.ScratchEnable),
1082 false);
1083 OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:USER_SGPR: " +
1084 Twine(CurrentProgramInfo.UserSGPR),
1085 false);
1086 OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TRAP_HANDLER: " +
1087 Twine(CurrentProgramInfo.TrapHandlerEnable),
1088 false);
1089 OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TGID_X_EN: " +
1090 Twine(CurrentProgramInfo.TGIdXEnable),
1091 false);
1092 OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TGID_Y_EN: " +
1093 Twine(CurrentProgramInfo.TGIdYEnable),
1094 false);
1095 OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TGID_Z_EN: " +
1096 Twine(CurrentProgramInfo.TGIdZEnable),
1097 false);
1098 OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TIDIG_COMP_CNT: " +
1099 Twine(CurrentProgramInfo.TIdIGCompCount),
1100 false);
1101
1102 [[maybe_unused]] int64_t PGMRSrc3;
1104 STM.hasGFX90AInsts() || STM.hasGFX1250Insts() ||
1105 (CurrentProgramInfo.ComputePGMRSrc3->evaluateAsAbsolute(PGMRSrc3) &&
1106 static_cast<uint64_t>(PGMRSrc3) == 0));
1107 if (STM.hasGFX90AInsts()) {
1108 OutStreamer->emitRawComment(
1109 " COMPUTE_PGM_RSRC3_GFX90A:ACCUM_OFFSET: " +
1110 getMCExprStr(MCKernelDescriptor::bits_get(
1111 CurrentProgramInfo.ComputePGMRSrc3,
1112 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET_SHIFT,
1113 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET, Ctx)),
1114 false);
1115 OutStreamer->emitRawComment(
1116 " COMPUTE_PGM_RSRC3_GFX90A:TG_SPLIT: " +
1117 getMCExprStr(MCKernelDescriptor::bits_get(
1118 CurrentProgramInfo.ComputePGMRSrc3,
1119 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT_SHIFT,
1120 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT, Ctx)),
1121 false);
1122 }
1123 }
1124
1125 if (DumpCodeInstEmitter) {
1126
1127 OutStreamer->switchSection(
1128 Context.getELFSection(".AMDGPU.disasm", ELF::SHT_PROGBITS, 0));
1129
1130 for (size_t i = 0; i < DisasmLines.size(); ++i) {
1131 std::string Comment = "\n";
1132 if (!HexLines[i].empty()) {
1133 Comment = std::string(DisasmLineMaxLen - DisasmLines[i].size(), ' ');
1134 Comment += " ; " + HexLines[i] + "\n";
1135 }
1136
1137 OutStreamer->emitBytes(StringRef(DisasmLines[i]));
1138 OutStreamer->emitBytes(StringRef(Comment));
1139 }
1140 }
1141
1142 return false;
1143}
1144
1145// When appropriate, add a _dvgpr$ symbol, with the value of the function
1146// symbol, plus an offset encoding one less than the number of VGPR blocks used
1147// by the function in bits 5..3 of the symbol value. A "VGPR block" can be
1148// either 16 VGPRs (for a max of 128), or 32 VGPRs (for a max of 256). This is
1149// used by a front-end to have functions that are chained rather than called,
1150// and a dispatcher that dynamically resizes the VGPR count before dispatching
1151// to a function.
1152void AMDGPUAsmPrinter::emitDVgprSymbol(MachineFunction &MF) {
1154 if (MFI.isDynamicVGPREnabled() &&
1156 MCContext &Ctx = MF.getContext();
1157 unsigned BlockSize = MFI.getDynamicVGPRBlockSize();
1158
1159 const MCExpr *EncodedBlocks;
1160 MCValue NumVGPRs;
1161 if (CurrentProgramInfo.NumVGPRsForWavesPerEU->evaluateAsRelocatable(
1162 NumVGPRs, nullptr) &&
1163 NumVGPRs.isAbsolute()) {
1164
1165 // Calculate number of VGPR blocks.
1166 // Treat 0 VGPRs as 1 VGPR to avoid underflowing.
1167 unsigned NumBlocks =
1168 divideCeil(std::max(unsigned(NumVGPRs.getConstant()), 1U), BlockSize);
1169
1170 if (NumBlocks > AMDGPU::IsaInfo::MaxDynamicVGPRBlocks) {
1172 {}, "DVGPR block count " + Twine(NumBlocks) +
1173 " exceeds maximum of " +
1175 " for __dvgpr$ symbol for '" +
1176 Twine(CurrentFnSym->getName()) + "'");
1177 return;
1178 }
1179 unsigned EncodedNumBlocks = (NumBlocks - 1) << 3;
1180 EncodedBlocks = MCConstantExpr::create(EncodedNumBlocks, Ctx);
1181 } else {
1182 // Value not yet available so build a symbolic MCExpr:
1183 // ((alignTo(max(NumVGPRs, 1), BlockSize) / BlockSize - 1) << 3
1184 const MCExpr *One = MCConstantExpr::create(1, Ctx);
1185 const MCExpr *BlockSizeConst = MCConstantExpr::create(BlockSize, Ctx);
1186 const MCExpr *MaxVGPRs = AMDGPUMCExpr::createMax(
1187 {CurrentProgramInfo.NumVGPRsForWavesPerEU, One}, Ctx);
1188 const MCExpr *NumBlocks = MCBinaryExpr::createDiv(
1189 AMDGPUMCExpr::createAlignTo(MaxVGPRs, BlockSizeConst, Ctx),
1190 BlockSizeConst, Ctx);
1191 EncodedBlocks =
1193 MCConstantExpr::create(3, Ctx), Ctx);
1194 }
1195
1196 // Add to function symbol to create _dvgpr$ symbol.
1197 const MCExpr *DVgprFuncVal = MCBinaryExpr::createAdd(
1198 MCSymbolRefExpr::create(CurrentFnSym, Ctx), EncodedBlocks, Ctx);
1199 MCSymbol *DVgprFuncSym =
1200 Ctx.getOrCreateSymbol(Twine("_dvgpr$") + CurrentFnSym->getName());
1201 OutStreamer->emitAssignment(DVgprFuncSym, DVgprFuncVal);
1202 emitVisibility(DVgprFuncSym, MF.getFunction().getVisibility());
1203 emitLinkage(&MF.getFunction(), DVgprFuncSym);
1204 }
1205}
1206
1207// TODO: Fold this into emitFunctionBodyStart.
1208void AMDGPUAsmPrinter::initializeTargetID(const Module &M) {
1210
1211 auto &TSTargetID = getTargetStreamer()->getTargetID();
1212
1213 // Error if -mattr specified xnack or sramecc.
1214 // TODO: Remove this when subtarget features removed.
1215 StringRef FeatureString = getGlobalSTI()->getFeatureString();
1216 if (FeatureString.contains("xnack")) {
1217 M.getContext().diagnose(DiagnosticInfoGeneric(
1218 "xnack/sramecc should be specified via module flags. "
1219 "Use module flag 'amdgpu.xnack' instead of subtarget feature",
1220 DS_Error));
1221 }
1222 if (FeatureString.contains("sramecc")) {
1223 M.getContext().diagnose(DiagnosticInfoGeneric(
1224 "xnack/sramecc should be specified via module flags. "
1225 "Use module flag 'amdgpu.sramecc' instead of subtarget feature",
1226 DS_Error));
1227 }
1228
1229 // Apply xnack/sramecc settings from module flags.
1230 if (getGlobalSTI()->getFeatureBits().test(AMDGPU::FeatureXNACKOnOffModes)) {
1231 AMDGPU::TargetIDSetting Setting =
1233 if (Setting != AMDGPU::TargetIDSetting::Any)
1234 TSTargetID->setXnackSetting(Setting);
1235 }
1236
1237 if (getGlobalSTI()->getFeatureBits().test(AMDGPU::FeatureSRAMECCOnOffModes)) {
1238 AMDGPU::TargetIDSetting Setting =
1240 if (Setting != AMDGPU::TargetIDSetting::Any)
1241 TSTargetID->setSramEccSetting(Setting);
1242 }
1243}
1244
1245// AccumOffset computed for the MCExpr equivalent of:
1246// alignTo(std::max(1, NumVGPR), 4) / 4 - 1;
1247static const MCExpr *computeAccumOffset(const MCExpr *NumVGPR, MCContext &Ctx) {
1248 const MCExpr *ConstFour = MCConstantExpr::create(4, Ctx);
1249 const MCExpr *ConstOne = MCConstantExpr::create(1, Ctx);
1250
1251 // Can't be lower than 1 for subsequent alignTo.
1252 const MCExpr *MaximumTaken =
1253 AMDGPUMCExpr::createMax({ConstOne, NumVGPR}, Ctx);
1254
1255 // Practically, it's computing divideCeil(MaximumTaken, 4).
1256 const MCExpr *DivCeil = MCBinaryExpr::createDiv(
1257 AMDGPUMCExpr::createAlignTo(MaximumTaken, ConstFour, Ctx), ConstFour,
1258 Ctx);
1259
1260 return MCBinaryExpr::createSub(DivCeil, ConstOne, Ctx);
1261}
1262
1263static unsigned getLDSEncodingGranule(const GCNSubtarget &ST) {
1264 unsigned Granule =
1265 AMDGPU::getLDSEncodingGranule(ST.getTargetID().getGPUKind());
1266 // The legacy generic targets have no encoding granularity feature. Preserve
1267 // the default used for code generation when no GPU is specified.
1268 return Granule ? Granule : 256;
1269}
1270
1271void AMDGPUAsmPrinter::getSIProgramInfo(SIProgramInfo &ProgInfo,
1272 const MachineFunction &MF) {
1273 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
1274 MCContext &Ctx = MF.getContext();
1275
1276 auto CreateExpr = [&Ctx](int64_t Value) {
1277 return MCConstantExpr::create(Value, Ctx);
1278 };
1279
1280 auto TryGetMCExprValue = [](const MCExpr *Value, uint64_t &Res) -> bool {
1281 int64_t Val;
1282 if (Value->evaluateAsAbsolute(Val)) {
1283 Res = Val;
1284 return true;
1285 }
1286 return false;
1287 };
1288
1289 auto GetSymRefExpr =
1290 [&](MCResourceInfo::ResourceInfoKind RIK) -> const MCExpr * {
1291 MCSymbol *Sym = RI.getSymbol(CurrentFnSym->getName(), RIK, OutContext);
1292 return MCSymbolRefExpr::create(Sym, Ctx);
1293 };
1294
1296 ProgInfo.NumArchVGPR = GetSymRefExpr(RIK::RIK_NumVGPR);
1297 ProgInfo.NumAccVGPR = GetSymRefExpr(RIK::RIK_NumAGPR);
1299 ProgInfo.NumAccVGPR, ProgInfo.NumArchVGPR, Ctx);
1300
1301 ProgInfo.AccumOffset = computeAccumOffset(ProgInfo.NumArchVGPR, Ctx);
1302 ProgInfo.TgSplit =
1303 STM.hasTgSplitSupport() && AMDGPU::isTgSplitEnabled(MF.getFunction());
1304 ProgInfo.NumSGPR = GetSymRefExpr(RIK::RIK_NumSGPR);
1305 ProgInfo.ScratchSize = GetSymRefExpr(RIK::RIK_PrivateSegSize);
1306 ProgInfo.VCCUsed = GetSymRefExpr(RIK::RIK_UsesVCC);
1307 ProgInfo.FlatUsed = GetSymRefExpr(RIK::RIK_UsesFlatScratch);
1308 ProgInfo.DynamicCallStack =
1309 MCBinaryExpr::createOr(GetSymRefExpr(RIK::RIK_HasDynSizedStack),
1310 GetSymRefExpr(RIK::RIK_HasRecursion), Ctx);
1311
1312 const MCExpr *BarBlkConst = MCConstantExpr::create(4, Ctx);
1313 const MCExpr *AlignToBlk = AMDGPUMCExpr::createAlignTo(
1314 GetSymRefExpr(RIK::RIK_NumNamedBarrier), BarBlkConst, Ctx);
1315 ProgInfo.NamedBarCnt = MCBinaryExpr::createDiv(AlignToBlk, BarBlkConst, Ctx);
1316
1317 const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1318
1319 // The calculations related to SGPR/VGPR blocks are
1320 // duplicated in part in AMDGPUAsmParser::calculateGPRBlocks, and could be
1321 // unified.
1322 const MCExpr *ExtraSGPRs = AMDGPUMCExpr::createExtraSGPRs(
1323 ProgInfo.VCCUsed, ProgInfo.FlatUsed,
1324 getTargetStreamer()->getTargetID()->isXnackOnOrAny(), Ctx);
1325
1326 // Check the addressable register limit before we add ExtraSGPRs.
1328 !STM.hasSGPRInitBug()) {
1329 unsigned MaxAddressableNumSGPRs = STM.getAddressableNumSGPRs();
1330 uint64_t NumSgpr;
1331 if (TryGetMCExprValue(ProgInfo.NumSGPR, NumSgpr) &&
1332 NumSgpr > MaxAddressableNumSGPRs) {
1333 // This can happen due to a compiler bug or when using inline asm.
1334 LLVMContext &Ctx = MF.getFunction().getContext();
1335 Ctx.diagnose(DiagnosticInfoResourceLimit(
1336 MF.getFunction(), "addressable scalar registers", NumSgpr,
1337 MaxAddressableNumSGPRs, DS_Error, DK_ResourceLimit));
1338 ProgInfo.NumSGPR = CreateExpr(MaxAddressableNumSGPRs - 1);
1339 }
1340 }
1341
1342 // Account for extra SGPRs and VGPRs reserved for debugger use.
1343 ProgInfo.NumSGPR = MCBinaryExpr::createAdd(ProgInfo.NumSGPR, ExtraSGPRs, Ctx);
1344
1345 const Function &F = MF.getFunction();
1346
1347 // Ensure there are enough SGPRs and VGPRs for wave dispatch, where wave
1348 // dispatch registers as function args.
1349 unsigned WaveDispatchNumSGPR = MFI->getNumWaveDispatchSGPRs(),
1350 WaveDispatchNumVGPR = MFI->getNumWaveDispatchVGPRs();
1351
1352 if (WaveDispatchNumSGPR) {
1354 {ProgInfo.NumSGPR,
1355 MCBinaryExpr::createAdd(CreateExpr(WaveDispatchNumSGPR), ExtraSGPRs,
1356 Ctx)},
1357 Ctx);
1358 }
1359
1360 if (WaveDispatchNumVGPR) {
1362 {ProgInfo.NumArchVGPR, CreateExpr(WaveDispatchNumVGPR)}, Ctx);
1363
1365 ProgInfo.NumAccVGPR, ProgInfo.NumArchVGPR, Ctx);
1366 }
1367
1368 // Adjust number of registers used to meet default/requested minimum/maximum
1369 // number of waves per execution unit request.
1370 unsigned MaxWaves = MFI->getMaxWavesPerEU();
1371 ProgInfo.NumSGPRsForWavesPerEU =
1372 AMDGPUMCExpr::createMax({ProgInfo.NumSGPR, CreateExpr(1ul),
1373 CreateExpr(STM.getMinNumSGPRs(MaxWaves))},
1374 Ctx);
1375 ProgInfo.NumVGPRsForWavesPerEU =
1376 AMDGPUMCExpr::createMax({ProgInfo.NumVGPR, CreateExpr(1ul),
1377 CreateExpr(STM.getMinNumVGPRs(
1378 MaxWaves, MFI->getDynamicVGPRBlockSize()))},
1379 Ctx);
1380
1382 STM.hasSGPRInitBug()) {
1383 unsigned MaxAddressableNumSGPRs = STM.getAddressableNumSGPRs();
1384 uint64_t NumSgpr;
1385 if (TryGetMCExprValue(ProgInfo.NumSGPR, NumSgpr) &&
1386 NumSgpr > MaxAddressableNumSGPRs) {
1387 // This can happen due to a compiler bug or when using inline asm to use
1388 // the registers which are usually reserved for vcc etc.
1389 LLVMContext &Ctx = MF.getFunction().getContext();
1390 Ctx.diagnose(DiagnosticInfoResourceLimit(
1391 MF.getFunction(), "scalar registers", NumSgpr, MaxAddressableNumSGPRs,
1393 ProgInfo.NumSGPR = CreateExpr(MaxAddressableNumSGPRs);
1394 ProgInfo.NumSGPRsForWavesPerEU = CreateExpr(MaxAddressableNumSGPRs);
1395 }
1396 }
1397
1398 if (STM.hasSGPRInitBug()) {
1399 ProgInfo.NumSGPR =
1401 ProgInfo.NumSGPRsForWavesPerEU =
1403 }
1404
1405 if (MFI->getNumUserSGPRs() > STM.getMaxNumUserSGPRs()) {
1406 LLVMContext &Ctx = MF.getFunction().getContext();
1407 Ctx.diagnose(DiagnosticInfoResourceLimit(
1408 MF.getFunction(), "user SGPRs", MFI->getNumUserSGPRs(),
1410 }
1411
1412 if (MFI->getLDSSize() > STM.getAddressableLocalMemorySize()) {
1413 LLVMContext &Ctx = MF.getFunction().getContext();
1414 Ctx.diagnose(DiagnosticInfoResourceLimit(
1415 MF.getFunction(), "local memory", MFI->getLDSSize(),
1417 }
1418
1419 // When dynamic VGPRs are enabled, entry functions are launched with a single
1420 // VGPR block. The register allocator enforces this constraint, but we also
1421 // need to catch explicit physical registers in inline asm and wave dispatch
1422 // VGPR arguments.
1423 if (MFI->isDynamicVGPREnabled() &&
1424 AMDGPU::isEntryFunctionCC(F.getCallingConv())) {
1425 unsigned BlockSize = MFI->getDynamicVGPRBlockSize();
1426 uint64_t NumVgpr;
1427 if (TryGetMCExprValue(ProgInfo.NumVGPRsForWavesPerEU, NumVgpr) &&
1428 NumVgpr > BlockSize) {
1429 LLVMContext &Ctx = F.getContext();
1430 Ctx.diagnose(DiagnosticInfoResourceLimit(
1431 F, "dynamic VGPR entry point vector registers", NumVgpr, BlockSize,
1433 }
1434 }
1435
1436 // The MCExpr equivalent of getNumSGPRBlocks/getNumVGPRBlocks:
1437 // (alignTo(max(1u, NumGPR), GPREncodingGranule) / GPREncodingGranule) - 1
1438 auto GetNumGPRBlocks = [&CreateExpr, &Ctx](const MCExpr *NumGPR,
1439 unsigned Granule) {
1440 const MCExpr *OneConst = CreateExpr(1ul);
1441 const MCExpr *GranuleConst = CreateExpr(Granule);
1442 const MCExpr *MaxNumGPR = AMDGPUMCExpr::createMax({NumGPR, OneConst}, Ctx);
1443 const MCExpr *AlignToGPR =
1444 AMDGPUMCExpr::createAlignTo(MaxNumGPR, GranuleConst, Ctx);
1445 const MCExpr *DivGPR =
1446 MCBinaryExpr::createDiv(AlignToGPR, GranuleConst, Ctx);
1447 const MCExpr *SubGPR = MCBinaryExpr::createSub(DivGPR, OneConst, Ctx);
1448 return SubGPR;
1449 };
1450 // GFX10+ will always allocate 128 SGPRs and this field must be 0
1452 ProgInfo.SGPRBlocks = CreateExpr(0ul);
1453 } else {
1454 ProgInfo.SGPRBlocks = GetNumGPRBlocks(ProgInfo.NumSGPRsForWavesPerEU,
1456 }
1457 ProgInfo.VGPRBlocks = GetNumGPRBlocks(ProgInfo.NumVGPRsForWavesPerEU,
1459
1460 const SIModeRegisterDefaults Mode = MFI->getMode();
1461
1462 // Set the value to initialize FP_ROUND and FP_DENORM parts of the mode
1463 // register.
1464 ProgInfo.FloatMode = getFPMode(Mode);
1465
1466 ProgInfo.IEEEMode = Mode.IEEE;
1467
1468 // Make clamp modifier on NaN input returns 0.
1469 ProgInfo.DX10Clamp = Mode.DX10Clamp;
1470 ProgInfo.SGPRSpill = MFI->getNumSpilledSGPRs();
1471 ProgInfo.VGPRSpill = MFI->getNumSpilledVGPRs();
1472
1473 ProgInfo.LDSSize = MFI->getLDSSize();
1474
1475 unsigned LDSGranularityBytes = getLDSEncodingGranule(STM);
1476 ProgInfo.LDSBlocks =
1477 alignTo(ProgInfo.LDSSize, LDSGranularityBytes) / LDSGranularityBytes;
1478
1479 // The MCExpr equivalent of divideCeil.
1480 auto DivideCeil = [&Ctx](const MCExpr *Numerator, const MCExpr *Denominator) {
1481 const MCExpr *Ceil =
1482 AMDGPUMCExpr::createAlignTo(Numerator, Denominator, Ctx);
1483 return MCBinaryExpr::createDiv(Ceil, Denominator, Ctx);
1484 };
1485
1486 // Scratch is allocated in 64-dword or 256-dword blocks.
1487 unsigned ScratchAlignShift =
1488 STM.getGeneration() >= AMDGPUSubtarget::GFX11 ? 8 : 10;
1489 // We need to program the hardware with the amount of scratch memory that
1490 // is used by the entire wave. ProgInfo.ScratchSize is the amount of
1491 // scratch memory used per thread.
1492 ProgInfo.ScratchBlocks = DivideCeil(
1494 CreateExpr(STM.getWavefrontSize()), Ctx),
1495 CreateExpr(1ULL << ScratchAlignShift));
1496
1497 if (STM.hasSupportsWGP()) {
1498 ProgInfo.WgpMode = STM.isCuModeEnabled() ? 0 : 1;
1499 }
1500
1501 if (getIsaVersion(getGlobalSTI()->getCPU()).Major >= 10) {
1502 ProgInfo.MemOrdered = 1;
1503 ProgInfo.FwdProgress = !F.hasFnAttribute("amdgpu-no-fwd-progress");
1504 }
1505
1506 // 0 = X, 1 = XY, 2 = XYZ
1507 unsigned TIDIGCompCnt = 0;
1508 if (MFI->hasWorkItemIDZ())
1509 TIDIGCompCnt = 2;
1510 else if (MFI->hasWorkItemIDY())
1511 TIDIGCompCnt = 1;
1512
1513 // The private segment wave byte offset is the last of the system SGPRs. We
1514 // initially assumed it was allocated, and may have used it. It shouldn't harm
1515 // anything to disable it if we know the stack isn't used here. We may still
1516 // have emitted code reading it to initialize scratch, but if that's unused
1517 // reading garbage should be OK.
1520 MCConstantExpr::create(0, Ctx), Ctx),
1521 ProgInfo.DynamicCallStack, Ctx);
1522
1523 ProgInfo.UserSGPR = MFI->getNumUserSGPRs();
1524 // For AMDHSA, TRAP_HANDLER must be zero, as it is populated by the CP.
1525 ProgInfo.TrapHandlerEnable = STM.isAmdHsaOS() ? 0 : STM.hasTrapHandler();
1526 ProgInfo.TGIdXEnable = MFI->hasWorkGroupIDX();
1527 ProgInfo.TGIdYEnable = MFI->hasWorkGroupIDY();
1528 ProgInfo.TGIdZEnable = MFI->hasWorkGroupIDZ();
1529 ProgInfo.TGSizeEnable = MFI->hasWorkGroupInfo();
1530 ProgInfo.TIdIGCompCount = TIDIGCompCnt;
1531 ProgInfo.EXCPEnMSB = 0;
1532 // For AMDHSA, LDS_SIZE must be zero, as it is populated by the CP.
1533 ProgInfo.LdsSize = STM.isAmdHsaOS() ? 0 : ProgInfo.LDSBlocks;
1534 ProgInfo.EXCPEnable = 0;
1535
1536 if (STM.hasGFX90AInsts()) {
1537 ProgInfo.ComputePGMRSrc3 =
1538 setBits(ProgInfo.ComputePGMRSrc3, ProgInfo.AccumOffset,
1539 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET,
1540 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET_SHIFT, Ctx);
1541 ProgInfo.ComputePGMRSrc3 =
1542 setBits(ProgInfo.ComputePGMRSrc3, CreateExpr(ProgInfo.TgSplit),
1543 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT,
1544 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT_SHIFT, Ctx);
1545 }
1546
1547 if (STM.hasGFX1250Insts())
1548 ProgInfo.ComputePGMRSrc3 =
1549 setBits(ProgInfo.ComputePGMRSrc3, ProgInfo.NamedBarCnt,
1550 amdhsa::COMPUTE_PGM_RSRC3_GFX125_NAMED_BAR_CNT,
1551 amdhsa::COMPUTE_PGM_RSRC3_GFX125_NAMED_BAR_CNT_SHIFT, Ctx);
1552
1553 ProgInfo.Occupancy = createOccupancy(
1556 MFI->getDynamicVGPRBlockSize(), STM, Ctx);
1557
1558 const auto [MinWEU, MaxWEU] =
1559 AMDGPU::getIntegerPairAttribute(F, "amdgpu-waves-per-eu", {0, 0}, true);
1560 uint64_t Occupancy;
1561 if (TryGetMCExprValue(ProgInfo.Occupancy, Occupancy) && Occupancy < MinWEU) {
1562 DiagnosticInfoOptimizationFailure Diag(
1563 F, F.getSubprogram(),
1564 "failed to meet occupancy target given by 'amdgpu-waves-per-eu' in "
1565 "'" +
1566 F.getName() + "': desired occupancy was " + Twine(MinWEU) +
1567 ", final occupancy is " + Twine(Occupancy));
1568 F.getContext().diagnose(Diag);
1569 }
1570}
1571
1572static unsigned getRsrcReg(CallingConv::ID CallConv) {
1573 switch (CallConv) {
1574 default:
1575 [[fallthrough]];
1590 }
1591}
1592
1593void AMDGPUAsmPrinter::EmitProgramInfoSI(
1594 const MachineFunction &MF, const SIProgramInfo &CurrentProgramInfo) {
1595 const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1596 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
1597 unsigned RsrcReg = getRsrcReg(MF.getFunction().getCallingConv());
1598 MCContext &Ctx = MF.getContext();
1599
1600 // (((Value) & Mask) << Shift)
1601 auto SetBits = [&Ctx](const MCExpr *Value, uint32_t Mask, uint32_t Shift) {
1602 const MCExpr *msk = MCConstantExpr::create(Mask, Ctx);
1603 const MCExpr *shft = MCConstantExpr::create(Shift, Ctx);
1605 shft, Ctx);
1606 };
1607
1608 auto EmitResolvedOrExpr = [this](const MCExpr *Value, unsigned Size) {
1609 int64_t Val;
1610 if (Value->evaluateAsAbsolute(Val))
1611 OutStreamer->emitIntValue(static_cast<uint64_t>(Val), Size);
1612 else
1613 OutStreamer->emitValue(Value, Size);
1614 };
1615
1616 if (AMDGPU::isCompute(MF.getFunction().getCallingConv())) {
1618
1619 EmitResolvedOrExpr(CurrentProgramInfo.getComputePGMRSrc1(STM, Ctx),
1620 /*Size=*/4);
1621
1623 EmitResolvedOrExpr(CurrentProgramInfo.getComputePGMRSrc2(STM, Ctx),
1624 /*Size=*/4);
1625
1627
1628 // Sets bits according to S_0286E8_WAVESIZE_* mask and shift values for the
1629 // appropriate generation.
1630 if (STM.getGeneration() >= AMDGPUSubtarget::GFX12) {
1631 EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1632 /*Mask=*/0x3FFFF, /*Shift=*/12),
1633 /*Size=*/4);
1634 } else if (STM.getGeneration() == AMDGPUSubtarget::GFX11) {
1635 EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1636 /*Mask=*/0x7FFF, /*Shift=*/12),
1637 /*Size=*/4);
1638 } else {
1639 EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1640 /*Mask=*/0x1FFF, /*Shift=*/12),
1641 /*Size=*/4);
1642 }
1643
1644 // TODO: Should probably note flat usage somewhere. SC emits a "FlatPtr32 =
1645 // 0" comment but I don't see a corresponding field in the register spec.
1646 } else {
1647 OutStreamer->emitInt32(RsrcReg);
1648
1649 const MCExpr *GPRBlocks = MCBinaryExpr::createOr(
1650 SetBits(CurrentProgramInfo.VGPRBlocks, /*Mask=*/0x3F, /*Shift=*/0),
1651 SetBits(CurrentProgramInfo.SGPRBlocks, /*Mask=*/0x0F, /*Shift=*/6),
1652 MF.getContext());
1653 EmitResolvedOrExpr(GPRBlocks, /*Size=*/4);
1655
1656 // Sets bits according to S_0286E8_WAVESIZE_* mask and shift values for the
1657 // appropriate generation.
1658 if (STM.getGeneration() >= AMDGPUSubtarget::GFX12) {
1659 EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1660 /*Mask=*/0x3FFFF, /*Shift=*/12),
1661 /*Size=*/4);
1662 } else if (STM.getGeneration() == AMDGPUSubtarget::GFX11) {
1663 EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1664 /*Mask=*/0x7FFF, /*Shift=*/12),
1665 /*Size=*/4);
1666 } else {
1667 EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1668 /*Mask=*/0x1FFF, /*Shift=*/12),
1669 /*Size=*/4);
1670 }
1671 }
1672
1673 if (MF.getFunction().getCallingConv() == CallingConv::AMDGPU_PS) {
1675 unsigned ExtraLDSSize = STM.getGeneration() >= AMDGPUSubtarget::GFX11
1676 ? divideCeil(CurrentProgramInfo.LDSBlocks, 2)
1677 : CurrentProgramInfo.LDSBlocks;
1678 OutStreamer->emitInt32(S_00B02C_EXTRA_LDS_SIZE(ExtraLDSSize));
1680 OutStreamer->emitInt32(MFI->getPSInputEnable());
1682 OutStreamer->emitInt32(MFI->getPSInputAddr());
1683 }
1684
1685 OutStreamer->emitInt32(R_SPILLED_SGPRS);
1686 OutStreamer->emitInt32(MFI->getNumSpilledSGPRs());
1687 OutStreamer->emitInt32(R_SPILLED_VGPRS);
1688 OutStreamer->emitInt32(MFI->getNumSpilledVGPRs());
1689}
1690
1691// Helper function to add common PAL Metadata 3.0+
1693 const SIProgramInfo &CurrentProgramInfo,
1694 CallingConv::ID CC, const GCNSubtarget &ST,
1695 unsigned DynamicVGPRBlockSize) {
1696 if (ST.hasFeature(AMDGPU::FeatureDX10ClampAndIEEEMode))
1697 MD->setHwStage(CC, ".ieee_mode", (bool)CurrentProgramInfo.IEEEMode);
1698
1699 MD->setHwStage(CC, ".wgp_mode", (bool)CurrentProgramInfo.WgpMode);
1700 MD->setHwStage(CC, ".mem_ordered", (bool)CurrentProgramInfo.MemOrdered);
1701 MD->setHwStage(CC, ".forward_progress", (bool)CurrentProgramInfo.FwdProgress);
1702
1703 if (AMDGPU::isCompute(CC)) {
1704 MD->setHwStage(CC, ".trap_present",
1705 (bool)CurrentProgramInfo.TrapHandlerEnable);
1706 MD->setHwStage(CC, ".excp_en", CurrentProgramInfo.EXCPEnable);
1707
1708 if (DynamicVGPRBlockSize != 0)
1709 MD->setComputeRegisters(".dynamic_vgpr_en", true);
1710 }
1711
1713 CC, ".lds_size",
1714 (unsigned)(CurrentProgramInfo.LdsSize * getLDSEncodingGranule(ST)));
1715}
1716
1717// This is the equivalent of EmitProgramInfoSI above, but for when the OS type
1718// is AMDPAL. It stores each compute/SPI register setting and other PAL
1719// metadata items into the PALMD::Metadata, combining with any provided by the
1720// frontend as LLVM metadata. Once all functions are written, the PAL metadata
1721// is then written as a single block in the .note section.
1722void AMDGPUAsmPrinter::EmitPALMetadata(
1723 const MachineFunction &MF, const SIProgramInfo &CurrentProgramInfo) {
1724 const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1725 auto CC = MF.getFunction().getCallingConv();
1726 auto *MD = getTargetStreamer()->getPALMetadata();
1727 auto &Ctx = MF.getContext();
1728
1729 MD->setEntryPoint(CC, MF.getFunction().getName());
1730 MD->setNumUsedVgprs(CC, CurrentProgramInfo.NumVGPRsForWavesPerEU, Ctx);
1731
1732 // For targets that support dynamic VGPRs, set the number of saved dynamic
1733 // VGPRs (if any) in the PAL metadata.
1734 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
1735 if (MFI->isDynamicVGPREnabled() &&
1737 MD->setHwStage(CC, ".dynamic_vgpr_saved_count",
1739
1740 // Only set AGPRs for supported devices
1741 if (STM.hasMAIInsts()) {
1742 MD->setNumUsedAgprs(CC, CurrentProgramInfo.NumAccVGPR);
1743 }
1744
1745 MD->setNumUsedSgprs(CC, CurrentProgramInfo.NumSGPRsForWavesPerEU, Ctx);
1746 if (MD->getPALMajorVersion() < 3) {
1747 MD->setRsrc1(CC, CurrentProgramInfo.getPGMRSrc1(CC, STM, Ctx), Ctx);
1748 if (AMDGPU::isCompute(CC)) {
1749 MD->setRsrc2(CC, CurrentProgramInfo.getComputePGMRSrc2(STM, Ctx), Ctx);
1750 } else {
1751 const MCExpr *HasScratchBlocks =
1752 MCBinaryExpr::createGT(CurrentProgramInfo.ScratchBlocks,
1753 MCConstantExpr::create(0, Ctx), Ctx);
1754 auto [Shift, Mask] = getShiftMask(C_00B84C_SCRATCH_EN);
1755 MD->setRsrc2(CC, maskShiftSet(HasScratchBlocks, Mask, Shift, Ctx), Ctx);
1756 }
1757 } else {
1758 MD->setHwStage(CC, ".debug_mode", (bool)CurrentProgramInfo.DebugMode);
1759 MD->setHwStage(CC, ".scratch_en", msgpack::Type::Boolean,
1760 CurrentProgramInfo.ScratchEnable);
1761 EmitPALMetadataCommon(MD, CurrentProgramInfo, CC, STM,
1763 }
1764
1765 // ScratchSize is in bytes, 16 aligned.
1766 MD->setScratchSize(
1767 CC,
1768 AMDGPUMCExpr::createAlignTo(CurrentProgramInfo.ScratchSize,
1769 MCConstantExpr::create(16, Ctx), Ctx),
1770 Ctx);
1771
1772 if (MF.getFunction().getCallingConv() == CallingConv::AMDGPU_PS) {
1773 unsigned ExtraLDSSize = STM.getGeneration() >= AMDGPUSubtarget::GFX11
1774 ? divideCeil(CurrentProgramInfo.LDSBlocks, 2)
1775 : CurrentProgramInfo.LDSBlocks;
1776 if (MD->getPALMajorVersion() < 3) {
1777 MD->setRsrc2(
1778 CC,
1780 Ctx);
1781 MD->setSpiPsInputEna(MFI->getPSInputEnable());
1782 MD->setSpiPsInputAddr(MFI->getPSInputAddr());
1783 } else {
1784 // Graphics registers
1785 const unsigned ExtraLdsDwGranularity =
1786 STM.getGeneration() >= AMDGPUSubtarget::GFX11 ? 256 : 128;
1787 MD->setGraphicsRegisters(
1788 ".ps_extra_lds_size",
1789 (unsigned)(ExtraLDSSize * ExtraLdsDwGranularity * sizeof(uint32_t)));
1790
1791 // Set PsInputEna and PsInputAddr .spi_ps_input_ena and .spi_ps_input_addr
1792 static StringLiteral const PsInputFields[] = {
1793 ".persp_sample_ena", ".persp_center_ena",
1794 ".persp_centroid_ena", ".persp_pull_model_ena",
1795 ".linear_sample_ena", ".linear_center_ena",
1796 ".linear_centroid_ena", ".line_stipple_tex_ena",
1797 ".pos_x_float_ena", ".pos_y_float_ena",
1798 ".pos_z_float_ena", ".pos_w_float_ena",
1799 ".front_face_ena", ".ancillary_ena",
1800 ".sample_coverage_ena", ".pos_fixed_pt_ena"};
1801 unsigned PSInputEna = MFI->getPSInputEnable();
1802 unsigned PSInputAddr = MFI->getPSInputAddr();
1803 for (auto [Idx, Field] : enumerate(PsInputFields)) {
1804 MD->setGraphicsRegisters(".spi_ps_input_ena", Field,
1805 (bool)((PSInputEna >> Idx) & 1));
1806 MD->setGraphicsRegisters(".spi_ps_input_addr", Field,
1807 (bool)((PSInputAddr >> Idx) & 1));
1808 }
1809 }
1810 }
1811
1812 // For version 3 and above the wave front size is already set in the metadata
1813 if (MD->getPALMajorVersion() < 3 && STM.isWave32())
1814 MD->setWave32(MF.getFunction().getCallingConv());
1815}
1816
1817void AMDGPUAsmPrinter::emitPALFunctionMetadata(const MachineFunction &MF) {
1818 auto *MD = getTargetStreamer()->getPALMetadata();
1819 const MachineFrameInfo &MFI = MF.getFrameInfo();
1820 StringRef FnName = MF.getFunction().getName();
1821 MD->setFunctionScratchSize(FnName, MFI.getStackSize());
1822 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
1823 MCContext &Ctx = MF.getContext();
1824
1825 if (MD->getPALMajorVersion() < 3) {
1826 // Set compute registers
1827 MD->setRsrc1(
1829 CurrentProgramInfo.getPGMRSrc1(CallingConv::AMDGPU_CS, ST, Ctx), Ctx);
1830 MD->setRsrc2(CallingConv::AMDGPU_CS,
1831 CurrentProgramInfo.getComputePGMRSrc2(ST, Ctx), Ctx);
1832 } else {
1834 MD, CurrentProgramInfo, CallingConv::AMDGPU_CS, ST,
1835 MF.getInfo<SIMachineFunctionInfo>()->getDynamicVGPRBlockSize());
1836 }
1837
1838 // Set optional info
1839 MD->setFunctionLdsSize(FnName, CurrentProgramInfo.LDSSize);
1840 MD->setFunctionNumUsedVgprs(FnName, CurrentProgramInfo.NumVGPRsForWavesPerEU);
1841 MD->setFunctionNumUsedSgprs(FnName, CurrentProgramInfo.NumSGPRsForWavesPerEU);
1842}
1843
1844// This is supposed to be log2(Size)
1846 switch (Size) {
1847 case 4:
1848 return AMD_ELEMENT_4_BYTES;
1849 case 8:
1850 return AMD_ELEMENT_8_BYTES;
1851 case 16:
1852 return AMD_ELEMENT_16_BYTES;
1853 default:
1854 llvm_unreachable("invalid private_element_size");
1855 }
1856}
1857
1858void AMDGPUAsmPrinter::getAmdKernelCode(AMDGPUMCKernelCodeT &Out,
1859 const SIProgramInfo &CurrentProgramInfo,
1860 const MachineFunction &MF) const {
1861 const Function &F = MF.getFunction();
1862 assert(F.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
1863 F.getCallingConv() == CallingConv::SPIR_KERNEL);
1864
1865 const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1866 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
1867 MCContext &Ctx = MF.getContext();
1868
1869 Out.initDefault(STM, Ctx, /*InitMCExpr=*/false);
1870
1871 Out.compute_pgm_resource1_registers =
1872 CurrentProgramInfo.getComputePGMRSrc1(STM, Ctx);
1873 Out.compute_pgm_resource2_registers =
1874 CurrentProgramInfo.getComputePGMRSrc2(STM, Ctx);
1875 Out.code_properties |= AMD_CODE_PROPERTY_IS_PTR64;
1876
1877 Out.is_dynamic_callstack = CurrentProgramInfo.DynamicCallStack;
1878
1880 getElementByteSizeValue(STM.getMaxPrivateElementSize(true)));
1881
1882 const GCNUserSGPRUsageInfo &UserSGPRInfo = MFI->getUserSGPRInfo();
1883 if (UserSGPRInfo.hasPrivateSegmentBuffer()) {
1885 }
1886
1887 if (UserSGPRInfo.hasDispatchPtr())
1889
1890 if (UserSGPRInfo.hasQueuePtr())
1892
1893 if (UserSGPRInfo.hasKernargSegmentPtr())
1895
1896 if (UserSGPRInfo.hasDispatchID())
1898
1899 if (UserSGPRInfo.hasFlatScratchInit())
1901
1902 if (UserSGPRInfo.hasPrivateSegmentSize())
1904
1905 if (STM.isXNACKEnabled())
1906 Out.code_properties |= AMD_CODE_PROPERTY_IS_XNACK_SUPPORTED;
1907
1908 Align MaxKernArgAlign;
1909 Out.kernarg_segment_byte_size = STM.getKernArgSegmentSize(F, MaxKernArgAlign);
1910 Out.wavefront_sgpr_count = CurrentProgramInfo.NumSGPR;
1911 Out.workitem_vgpr_count = CurrentProgramInfo.NumVGPR;
1912 Out.workitem_private_segment_byte_size = CurrentProgramInfo.ScratchSize;
1913 Out.workgroup_group_segment_byte_size = CurrentProgramInfo.LDSSize;
1914
1915 // kernarg_segment_alignment is specified as log of the alignment.
1916 // The minimum alignment is 16.
1917 // FIXME: The metadata treats the minimum as 4?
1918 Out.kernarg_segment_alignment = Log2(std::max(Align(16), MaxKernArgAlign));
1919}
1920
1922 const char *ExtraCode, raw_ostream &O) {
1923 // First try the generic code, which knows about modifiers like 'c' and 'n'.
1924 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O))
1925 return false;
1926
1927 if (ExtraCode && ExtraCode[0]) {
1928 if (ExtraCode[1] != 0)
1929 return true; // Unknown modifier.
1930
1931 switch (ExtraCode[0]) {
1932 case 'r':
1933 break;
1934 default:
1935 return true;
1936 }
1937 }
1938
1939 // TODO: Should be able to support other operand types like globals.
1940 const MachineOperand &MO = MI->getOperand(OpNo);
1941 if (MO.isReg()) {
1943 *MF->getSubtarget().getRegisterInfo());
1944 return false;
1945 }
1946 if (MO.isImm()) {
1947 int64_t Val = MO.getImm();
1949 O << Val;
1950 } else if (isUInt<16>(Val)) {
1951 O << format("0x%" PRIx16, static_cast<uint16_t>(Val));
1952 } else if (isUInt<32>(Val)) {
1953 O << format("0x%" PRIx32, static_cast<uint32_t>(Val));
1954 } else {
1955 O << format("0x%" PRIx64, static_cast<uint64_t>(Val));
1956 }
1957 return false;
1958 }
1959 return true;
1960}
1961
1969
1970void AMDGPUAsmPrinter::emitResourceUsageRemarks(
1971 const MachineFunction &MF, const SIProgramInfo &CurrentProgramInfo,
1972 bool isModuleEntryFunction, bool hasMAIInsts) {
1973 if (!ORE)
1974 return;
1975
1976 const char *Name = "kernel-resource-usage";
1977 const char *Indent = " ";
1978
1979 // If the remark is not specifically enabled, do not output to yaml
1981 if (!Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(Name))
1982 return;
1983
1984 // Currently non-kernel functions have no resources to emit.
1986 return;
1987
1988 auto EmitResourceUsageRemark = [&](StringRef RemarkName,
1989 StringRef RemarkLabel, auto Argument) {
1990 // Add an indent for every line besides the line with the kernel name. This
1991 // makes it easier to tell which resource usage go with which kernel since
1992 // the kernel name will always be displayed first.
1993 std::string LabelStr = RemarkLabel.str() + ": ";
1994 if (RemarkName != "FunctionName")
1995 LabelStr = Indent + LabelStr;
1996
1997 ORE->emit([&]() {
1998 return MachineOptimizationRemarkAnalysis(Name, RemarkName,
2000 &MF.front())
2001 << LabelStr << ore::NV(RemarkName, Argument);
2002 });
2003 };
2004
2005 // FIXME: Formatting here is pretty nasty because clang does not accept
2006 // newlines from diagnostics. This forces us to emit multiple diagnostic
2007 // remarks to simulate newlines. If and when clang does accept newlines, this
2008 // formatting should be aggregated into one remark with newlines to avoid
2009 // printing multiple diagnostic location and diag opts.
2010 EmitResourceUsageRemark("FunctionName", "Function Name",
2011 MF.getFunction().getName());
2012 EmitResourceUsageRemark("NumSGPR", "TotalSGPRs",
2013 getMCExprStr(CurrentProgramInfo.NumSGPR));
2014 EmitResourceUsageRemark("NumVGPR", "VGPRs",
2015 getMCExprStr(CurrentProgramInfo.NumArchVGPR));
2016 if (hasMAIInsts) {
2017 EmitResourceUsageRemark("NumAGPR", "AGPRs",
2018 getMCExprStr(CurrentProgramInfo.NumAccVGPR));
2019 }
2020 EmitResourceUsageRemark("ScratchSize", "ScratchSize [bytes/lane]",
2021 getMCExprStr(CurrentProgramInfo.ScratchSize));
2022 int64_t DynStack;
2023 bool DynStackEvaluatable =
2024 CurrentProgramInfo.DynamicCallStack->evaluateAsAbsolute(DynStack);
2025 StringRef DynamicStackStr =
2026 DynStackEvaluatable && DynStack ? "True" : "False";
2027 EmitResourceUsageRemark("DynamicStack", "Dynamic Stack", DynamicStackStr);
2028 EmitResourceUsageRemark("Occupancy", "Occupancy [waves/SIMD]",
2029 getMCExprStr(CurrentProgramInfo.Occupancy));
2030 EmitResourceUsageRemark("SGPRSpill", "SGPRs Spill",
2031 CurrentProgramInfo.SGPRSpill);
2032 EmitResourceUsageRemark("VGPRSpill", "VGPRs Spill",
2033 CurrentProgramInfo.VGPRSpill);
2034 if (isModuleEntryFunction)
2035 EmitResourceUsageRemark("BytesLDS", "LDS Size [bytes/block]",
2036 CurrentProgramInfo.LDSSize);
2037}
2038
2048
2064
2073
2074char AMDGPUAsmPrinter::ID = 0;
2075
2076INITIALIZE_PASS(AMDGPUAsmPrinter, "amdgpu-asm-printer",
2077 "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
static AMDGPU::TargetIDSetting getTargetIDSettingFromModuleFlag(const Module &M, StringRef FlagName)
Get xnack/sramecc setting from module flag or cl::opt (for testing).
bool hasPrivateSegmentBuffer() const
VisibilityTypes getVisibility() const
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition Globals.cpp:408
unsigned getAddressSpace() const
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
Definition Globals.cpp:205
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
bool hasInitializer() const
Definitions have initializers, declarations don't.
MaybeAlign getAlign() const
Returns the alignment of the given variable.
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
Definition Globals.cpp:640
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h: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:26
void push_back(const T &Elt)
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
Definition StringRef.h:446
std::pair< typename Base::iterator, bool > insert(StringRef key)
Definition StringSet.h:39
Primary interface to the complete machine description for the target machine.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM Value Representation.
Definition Value.h:75
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:315
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:878
#define N
AMDGPUResourceUsageAnalysisImpl::SIFunctionResourceInfo FunctionResourceInfo
void validate(const MCSubtargetInfo *STI, MCContext &Ctx)
static const MCExpr * bits_get(const MCExpr *Src, uint32_t Shift, uint32_t Mask, MCContext &Ctx)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Track resource usage for kernels / entry functions.
const MCExpr * NumSGPR
const MCExpr * NumArchVGPR
const MCExpr * VGPRBlocks
const MCExpr * ScratchBlocks
const MCExpr * ComputePGMRSrc3
const MCExpr * getComputePGMRSrc1(const GCNSubtarget &ST, MCContext &Ctx) const
Compute the value of the ComputePGMRsrc1 register.
const MCExpr * VCCUsed
const MCExpr * FlatUsed
const MCExpr * NamedBarCnt
const MCExpr * ScratchEnable
const MCExpr * AccumOffset
const MCExpr * NumAccVGPR
const MCExpr * DynamicCallStack
const MCExpr * SGPRBlocks
const MCExpr * NumVGPRsForWavesPerEU
const MCExpr * NumVGPR
const MCExpr * Occupancy
const MCExpr * ScratchSize
const MCExpr * NumSGPRsForWavesPerEU
const MCExpr * getComputePGMRSrc2(const GCNSubtarget &ST, MCContext &Ctx) const
Compute the value of the ComputePGMRsrc2 register.
static void RegisterAsmPrinter(Target &T, Target::AsmPrinterCtorTy Fn)
RegisterAsmPrinter - Register an AsmPrinter implementation for the given target.