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