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