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