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