//===-- AMDGPUAsmPrinter.cpp - AMDGPU assembly printer --------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// \file
///
/// The AMDGPUAsmPrinter is used to print both assembly string and also binary
/// code.  When passed an MCAsmStreamer it prints assembly and when passed
/// an MCObjectStreamer it outputs binary code.
//
//===----------------------------------------------------------------------===//
//

#include "AMDGPUAsmPrinter.h"
#include "AMDGPU.h"
#include "AMDGPUHSAMetadataStreamer.h"
#include "AMDGPUMCResourceInfo.h"
#include "AMDGPUResourceUsageAnalysis.h"
#include "AMDGPUTargetMachine.h"
#include "GCNSubtarget.h"
#include "MCTargetDesc/AMDGPUInstPrinter.h"
#include "MCTargetDesc/AMDGPUMCExpr.h"
#include "MCTargetDesc/AMDGPUMCKernelDescriptor.h"
#include "MCTargetDesc/AMDGPUTargetStreamer.h"
#include "R600AsmPrinter.h"
#include "SIMachineFunctionInfo.h"
#include "TargetInfo/AMDGPUTargetInfo.h"
#include "Utils/AMDGPUBaseInfo.h"
#include "Utils/AMDKernelCodeTUtils.h"
#include "Utils/SIDefinesUtils.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/CodeGen/AsmPrinterAnalysis.h"
#include "llvm/CodeGen/AsmPrinterHandler.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/AMDHSAKernelDescriptor.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/TargetParser/AMDGPUTargetParser.h"

using namespace llvm;
using namespace llvm::AMDGPU;

// This should get the default rounding mode from the kernel. We just set the
// default here, but this could change if the OpenCL rounding mode pragmas are
// used.
//
// The denormal mode here should match what is reported by the OpenCL runtime
// for the CL_FP_DENORM bit from CL_DEVICE_{HALF|SINGLE|DOUBLE}_FP_CONFIG, but
// can also be override to flush with the -cl-denorms-are-zero compiler flag.
//
// AMD OpenCL only sets flush none and reports CL_FP_DENORM for double
// precision, and leaves single precision to flush all and does not report
// CL_FP_DENORM for CL_DEVICE_SINGLE_FP_CONFIG. Mesa's OpenCL currently reports
// CL_FP_DENORM for both.
//
// FIXME: It seems some instructions do not support single precision denormals
// regardless of the mode (exp_*_f32, rcp_*_f32, rsq_*_f32, rsq_*f32, sqrt_f32,
// and sin_f32, cos_f32 on most parts).

// We want to use these instructions, and using fp32 denormals also causes
// instructions to run at the double precision rate for the device so it's
// probably best to just report no single precision denormals.
static uint32_t getFPMode(SIModeRegisterDefaults Mode) {
  return FP_ROUND_MODE_SP(FP_ROUND_ROUND_TO_NEAREST) |
         FP_ROUND_MODE_DP(FP_ROUND_ROUND_TO_NEAREST) |
         FP_DENORM_MODE_SP(Mode.fpDenormModeSPValue()) |
         FP_DENORM_MODE_DP(Mode.fpDenormModeDPValue());
}

static AsmPrinter *
createAMDGPUAsmPrinterPass(TargetMachine &tm,
                           std::unique_ptr<MCStreamer> &&Streamer) {
  return new AMDGPUAsmPrinter(tm, std::move(Streamer));
}

extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
LLVMInitializeAMDGPUAsmPrinter() {
  TargetRegistry::RegisterAsmPrinter(getTheR600Target(),
                                     llvm::createR600AsmPrinterPass);
  TargetRegistry::RegisterAsmPrinter(getTheGCNTarget(),
                                     createAMDGPUAsmPrinterPass);
  TargetRegistry::RegisterAsmPrinter(getTheGCNLegacyTarget(),
                                     createAMDGPUAsmPrinterPass);
}

namespace {
class AMDGPUAsmPrinterHandler : public AsmPrinterHandler {
protected:
  AMDGPUAsmPrinter *Asm;

public:
  AMDGPUAsmPrinterHandler(AMDGPUAsmPrinter *A) : Asm(A) {}

  void beginFunction(const MachineFunction *MF) override {}

  void endFunction(const MachineFunction *MF) override { Asm->endFunction(MF); }

  void endModule() override {}
};
} // End anonymous namespace

AMDGPUAsmPrinter::AMDGPUAsmPrinter(TargetMachine &TM,
                                   std::unique_ptr<MCStreamer> Streamer)
    : AsmPrinter(TM, std::move(Streamer)) {
  assert(OutStreamer && "AsmPrinter constructed without streamer");
  GetResourceUsage = [this](MachineFunction &MF)
      -> const AMDGPUResourceUsageAnalysisImpl::SIFunctionResourceInfo * {
    if (auto *ResourceUsageW =
            getAnalysisIfAvailable<AMDGPUResourceUsageAnalysisWrapperPass>())
      return &ResourceUsageW->getResourceInfo();
    return nullptr;
  };
}

StringRef AMDGPUAsmPrinter::getPassName() const {
  return "AMDGPU Assembly Printer";
}

const MCSubtargetInfo *AMDGPUAsmPrinter::getGlobalSTI() const {
  return &TM.getMCSubtargetInfo();
}

AMDGPUTargetStreamer *AMDGPUAsmPrinter::getTargetStreamer() const {
  if (!OutStreamer)
    return nullptr;
  return static_cast<AMDGPUTargetStreamer *>(OutStreamer->getTargetStreamer());
}

void AMDGPUAsmPrinter::emitStartOfAsmFile(Module &M) {
  IsTargetStreamerInitialized = false;
}

void AMDGPUAsmPrinter::initTargetStreamer(Module &M) {
  IsTargetStreamerInitialized = true;

  // TODO: Which one is called first, emitStartOfAsmFile or
  // emitFunctionBodyStart?
  if (getTargetStreamer() && !getTargetStreamer()->getTargetID())
    initializeTargetID(M);

  const Triple &TT = M.getTargetTriple();
  if (TT.getOS() != Triple::AMDHSA && TT.getOS() != Triple::AMDPAL)
    return;

  getTargetStreamer()->EmitDirectiveAMDGCNTarget();

  if (TT.getOS() == Triple::AMDHSA) {
    getTargetStreamer()->EmitDirectiveAMDHSACodeObjectVersion(
        CodeObjectVersion);
    HSAMetadataStream->begin(M, *getTargetStreamer()->getTargetID());
  }

  if (TT.getOS() == Triple::AMDPAL)
    getTargetStreamer()->getPALMetadata()->readFromIR(M);
}

void AMDGPUAsmPrinter::emitEndOfAsmFile(Module &M) {
  // Init target streamer if it has not yet happened
  if (!IsTargetStreamerInitialized)
    initTargetStreamer(M);

  const Triple &TT = M.getTargetTriple();
  if (TT.getOS() != Triple::AMDHSA)
    getTargetStreamer()->EmitISAVersion();

  // Emit HSA Metadata (NT_AMD_AMDGPU_HSA_METADATA).
  // Emit HSA Metadata (NT_AMD_HSA_METADATA).
  if (TT.getOS() == Triple::AMDHSA) {
    HSAMetadataStream->end();
    bool Success = HSAMetadataStream->emitTo(*getTargetStreamer());
    (void)Success;
    assert(Success && "Malformed HSA Metadata");
  }
}

void AMDGPUAsmPrinter::emitFunctionBodyStart() {
  const SIMachineFunctionInfo &MFI = *MF->getInfo<SIMachineFunctionInfo>();
  const GCNSubtarget &STM = MF->getSubtarget<GCNSubtarget>();
  const Function &F = MF->getFunction();

  // TODO: We're checking this late, would be nice to check it earlier.
  if (STM.requiresCodeObjectV6() && CodeObjectVersion < AMDGPU::AMDHSA_COV6) {
    reportFatalUsageError(
        STM.getCPU() + " is only available on code object version 6 or better");
  }

  // TODO: Which one is called first, emitStartOfAsmFile or
  // emitFunctionBodyStart?
  if (!getTargetStreamer()->getTargetID())
    initializeTargetID(*F.getParent());

  if (!MFI.isEntryFunction())
    return;

  if (STM.isMesaKernel(F) &&
      (F.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
       F.getCallingConv() == CallingConv::SPIR_KERNEL)) {
    AMDGPUMCKernelCodeT KernelCode;
    getAmdKernelCode(KernelCode, CurrentProgramInfo, *MF);
    KernelCode.validate(&STM, MF->getContext());
    getTargetStreamer()->EmitAMDKernelCodeT(KernelCode);
  }

  if (STM.isAmdHsaOS())
    HSAMetadataStream->emitKernel(*MF, CurrentProgramInfo);
}

/// Set bits in a kernel descriptor MCExpr field:
///   return ((Dst & ~Mask) | (Value << Shift))
static const MCExpr *setBits(const MCExpr *Dst, const MCExpr *Value,
                             uint32_t Mask, uint32_t Shift, MCContext &Ctx) {
  const auto *Shft = MCConstantExpr::create(Shift, Ctx);
  const auto *Msk = MCConstantExpr::create(Mask, Ctx);
  Dst = MCBinaryExpr::createAnd(Dst, MCUnaryExpr::createNot(Msk, Ctx), Ctx);
  Dst = MCBinaryExpr::createOr(Dst, MCBinaryExpr::createShl(Value, Shft, Ctx),
                               Ctx);
  return Dst;
}

void AMDGPUAsmPrinter::endFunction(const MachineFunction *MF) {
  const SIMachineFunctionInfo &MFI = *MF->getInfo<SIMachineFunctionInfo>();
  if (!MFI.isEntryFunction())
    return;

  assert(TM.getTargetTriple().getOS() == Triple::AMDHSA);

  const GCNSubtarget &STM = MF->getSubtarget<GCNSubtarget>();
  MCContext &Ctx = MF->getContext();

  AMDGPU::MCKernelDescriptor KD =
      getAmdhsaKernelDescriptor(*MF, CurrentProgramInfo);

  // Compute inst_pref_size using MCExpr label subtraction for exact code
  // size. At this point .Lfunc_end has been emitted (by the base AsmPrinter)
  // right after the function code, so (Lfunc_end - func_sym) gives the
  // exact function code size in bytes.
  if (STM.hasInstPrefSize()) {
    const MCExpr *CodeSizeExpr = MCBinaryExpr::createSub(
        MCSymbolRefExpr::create(getFunctionEnd(), OutContext),
        MCSymbolRefExpr::create(CurrentFnSym, OutContext), OutContext);

    uint32_t Mask, Shift, Width, CacheLineSize;
    STM.getInstPrefSizeArgs(Mask, Shift, Width, CacheLineSize);
    const MCExpr *InstPrefSize =
        AMDGPUMCExpr::createInstPrefSize(CodeSizeExpr, Ctx);
    KD.compute_pgm_rsrc3 =
        setBits(KD.compute_pgm_rsrc3, InstPrefSize, Mask, Shift, Ctx);
  }

  auto &Streamer = getTargetStreamer()->getStreamer();
  auto &Context = Streamer.getContext();
  auto &ObjectFileInfo = *Context.getObjectFileInfo();
  auto &ReadOnlySection = *ObjectFileInfo.getReadOnlySection();

  Streamer.pushSection();
  Streamer.switchSection(&ReadOnlySection);

  // CP microcode requires the kernel descriptor to be allocated on 64 byte
  // alignment.
  Streamer.emitValueToAlignment(Align(64), 0, 1, 0);
  ReadOnlySection.ensureMinAlignment(Align(64));

  SmallString<128> KernelName;
  getNameWithPrefix(KernelName, &MF->getFunction());
  getTargetStreamer()->EmitAmdhsaKernelDescriptor(
      STM, KernelName, KD, CurrentProgramInfo.NumVGPRsForWavesPerEU,
      MCBinaryExpr::createSub(
          CurrentProgramInfo.NumSGPRsForWavesPerEU,
          AMDGPUMCExpr::createExtraSGPRs(
              CurrentProgramInfo.VCCUsed, CurrentProgramInfo.FlatUsed,
              getTargetStreamer()->getTargetID()->isXnackOnOrAny(), Context),
          Context),
      CurrentProgramInfo.VCCUsed, CurrentProgramInfo.FlatUsed);

  Streamer.popSection();
}

void AMDGPUAsmPrinter::emitImplicitDef(const MachineInstr *MI) const {
  Register RegNo = MI->getOperand(0).getReg();

  SmallString<128> Str;
  raw_svector_ostream OS(Str);
  OS << "implicit-def: "
     << printReg(RegNo, MF->getSubtarget().getRegisterInfo());

  if (MI->getAsmPrinterFlags() & AMDGPU::SGPR_SPILL)
    OS << " : SGPR spill to VGPR lane";

  OutStreamer->AddComment(OS.str());
  OutStreamer->addBlankLine();
}

void AMDGPUAsmPrinter::emitFunctionEntryLabel() {
  if (TM.getTargetTriple().getOS() == Triple::AMDHSA) {
    AsmPrinter::emitFunctionEntryLabel();
    return;
  }

  const SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>();
  const GCNSubtarget &STM = MF->getSubtarget<GCNSubtarget>();
  if (MFI->isEntryFunction() && STM.isAmdHsaOrMesa(MF->getFunction())) {
    SmallString<128> SymbolName;
    getNameWithPrefix(SymbolName, &MF->getFunction()),
        getTargetStreamer()->EmitAMDGPUSymbolType(SymbolName,
                                                  ELF::STT_AMDGPU_HSA_KERNEL);
  }
  if (DumpCodeInstEmitter) {
    // Disassemble function name label to text.
    DisasmLines.push_back(MF->getName().str() + ":");
    DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLines.back().size());
    HexLines.emplace_back("");
  }

  AsmPrinter::emitFunctionEntryLabel();
}

void AMDGPUAsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) {
  if (DumpCodeInstEmitter && !isBlockOnlyReachableByFallthrough(&MBB)) {
    // Write a line for the basic block label if it is not only fallthrough.
    DisasmLines.push_back((Twine("BB") + Twine(getFunctionNumber()) + "_" +
                           Twine(MBB.getNumber()) + ":")
                              .str());
    DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLines.back().size());
    HexLines.emplace_back("");
  }
  AsmPrinter::emitBasicBlockStart(MBB);
}

void AMDGPUAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
  if (GV->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS) {
    if (GV->hasInitializer() && !isa<UndefValue>(GV->getInitializer())) {
      OutContext.reportError({},
                             Twine(GV->getName()) +
                                 ": unsupported initializer for address space");
      return;
    }

    const Triple::OSType OS = TM.getTargetTriple().getOS();
    if (OS == Triple::AMDHSA || OS == Triple::AMDPAL) {
      if (!AMDGPUTargetMachine::EnableObjectLinking)
        return;
      // With object linking, LDS definitions should have been externalized
      // by earlier passes (e.g. LDS lowering, named barrier lowering).
      // Only declarations reach here, emitted as SHN_AMDGPU_LDS symbols
      // so the linker can assign their offsets.
      assert(GV->isDeclaration() &&
             "LDS definitions should have been externalized when object "
             "linking is enabled");
    }

    MCSymbol *GVSym = getSymbol(GV);

    GVSym->redefineIfPossible();
    if (GVSym->isDefined() || GVSym->isVariable())
      report_fatal_error("symbol '" + Twine(GVSym->getName()) +
                         "' is already defined");

    const DataLayout &DL = GV->getDataLayout();
    uint64_t Size = GV->getGlobalSize(DL);
    Align Alignment = GV->getAlign().value_or(Align(4));

    emitVisibility(GVSym, GV->getVisibility(), !GV->isDeclaration());
    emitLinkage(GV, GVSym);
    auto *TS = getTargetStreamer();
    TS->emitAMDGPULDS(GVSym, Size, Alignment);
    return;
  }

  AsmPrinter::emitGlobalVariable(GV);
}

bool AMDGPUAsmPrinter::doInitialization(Module &M) {
  const Triple &TT = M.getTargetTriple();
  if (TT.getSubArch() == Triple::NoSubArch) {
    Triple::SubArchType SubArch =
        AMDGPU::getSubArch(AMDGPU::parseArchAMDGCN(getGlobalSTI()->getCPU()));
    if (SubArch != Triple::NoSubArch) {
      Triple Fixed(TT);
      Fixed.setArch(Triple::amdgpu, SubArch);
      M.getContext().diagnose(DiagnosticInfoGeneric(
          "codegen with no subarch in the target triple is deprecated and will "
          "become an error; use the target triple '" +
              Fixed.str() + "' instead",
          DS_Warning));
    } else {
      M.getContext().diagnose(DiagnosticInfoGeneric(
          "codegen with no subarch in the target triple is deprecated and will "
          "become an error",
          DS_Warning));
    }
  }

  CodeObjectVersion = AMDGPU::getAMDHSACodeObjectVersion(M);

  if (TT.getOS() == Triple::AMDHSA) {
    switch (CodeObjectVersion) {
    case AMDGPU::AMDHSA_COV4:
      HSAMetadataStream = std::make_unique<HSAMD::MetadataStreamerMsgPackV4>();
      break;
    case AMDGPU::AMDHSA_COV5:
      HSAMetadataStream = std::make_unique<HSAMD::MetadataStreamerMsgPackV5>();
      break;
    case AMDGPU::AMDHSA_COV6:
      HSAMetadataStream = std::make_unique<HSAMD::MetadataStreamerMsgPackV6>();
      break;
    default:
      reportFatalUsageError("unsupported code object version");
    }

    addAsmPrinterHandler(std::make_unique<AMDGPUAsmPrinterHandler>(this));
  }

  return AsmPrinter::doInitialization(M);
}

/// Mimics GCNSubtarget::computeOccupancy for MCExpr.
///
/// Remove dependency on GCNSubtarget and depend only only the necessary values
/// for said occupancy computation. Should match computeOccupancy implementation
/// without passing \p STM on.
const AMDGPUMCExpr *createOccupancy(unsigned InitOcc, const MCExpr *NumSGPRs,
                                    const MCExpr *NumVGPRs,
                                    unsigned DynamicVGPRBlockSize,
                                    const GCNSubtarget &STM, MCContext &Ctx) {
  unsigned MaxWaves = STM.getMaxWavesPerEU();
  unsigned Granule = IsaInfo::getVGPRAllocGranule(STM, DynamicVGPRBlockSize);
  unsigned TargetTotalNumVGPRs = STM.getTotalNumVGPRs();

  // Bake the per-function SGPR budget into the operands so the late-evaluated
  // MCExpr stays arithmetic. The trap reservation in particular is implicit on
  // amdhsa and lives on STM, not on the assembler's MCSubtargetInfo.
  AMDGPU::GPUKind Kind = STM.getTargetID().getGPUKind();
  unsigned SGPRTotal = AMDGPU::getTotalNumSGPRs(Kind);
  unsigned SGPRGranule = AMDGPU::getSGPRAllocGranule(Kind);
  unsigned SGPRTrapReserve = STM.hasTrapHandler() ? IsaInfo::TRAP_NUM_SGPRS : 0;

  auto CreateExpr = [&Ctx](unsigned Value) {
    return MCConstantExpr::create(Value, Ctx);
  };

  // Zero SGPR count when SGPRs don't limit occupancy, so the MCExpr skips the
  // SGPR term without having to test the generation itself.
  const MCExpr *SGPRArg =
      IsaInfo::isSGPROccupancyLimited(STM) ? NumSGPRs : CreateExpr(0);

  return AMDGPUMCExpr::create(AMDGPUMCExpr::AGVK_Occupancy,
                              {CreateExpr(MaxWaves), CreateExpr(Granule),
                               CreateExpr(TargetTotalNumVGPRs),
                               CreateExpr(InitOcc), CreateExpr(SGPRTotal),
                               CreateExpr(SGPRGranule),
                               CreateExpr(SGPRTrapReserve), SGPRArg, NumVGPRs},
                              Ctx);
}

void AMDGPUAsmPrinter::validateMCResourceInfo(Function &F) {
  if (F.isDeclaration() || !AMDGPU::isModuleEntryFunctionCC(F.getCallingConv()))
    return;

  using RIK = MCResourceInfo::ResourceInfoKind;
  const GCNSubtarget &STM = TM.getSubtarget<GCNSubtarget>(F);
  MCSymbol *FnSym = TM.getSymbol(&F);

  auto TryGetMCExprValue = [](const MCExpr *Value, uint64_t &Res) -> bool {
    int64_t Val;
    if (Value->evaluateAsAbsolute(Val)) {
      Res = Val;
      return true;
    }
    return false;
  };

  const uint64_t MaxScratchPerWorkitem =
      STM.getMaxWaveScratchSize() / STM.getWavefrontSize();
  MCSymbol *ScratchSizeSymbol =
      RI.getSymbol(FnSym->getName(), RIK::RIK_PrivateSegSize, OutContext);
  uint64_t ScratchSize;
  if (ScratchSizeSymbol->isVariable() &&
      TryGetMCExprValue(ScratchSizeSymbol->getVariableValue(), ScratchSize) &&
      ScratchSize > MaxScratchPerWorkitem) {
    DiagnosticInfoStackSize DiagStackSize(F, ScratchSize, MaxScratchPerWorkitem,
                                          DS_Error);
    F.getContext().diagnose(DiagStackSize);
  }

  // Validate addressable scalar registers (i.e., prior to added implicit
  // SGPRs).
  MCSymbol *NumSGPRSymbol =
      RI.getSymbol(FnSym->getName(), RIK::RIK_NumSGPR, OutContext);
  if (STM.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS &&
      !STM.hasSGPRInitBug()) {
    unsigned MaxAddressableNumSGPRs = STM.getAddressableNumSGPRs();
    uint64_t NumSgpr;
    if (NumSGPRSymbol->isVariable() &&
        TryGetMCExprValue(NumSGPRSymbol->getVariableValue(), NumSgpr) &&
        NumSgpr > MaxAddressableNumSGPRs) {
      F.getContext().diagnose(DiagnosticInfoResourceLimit(
          F, "addressable scalar registers", NumSgpr, MaxAddressableNumSGPRs,
          DS_Error, DK_ResourceLimit));
      return;
    }
  }

  MCSymbol *VCCUsedSymbol =
      RI.getSymbol(FnSym->getName(), RIK::RIK_UsesVCC, OutContext);
  MCSymbol *FlatUsedSymbol =
      RI.getSymbol(FnSym->getName(), RIK::RIK_UsesFlatScratch, OutContext);
  uint64_t VCCUsed, FlatUsed, NumSgpr;

  if (NumSGPRSymbol->isVariable() && VCCUsedSymbol->isVariable() &&
      FlatUsedSymbol->isVariable() &&
      TryGetMCExprValue(NumSGPRSymbol->getVariableValue(), NumSgpr) &&
      TryGetMCExprValue(VCCUsedSymbol->getVariableValue(), VCCUsed) &&
      TryGetMCExprValue(FlatUsedSymbol->getVariableValue(), FlatUsed)) {

    // Recomputes NumSgprs + implicit SGPRs but all symbols should now be
    // resolvable.
    NumSgpr += IsaInfo::getNumExtraSGPRs(
        STM, VCCUsed, FlatUsed,
        getTargetStreamer()->getTargetID()->isXnackOnOrAny());
    if (STM.getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS ||
        STM.hasSGPRInitBug()) {
      unsigned MaxAddressableNumSGPRs = STM.getAddressableNumSGPRs();
      if (NumSgpr > MaxAddressableNumSGPRs) {
        F.getContext().diagnose(DiagnosticInfoResourceLimit(
            F, "scalar registers", NumSgpr, MaxAddressableNumSGPRs, DS_Error,
            DK_ResourceLimit));
        return;
      }
    }

    MCSymbol *NumVgprSymbol =
        RI.getSymbol(FnSym->getName(), RIK::RIK_NumVGPR, OutContext);
    MCSymbol *NumAgprSymbol =
        RI.getSymbol(FnSym->getName(), RIK::RIK_NumAGPR, OutContext);
    uint64_t NumVgpr, NumAgpr;

    MachineModuleInfo &MMI = *GetMMI();
    MachineFunction *MF = MMI.getMachineFunction(F);
    if (MF && NumVgprSymbol->isVariable() && NumAgprSymbol->isVariable() &&
        TryGetMCExprValue(NumVgprSymbol->getVariableValue(), NumVgpr) &&
        TryGetMCExprValue(NumAgprSymbol->getVariableValue(), NumAgpr)) {
      const SIMachineFunctionInfo &MFI = *MF->getInfo<SIMachineFunctionInfo>();
      unsigned MaxWaves = MFI.getMaxWavesPerEU();
      uint64_t TotalNumVgpr =
          getTotalNumVGPRs(STM.hasGFX90AInsts(), NumAgpr, NumVgpr);
      uint64_t NumVGPRsForWavesPerEU =
          std::max({TotalNumVgpr, (uint64_t)1,
                    (uint64_t)STM.getMinNumVGPRs(
                        MaxWaves, MFI.getDynamicVGPRBlockSize())});
      uint64_t NumSGPRsForWavesPerEU = std::max(
          {NumSgpr, (uint64_t)1, (uint64_t)STM.getMinNumSGPRs(MaxWaves)});
      const MCExpr *OccupancyExpr = createOccupancy(
          STM.getOccupancyWithWorkGroupSizes(*MF).second,
          MCConstantExpr::create(NumSGPRsForWavesPerEU, OutContext),
          MCConstantExpr::create(NumVGPRsForWavesPerEU, OutContext),
          MFI.getDynamicVGPRBlockSize(), STM, OutContext);
      uint64_t Occupancy;

      const auto [MinWEU, MaxWEU] = AMDGPU::getIntegerPairAttribute(
          F, "amdgpu-waves-per-eu", {0, 0}, true);

      if (TryGetMCExprValue(OccupancyExpr, Occupancy) && Occupancy < MinWEU) {
        DiagnosticInfoOptimizationFailure Diag(
            F, F.getSubprogram(),
            "failed to meet occupancy target given by 'amdgpu-waves-per-eu' in "
            "'" +
                F.getName() + "': desired occupancy was " + Twine(MinWEU) +
                ", final occupancy is " + Twine(Occupancy));
        F.getContext().diagnose(Diag);
        return;
      }
    }
  }
}

static void appendTypeEncoding(std::string &Enc, Type *Ty, const DataLayout &DL,
                               bool IsReturnType) {
  if (Ty->isVoidTy()) {
    Enc += 'v';
    return;
  }
  unsigned Bits = DL.getTypeSizeInBits(Ty);
  // Zero-sized non-void types (e.g. `{}` or `[0 x i8]`) consume no ABI
  // registers. For returns, emit the same no-result marker as void so the
  // parameter encoding still has an explicit return-type prefix.
  if (Bits == 0) {
    if (IsReturnType)
      Enc += 'v';
    return;
  }
  if (Bits <= 32)
    Enc += 'i';
  else if (Bits <= 64)
    Enc += 'l';
  else
    Enc.append(divideCeil(Bits, 32), 'i');
}

static std::string computeTypeId(const FunctionType *FTy,
                                 const DataLayout &DL) {
  std::string Enc;
  appendTypeEncoding(Enc, FTy->getReturnType(), DL, /*IsReturnType=*/true);
  for (Type *ParamTy : FTy->params())
    appendTypeEncoding(Enc, ParamTy, DL, /*IsReturnType=*/false);
  return Enc;
}

void AMDGPUAsmPrinter::collectCallEdge(const MachineInstr &MI) {
  if (!AMDGPUTargetMachine::EnableObjectLinking)
    return;
  const SIInstrInfo *TII = MF->getSubtarget<GCNSubtarget>().getInstrInfo();
  const MachineOperand *Callee =
      TII->getNamedOperand(MI, AMDGPU::OpName::callee);
  if (!Callee || !Callee->isGlobal())
    return;
  DirectCallEdges.insert(
      {getSymbol(&MF->getFunction()), getSymbol(Callee->getGlobal())});
}

void AMDGPUAsmPrinter::emitAMDGPUInfo(Module &M) {
  if (!AMDGPUTargetMachine::EnableObjectLinking)
    return;

  const NamedMDNode *LDSMD = M.getNamedMetadata("amdgpu.lds.uses");
  bool HasLDSUses = LDSMD && LDSMD->getNumOperands() > 0;

  const NamedMDNode *BarMD = M.getNamedMetadata("amdgpu.named_barrier.uses");
  bool HasNamedBarriers = BarMD && BarMD->getNumOperands() > 0;

  // Collect address-taken functions (with type IDs) and indirect call sites.
  DenseMap<const Function *, std::string> AddrTakenTypeIds;
  using IndirectCallInfo = std::pair<const Function *, std::string>;
  SmallVector<IndirectCallInfo, 8> IndirectCalls;

  for (const Function &F : M) {
    bool IsKernel = AMDGPU::isKernel(F.getCallingConv());

    if (!IsKernel && F.hasAddressTaken(/*PutOffender=*/nullptr,
                                       /*IgnoreCallbackUses=*/false,
                                       /*IgnoreAssumeLikeCalls=*/true,
                                       /*IgnoreLLVMUsed=*/true)) {
      AddrTakenTypeIds[&F] =
          computeTypeId(F.getFunctionType(), M.getDataLayout());
    }

    if (F.isDeclaration())
      continue;

    StringSet<> SeenTypeIds;
    for (const BasicBlock &BB : F) {
      for (const Instruction &I : BB) {
        const auto *CB = dyn_cast<CallBase>(&I);
        if (!CB || !CB->isIndirectCall())
          continue;
        std::string TId =
            computeTypeId(CB->getFunctionType(), M.getDataLayout());
        if (SeenTypeIds.insert(TId).second)
          IndirectCalls.push_back({&F, std::move(TId)});
      }
    }
  }

  if (FunctionInfos.empty() && DirectCallEdges.empty() && !HasLDSUses &&
      !HasNamedBarriers && AddrTakenTypeIds.empty() && IndirectCalls.empty())
    return;

  AMDGPU::InfoSectionData Data;
  Data.Funcs = std::move(FunctionInfos);

  for (auto &[F, TypeId] : AddrTakenTypeIds) {
    MCSymbol *Sym = getSymbol(F);
    Data.TypeIds.push_back({Sym, TypeId});
  }

  for (auto &[CallerSym, CalleeSym] : DirectCallEdges)
    Data.Calls.push_back({CallerSym, CalleeSym});
  DirectCallEdges.clear();

  if (HasLDSUses) {
    for (const MDNode *N : LDSMD->operands()) {
      auto *Func = mdconst::extract<Function>(N->getOperand(0));
      auto *LdsVar = mdconst::extract<GlobalVariable>(N->getOperand(1));
      Data.Uses.push_back({getSymbol(Func), getSymbol(LdsVar)});
    }
  }

  if (HasNamedBarriers) {
    for (const MDNode *N : BarMD->operands()) {
      auto *BarVar = mdconst::extract<GlobalVariable>(N->getOperand(0));
      MCSymbol *BarSym = getSymbol(BarVar);
      for (unsigned I = 1, E = N->getNumOperands(); I < E; ++I) {
        auto *Func = mdconst::extract<Function>(N->getOperand(I));
        Data.Uses.push_back({getSymbol(Func), BarSym});
      }
    }
  }

  for (auto &[Caller, Enc] : IndirectCalls) {
    MCSymbol *CallerSym = getSymbol(Caller);
    Data.IndirectCalls.push_back({CallerSym, Enc});
  }

  getTargetStreamer()->emitAMDGPUInfo(Data);
}

bool AMDGPUAsmPrinter::doFinalization(Module &M) {
  const Triple &TT = M.getTargetTriple();

  // Pad with s_code_end to help tools and guard against instruction prefetch
  // causing stale data in caches. Arguably this should be done by the linker,
  // which is why this isn't done for Mesa.
  // Don't do it if there is no code.
  const MCSubtargetInfo &STI = *getGlobalSTI();
  if ((AMDGPU::isGFX10Plus(STI) || AMDGPU::isGFX90A(STI)) &&
      (TT.getOS() == Triple::AMDHSA || TT.getOS() == Triple::AMDPAL)) {
    MCSection *TextSect = getObjFileLowering().getTextSection();
    if (TextSect->hasInstructions()) {
      OutStreamer->switchSection(TextSect);
      getTargetStreamer()->EmitCodeEnd(STI);
    }
  }

  // Emit the unified .amdgpu.info section (per-function resources, call graph,
  // LDS/named-barrier use edges, indirect calls, and address-taken type IDs).
  emitAMDGPUInfo(M);

  // Assign expressions which can only be resolved when all other functions are
  // known.
  RI.finalize(OutContext);

  // Switch section and emit all GPR maximums within the processed module.
  OutStreamer->pushSection();
  MCSectionELF *MaxGPRSection =
      OutContext.getELFSection(".AMDGPU.gpr_maximums", ELF::SHT_PROGBITS, 0);
  OutStreamer->switchSection(MaxGPRSection);
  getTargetStreamer()->EmitMCResourceMaximums(
      RI.getMaxVGPRSymbol(OutContext), RI.getMaxAGPRSymbol(OutContext),
      RI.getMaxSGPRSymbol(OutContext), RI.getMaxNamedBarrierSymbol(OutContext));
  OutStreamer->popSection();

  // In the object-linking pipeline per-function resource MCExprs reference
  // external callee symbols that cannot be evaluated here, so cross-TU limit
  // checks would silently no-op for every non-leaf function. Defer resource
  // sanity checking to the linker, which re-validates against the aggregated
  // call graph in the combined .amdgpu.info metadata.
  if (!AMDGPUTargetMachine::EnableObjectLinking) {
    for (Function &F : M.functions())
      validateMCResourceInfo(F);
  }

  RI.reset();

  return AsmPrinter::doFinalization(M);
}

SmallString<128> AMDGPUAsmPrinter::getMCExprStr(const MCExpr *Value) {
  SmallString<128> Str;
  raw_svector_ostream OSS(Str);
  auto &Streamer = getTargetStreamer()->getStreamer();
  auto &Context = Streamer.getContext();
  const MCExpr *New = foldAMDGPUMCExpr(Value, Context);
  printAMDGPUMCExpr(New, OSS, &MAI);
  return Str;
}

// Print comments that apply to both callable functions and entry points.
void AMDGPUAsmPrinter::emitCommonFunctionComments(
    const MCExpr *NumVGPR, const MCExpr *NumAGPR, const MCExpr *TotalNumVGPR,
    const MCExpr *NumSGPR, const MCExpr *ScratchSize, uint64_t CodeSize,
    const AMDGPUMachineFunctionInfo *MFI) {
  OutStreamer->emitRawComment(" codeLenInByte = " + Twine(CodeSize), false);
  OutStreamer->emitRawComment(" TotalNumSgprs: " + getMCExprStr(NumSGPR),
                              false);
  OutStreamer->emitRawComment(" NumVgprs: " + getMCExprStr(NumVGPR), false);
  if (NumAGPR && TotalNumVGPR) {
    OutStreamer->emitRawComment(" NumAgprs: " + getMCExprStr(NumAGPR), false);
    OutStreamer->emitRawComment(" TotalNumVgprs: " + getMCExprStr(TotalNumVGPR),
                                false);
  }
  OutStreamer->emitRawComment(" ScratchSize: " + getMCExprStr(ScratchSize),
                              false);
  OutStreamer->emitRawComment(" MemoryBound: " + Twine(MFI->isMemoryBound()),
                              false);
}

const MCExpr *AMDGPUAsmPrinter::getAmdhsaKernelCodeProperties(
    const MachineFunction &MF) const {
  const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
  MCContext &Ctx = MF.getContext();
  uint16_t KernelCodeProperties = 0;
  const GCNUserSGPRUsageInfo &UserSGPRInfo = MFI.getUserSGPRInfo();

  if (UserSGPRInfo.hasPrivateSegmentBuffer()) {
    KernelCodeProperties |=
        amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER;
  }
  if (UserSGPRInfo.hasDispatchPtr()) {
    KernelCodeProperties |=
        amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR;
  }
  if (UserSGPRInfo.hasQueuePtr()) {
    KernelCodeProperties |= amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR;
  }
  if (UserSGPRInfo.hasKernargSegmentPtr()) {
    KernelCodeProperties |=
        amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR;
  }
  if (UserSGPRInfo.hasDispatchID()) {
    KernelCodeProperties |=
        amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID;
  }
  if (UserSGPRInfo.hasFlatScratchInit()) {
    KernelCodeProperties |=
        amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT;
  }
  if (UserSGPRInfo.hasPrivateSegmentSize()) {
    KernelCodeProperties |=
        amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE;
  }
  if (MF.getSubtarget<GCNSubtarget>().isWave32()) {
    KernelCodeProperties |=
        amdhsa::KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32;
  }

  // CurrentProgramInfo.DynamicCallStack is a MCExpr and could be
  // un-evaluatable at this point so it cannot be conditionally checked here.
  // Instead, we'll directly shift the possibly unknown MCExpr into its place
  // and bitwise-or it into KernelCodeProperties.
  const MCExpr *KernelCodePropExpr =
      MCConstantExpr::create(KernelCodeProperties, Ctx);
  const MCExpr *OrValue = MCConstantExpr::create(
      amdhsa::KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK_SHIFT, Ctx);
  OrValue = MCBinaryExpr::createShl(CurrentProgramInfo.DynamicCallStack,
                                    OrValue, Ctx);
  KernelCodePropExpr = MCBinaryExpr::createOr(KernelCodePropExpr, OrValue, Ctx);

  return KernelCodePropExpr;
}

MCKernelDescriptor
AMDGPUAsmPrinter::getAmdhsaKernelDescriptor(const MachineFunction &MF,
                                            const SIProgramInfo &PI) const {
  const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
  const Function &F = MF.getFunction();
  const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
  MCContext &Ctx = MF.getContext();

  MCKernelDescriptor KernelDescriptor;

  KernelDescriptor.group_segment_fixed_size =
      MCConstantExpr::create(PI.LDSSize, Ctx);
  KernelDescriptor.private_segment_fixed_size = PI.ScratchSize;

  Align MaxKernArgAlign;
  KernelDescriptor.kernarg_size = MCConstantExpr::create(
      STM.getKernArgSegmentSize(F, MaxKernArgAlign), Ctx);

  KernelDescriptor.compute_pgm_rsrc1 = PI.getComputePGMRSrc1(STM, Ctx);
  KernelDescriptor.compute_pgm_rsrc2 = PI.getComputePGMRSrc2(STM, Ctx);
  KernelDescriptor.kernel_code_properties = getAmdhsaKernelCodeProperties(MF);

  int64_t PGM_Rsrc3 = 1;
  bool EvaluatableRsrc3 =
      CurrentProgramInfo.ComputePGMRSrc3->evaluateAsAbsolute(PGM_Rsrc3);
  (void)PGM_Rsrc3;
  (void)EvaluatableRsrc3;
  assert(STM.getGeneration() >= AMDGPUSubtarget::GFX10 ||
         STM.hasGFX90AInsts() || STM.hasGFX1250Insts() || !EvaluatableRsrc3 ||
         static_cast<uint64_t>(PGM_Rsrc3) == 0);
  KernelDescriptor.compute_pgm_rsrc3 = CurrentProgramInfo.ComputePGMRSrc3;

  KernelDescriptor.kernarg_preload = MCConstantExpr::create(
      AMDGPU::hasKernargPreload(STM) ? Info->getNumKernargPreloadedSGPRs() : 0,
      Ctx);

  return KernelDescriptor;
}

bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
  // Init target streamer lazily on the first function so that previous passes
  // can set metadata.
  if (!IsTargetStreamerInitialized)
    initTargetStreamer(*MF.getFunction().getParent());

  ResourceUsage = GetResourceUsage(MF);
  CurrentProgramInfo.reset(MF);

  const AMDGPUMachineFunctionInfo *MFI =
      MF.getInfo<AMDGPUMachineFunctionInfo>();
  MCContext &Ctx = MF.getContext();

  // The starting address of all shader programs must be 256 bytes aligned.
  // Regular functions just need the basic required instruction alignment.
  MF.ensureAlignment(MFI->isEntryFunction() ? Align(256) : Align(4));

  SetupMachineFunction(MF);

  const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
  MCContext &Context = getObjFileLowering().getContext();
  // FIXME: This should be an explicit check for Mesa.
  if (!STM.isAmdHsaOS() && !STM.isAmdPalOS()) {
    MCSectionELF *ConfigSection =
        Context.getELFSection(".AMDGPU.config", ELF::SHT_PROGBITS, 0);
    OutStreamer->switchSection(ConfigSection);
  }

  RI.gatherResourceInfo(MF, *ResourceUsage, OutContext);

  if (AMDGPUTargetMachine::EnableObjectLinking) {
    const AMDGPUResourceUsageAnalysisWrapperPass::FunctionResourceInfo &RU =
        *ResourceUsage;
    FunctionInfos.push_back(
        {/*NumSGPR=*/static_cast<uint32_t>(RU.NumExplicitSGPR),
         /*NumArchVGPR=*/static_cast<uint32_t>(RU.NumVGPR),
         /*NumAccVGPR=*/static_cast<uint32_t>(RU.NumAGPR),
         /*PrivateSegmentSize=*/static_cast<uint32_t>(RU.PrivateSegmentSize),
         /*UsesVCC=*/RU.UsesVCC,
         /*UsesFlatScratch=*/RU.UsesFlatScratch,
         /*HasDynStack=*/RU.HasDynamicallySizedStack,
         /*Sym=*/getSymbol(&MF.getFunction())});
  }

  if (MFI->isModuleEntryFunction()) {
    getSIProgramInfo(CurrentProgramInfo, MF);
  }

  if (STM.isAmdPalOS()) {
    if (MFI->isEntryFunction())
      EmitPALMetadata(MF, CurrentProgramInfo);
    else if (MFI->isModuleEntryFunction())
      emitPALFunctionMetadata(MF);
  } else if (!STM.isAmdHsaOS()) {
    EmitProgramInfoSI(MF, CurrentProgramInfo);
  }

  DumpCodeInstEmitter = nullptr;
  if (STM.dumpCode()) {
    // For -dumpcode, get the assembler out of the streamer. This only works
    // with -filetype=obj.
    MCAssembler *Assembler = OutStreamer->getAssemblerPtr();
    if (Assembler)
      DumpCodeInstEmitter = Assembler->getEmitterPtr();
  }

  DisasmLines.clear();
  HexLines.clear();
  DisasmLineMaxLen = 0;

  emitFunctionBody();

  emitResourceUsageRemarks(MF, CurrentProgramInfo, MFI->isModuleEntryFunction(),
                           STM.hasMAIInsts());

  {
    using RIK = MCResourceInfo::ResourceInfoKind;
    getTargetStreamer()->EmitMCResourceInfo(
        RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_NumVGPR, OutContext),
        RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_NumAGPR, OutContext),
        RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_NumSGPR, OutContext),
        RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_NumNamedBarrier,
                     OutContext),
        RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_PrivateSegSize,
                     OutContext),
        RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_UsesVCC, OutContext),
        RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_UsesFlatScratch,
                     OutContext),
        RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_HasDynSizedStack,
                     OutContext),
        RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_HasRecursion,
                     OutContext),
        RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_HasIndirectCall,
                     OutContext));
  }

  // Emit _dvgpr$ symbol when appropriate.
  emitDVgprSymbol(MF);

  if (isVerbose()) {
    MCSectionELF *CommentSection =
        Context.getELFSection(".AMDGPU.csdata", ELF::SHT_PROGBITS, 0);
    OutStreamer->switchSection(CommentSection);

    if (!MFI->isEntryFunction()) {
      using RIK = MCResourceInfo::ResourceInfoKind;
      OutStreamer->emitRawComment(" Function info:", false);

      emitCommonFunctionComments(
          RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_NumVGPR, OutContext)
              ->getVariableValue(),
          STM.hasMAIInsts() ? RI.getSymbol(CurrentFnSym->getName(),
                                           RIK::RIK_NumAGPR, OutContext)
                                  ->getVariableValue()
                            : nullptr,
          RI.createTotalNumVGPRs(MF, Ctx),
          RI.createTotalNumSGPRs(
              MF,
              MF.getSubtarget<GCNSubtarget>().getTargetID().isXnackOnOrAny(),
              Ctx),
          RI.getSymbol(CurrentFnSym->getName(), RIK::RIK_PrivateSegSize,
                       OutContext)
              ->getVariableValue(),
          CurrentProgramInfo.getFunctionCodeSize(MF), MFI);
      return false;
    }

    OutStreamer->emitRawComment(" Kernel info:", false);
    emitCommonFunctionComments(
        CurrentProgramInfo.NumArchVGPR,
        STM.hasMAIInsts() ? CurrentProgramInfo.NumAccVGPR : nullptr,
        CurrentProgramInfo.NumVGPR, CurrentProgramInfo.NumSGPR,
        CurrentProgramInfo.ScratchSize,
        CurrentProgramInfo.getFunctionCodeSize(MF), MFI);

    OutStreamer->emitRawComment(
        " FloatMode: " + Twine(CurrentProgramInfo.FloatMode), false);
    OutStreamer->emitRawComment(
        " IeeeMode: " + Twine(CurrentProgramInfo.IEEEMode), false);
    OutStreamer->emitRawComment(
        " LDSByteSize: " + Twine(CurrentProgramInfo.LDSSize) +
            " bytes/workgroup (compile time only)",
        false);

    OutStreamer->emitRawComment(
        " SGPRBlocks: " + getMCExprStr(CurrentProgramInfo.SGPRBlocks), false);

    OutStreamer->emitRawComment(
        " VGPRBlocks: " + getMCExprStr(CurrentProgramInfo.VGPRBlocks), false);

    OutStreamer->emitRawComment(
        " NumSGPRsForWavesPerEU: " +
            getMCExprStr(CurrentProgramInfo.NumSGPRsForWavesPerEU),
        false);
    OutStreamer->emitRawComment(
        " NumVGPRsForWavesPerEU: " +
            getMCExprStr(CurrentProgramInfo.NumVGPRsForWavesPerEU),
        false);

    if (STM.hasGFX90AInsts()) {
      const MCExpr *AdjustedAccum = MCBinaryExpr::createAdd(
          CurrentProgramInfo.AccumOffset, MCConstantExpr::create(1, Ctx), Ctx);
      AdjustedAccum = MCBinaryExpr::createMul(
          AdjustedAccum, MCConstantExpr::create(4, Ctx), Ctx);
      OutStreamer->emitRawComment(
          " AccumOffset: " + getMCExprStr(AdjustedAccum), false);
    }

    if (STM.hasGFX1250Insts())
      OutStreamer->emitRawComment(
          " NamedBarCnt: " + getMCExprStr(CurrentProgramInfo.NamedBarCnt),
          false);

    OutStreamer->emitRawComment(
        " Occupancy: " + getMCExprStr(CurrentProgramInfo.Occupancy), false);

    OutStreamer->emitRawComment(
        " WaveLimiterHint : " + Twine(MFI->needsWaveLimiter()), false);

    OutStreamer->emitRawComment(
        " COMPUTE_PGM_RSRC2:SCRATCH_EN: " +
            getMCExprStr(CurrentProgramInfo.ScratchEnable),
        false);
    OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:USER_SGPR: " +
                                    Twine(CurrentProgramInfo.UserSGPR),
                                false);
    OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TRAP_HANDLER: " +
                                    Twine(CurrentProgramInfo.TrapHandlerEnable),
                                false);
    OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TGID_X_EN: " +
                                    Twine(CurrentProgramInfo.TGIdXEnable),
                                false);
    OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TGID_Y_EN: " +
                                    Twine(CurrentProgramInfo.TGIdYEnable),
                                false);
    OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TGID_Z_EN: " +
                                    Twine(CurrentProgramInfo.TGIdZEnable),
                                false);
    OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TIDIG_COMP_CNT: " +
                                    Twine(CurrentProgramInfo.TIdIGCompCount),
                                false);

    [[maybe_unused]] int64_t PGMRSrc3;
    assert(STM.getGeneration() >= AMDGPUSubtarget::GFX10 ||
           STM.hasGFX90AInsts() || STM.hasGFX1250Insts() ||
           (CurrentProgramInfo.ComputePGMRSrc3->evaluateAsAbsolute(PGMRSrc3) &&
            static_cast<uint64_t>(PGMRSrc3) == 0));
    if (STM.hasGFX90AInsts()) {
      OutStreamer->emitRawComment(
          " COMPUTE_PGM_RSRC3_GFX90A:ACCUM_OFFSET: " +
              getMCExprStr(MCKernelDescriptor::bits_get(
                  CurrentProgramInfo.ComputePGMRSrc3,
                  amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET_SHIFT,
                  amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET, Ctx)),
          false);
      OutStreamer->emitRawComment(
          " COMPUTE_PGM_RSRC3_GFX90A:TG_SPLIT: " +
              getMCExprStr(MCKernelDescriptor::bits_get(
                  CurrentProgramInfo.ComputePGMRSrc3,
                  amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT_SHIFT,
                  amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT, Ctx)),
          false);
    }
  }

  if (DumpCodeInstEmitter) {

    OutStreamer->switchSection(
        Context.getELFSection(".AMDGPU.disasm", ELF::SHT_PROGBITS, 0));

    for (size_t i = 0; i < DisasmLines.size(); ++i) {
      std::string Comment = "\n";
      if (!HexLines[i].empty()) {
        Comment = std::string(DisasmLineMaxLen - DisasmLines[i].size(), ' ');
        Comment += " ; " + HexLines[i] + "\n";
      }

      OutStreamer->emitBytes(StringRef(DisasmLines[i]));
      OutStreamer->emitBytes(StringRef(Comment));
    }
  }

  return false;
}

// When appropriate, add a _dvgpr$ symbol, with the value of the function
// symbol, plus an offset encoding one less than the number of VGPR blocks used
// by the function in bits 5..3 of the symbol value. A "VGPR block" can be
// either 16 VGPRs (for a max of 128), or 32 VGPRs (for a max of 256). This is
// used by a front-end to have functions that are chained rather than called,
// and a dispatcher that dynamically resizes the VGPR count before dispatching
// to a function.
void AMDGPUAsmPrinter::emitDVgprSymbol(MachineFunction &MF) {
  const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
  if (MFI.isDynamicVGPREnabled() &&
      MF.getFunction().getCallingConv() == CallingConv::AMDGPU_CS_Chain) {
    MCContext &Ctx = MF.getContext();
    unsigned BlockSize = MFI.getDynamicVGPRBlockSize();

    const MCExpr *EncodedBlocks;
    MCValue NumVGPRs;
    if (CurrentProgramInfo.NumVGPRsForWavesPerEU->evaluateAsRelocatable(
            NumVGPRs, nullptr) &&
        NumVGPRs.isAbsolute()) {

      // Calculate number of VGPR blocks.
      // Treat 0 VGPRs as 1 VGPR to avoid underflowing.
      unsigned NumBlocks =
          divideCeil(std::max(unsigned(NumVGPRs.getConstant()), 1U), BlockSize);

      if (NumBlocks > AMDGPU::IsaInfo::MaxDynamicVGPRBlocks) {
        OutContext.reportError(
            {}, "DVGPR block count " + Twine(NumBlocks) +
                    " exceeds maximum of " +
                    Twine(AMDGPU::IsaInfo::MaxDynamicVGPRBlocks) +
                    " for __dvgpr$ symbol for '" +
                    Twine(CurrentFnSym->getName()) + "'");
        return;
      }
      unsigned EncodedNumBlocks = (NumBlocks - 1) << 3;
      EncodedBlocks = MCConstantExpr::create(EncodedNumBlocks, Ctx);
    } else {
      // Value not yet available so build a symbolic MCExpr:
      // ((alignTo(max(NumVGPRs, 1), BlockSize) / BlockSize - 1) << 3
      const MCExpr *One = MCConstantExpr::create(1, Ctx);
      const MCExpr *BlockSizeConst = MCConstantExpr::create(BlockSize, Ctx);
      const MCExpr *MaxVGPRs = AMDGPUMCExpr::createMax(
          {CurrentProgramInfo.NumVGPRsForWavesPerEU, One}, Ctx);
      const MCExpr *NumBlocks = MCBinaryExpr::createDiv(
          AMDGPUMCExpr::createAlignTo(MaxVGPRs, BlockSizeConst, Ctx),
          BlockSizeConst, Ctx);
      EncodedBlocks =
          MCBinaryExpr::createShl(MCBinaryExpr::createSub(NumBlocks, One, Ctx),
                                  MCConstantExpr::create(3, Ctx), Ctx);
    }

    // Add to function symbol to create _dvgpr$ symbol.
    const MCExpr *DVgprFuncVal = MCBinaryExpr::createAdd(
        MCSymbolRefExpr::create(CurrentFnSym, Ctx), EncodedBlocks, Ctx);
    MCSymbol *DVgprFuncSym =
        Ctx.getOrCreateSymbol(Twine("_dvgpr$") + CurrentFnSym->getName());
    OutStreamer->emitAssignment(DVgprFuncSym, DVgprFuncVal);
    emitVisibility(DVgprFuncSym, MF.getFunction().getVisibility());
    emitLinkage(&MF.getFunction(), DVgprFuncSym);
  }
}

// TODO: Fold this into emitFunctionBodyStart.
void AMDGPUAsmPrinter::initializeTargetID(const Module &M) {
  getTargetStreamer()->initializeTargetID(*getGlobalSTI());

  auto &TSTargetID = getTargetStreamer()->getTargetID();

  // Error if -mattr specified xnack or sramecc.
  // TODO: Remove this when subtarget features removed.
  StringRef FeatureString = getGlobalSTI()->getFeatureString();
  if (FeatureString.contains("xnack")) {
    M.getContext().diagnose(DiagnosticInfoGeneric(
        "xnack/sramecc should be specified via module flags. "
        "Use module flag 'amdgpu.xnack' instead of subtarget feature",
        DS_Error));
  }
  if (FeatureString.contains("sramecc")) {
    M.getContext().diagnose(DiagnosticInfoGeneric(
        "xnack/sramecc should be specified via module flags. "
        "Use module flag 'amdgpu.sramecc' instead of subtarget feature",
        DS_Error));
  }

  // Apply xnack/sramecc settings from module flags.
  if (getGlobalSTI()->getFeatureBits().test(AMDGPU::FeatureXNACKOnOffModes)) {
    AMDGPU::TargetIDSetting Setting =
        GCNTargetMachine::getTargetIDSettingFromModuleFlag(M, "amdgpu.xnack");
    if (Setting != AMDGPU::TargetIDSetting::Any)
      TSTargetID->setXnackSetting(Setting);
  }

  if (getGlobalSTI()->getFeatureBits().test(AMDGPU::FeatureSupportsSRAMECC)) {
    AMDGPU::TargetIDSetting Setting =
        GCNTargetMachine::getTargetIDSettingFromModuleFlag(M, "amdgpu.sramecc");
    if (Setting != AMDGPU::TargetIDSetting::Any)
      TSTargetID->setSramEccSetting(Setting);
  }
}

// AccumOffset computed for the MCExpr equivalent of:
// alignTo(std::max(1, NumVGPR), 4) / 4 - 1;
static const MCExpr *computeAccumOffset(const MCExpr *NumVGPR, MCContext &Ctx) {
  const MCExpr *ConstFour = MCConstantExpr::create(4, Ctx);
  const MCExpr *ConstOne = MCConstantExpr::create(1, Ctx);

  // Can't be lower than 1 for subsequent alignTo.
  const MCExpr *MaximumTaken =
      AMDGPUMCExpr::createMax({ConstOne, NumVGPR}, Ctx);

  // Practically, it's computing divideCeil(MaximumTaken, 4).
  const MCExpr *DivCeil = MCBinaryExpr::createDiv(
      AMDGPUMCExpr::createAlignTo(MaximumTaken, ConstFour, Ctx), ConstFour,
      Ctx);

  return MCBinaryExpr::createSub(DivCeil, ConstOne, Ctx);
}

static unsigned getLDSEncodingGranule(const GCNSubtarget &ST) {
  unsigned Granule =
      AMDGPU::getLDSEncodingGranule(ST.getTargetID().getGPUKind());
  // The legacy generic targets have no encoding granularity feature. Preserve
  // the default used for code generation when no GPU is specified.
  return Granule ? Granule : 256;
}

void AMDGPUAsmPrinter::getSIProgramInfo(SIProgramInfo &ProgInfo,
                                        const MachineFunction &MF) {
  const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
  MCContext &Ctx = MF.getContext();

  auto CreateExpr = [&Ctx](int64_t Value) {
    return MCConstantExpr::create(Value, Ctx);
  };

  auto TryGetMCExprValue = [](const MCExpr *Value, uint64_t &Res) -> bool {
    int64_t Val;
    if (Value->evaluateAsAbsolute(Val)) {
      Res = Val;
      return true;
    }
    return false;
  };

  auto GetSymRefExpr =
      [&](MCResourceInfo::ResourceInfoKind RIK) -> const MCExpr * {
    MCSymbol *Sym = RI.getSymbol(CurrentFnSym->getName(), RIK, OutContext);
    return MCSymbolRefExpr::create(Sym, Ctx);
  };

  using RIK = MCResourceInfo::ResourceInfoKind;
  ProgInfo.NumArchVGPR = GetSymRefExpr(RIK::RIK_NumVGPR);
  ProgInfo.NumAccVGPR = GetSymRefExpr(RIK::RIK_NumAGPR);
  ProgInfo.NumVGPR = AMDGPUMCExpr::createTotalNumVGPR(
      ProgInfo.NumAccVGPR, ProgInfo.NumArchVGPR, Ctx);

  ProgInfo.AccumOffset = computeAccumOffset(ProgInfo.NumArchVGPR, Ctx);
  ProgInfo.TgSplit =
      STM.hasTgSplitSupport() && AMDGPU::isTgSplitEnabled(MF.getFunction());
  ProgInfo.NumSGPR = GetSymRefExpr(RIK::RIK_NumSGPR);
  ProgInfo.ScratchSize = GetSymRefExpr(RIK::RIK_PrivateSegSize);
  ProgInfo.VCCUsed = GetSymRefExpr(RIK::RIK_UsesVCC);
  ProgInfo.FlatUsed = GetSymRefExpr(RIK::RIK_UsesFlatScratch);
  ProgInfo.DynamicCallStack =
      MCBinaryExpr::createOr(GetSymRefExpr(RIK::RIK_HasDynSizedStack),
                             GetSymRefExpr(RIK::RIK_HasRecursion), Ctx);

  const MCExpr *BarBlkConst = MCConstantExpr::create(4, Ctx);
  const MCExpr *AlignToBlk = AMDGPUMCExpr::createAlignTo(
      GetSymRefExpr(RIK::RIK_NumNamedBarrier), BarBlkConst, Ctx);
  ProgInfo.NamedBarCnt = MCBinaryExpr::createDiv(AlignToBlk, BarBlkConst, Ctx);

  const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();

  // The calculations related to SGPR/VGPR blocks are
  // duplicated in part in AMDGPUAsmParser::calculateGPRBlocks, and could be
  // unified.
  const MCExpr *ExtraSGPRs = AMDGPUMCExpr::createExtraSGPRs(
      ProgInfo.VCCUsed, ProgInfo.FlatUsed,
      getTargetStreamer()->getTargetID()->isXnackOnOrAny(), Ctx);

  // Check the addressable register limit before we add ExtraSGPRs.
  if (STM.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS &&
      !STM.hasSGPRInitBug()) {
    unsigned MaxAddressableNumSGPRs = STM.getAddressableNumSGPRs();
    uint64_t NumSgpr;
    if (TryGetMCExprValue(ProgInfo.NumSGPR, NumSgpr) &&
        NumSgpr > MaxAddressableNumSGPRs) {
      // This can happen due to a compiler bug or when using inline asm.
      LLVMContext &Ctx = MF.getFunction().getContext();
      Ctx.diagnose(DiagnosticInfoResourceLimit(
          MF.getFunction(), "addressable scalar registers", NumSgpr,
          MaxAddressableNumSGPRs, DS_Error, DK_ResourceLimit));
      ProgInfo.NumSGPR = CreateExpr(MaxAddressableNumSGPRs - 1);
    }
  }

  // Account for extra SGPRs and VGPRs reserved for debugger use.
  ProgInfo.NumSGPR = MCBinaryExpr::createAdd(ProgInfo.NumSGPR, ExtraSGPRs, Ctx);

  const Function &F = MF.getFunction();

  // Ensure there are enough SGPRs and VGPRs for wave dispatch, where wave
  // dispatch registers as function args.
  unsigned WaveDispatchNumSGPR = MFI->getNumWaveDispatchSGPRs(),
           WaveDispatchNumVGPR = MFI->getNumWaveDispatchVGPRs();

  if (WaveDispatchNumSGPR) {
    ProgInfo.NumSGPR = AMDGPUMCExpr::createMax(
        {ProgInfo.NumSGPR,
         MCBinaryExpr::createAdd(CreateExpr(WaveDispatchNumSGPR), ExtraSGPRs,
                                 Ctx)},
        Ctx);
  }

  if (WaveDispatchNumVGPR) {
    ProgInfo.NumArchVGPR = AMDGPUMCExpr::createMax(
        {ProgInfo.NumArchVGPR, CreateExpr(WaveDispatchNumVGPR)}, Ctx);

    ProgInfo.NumVGPR = AMDGPUMCExpr::createTotalNumVGPR(
        ProgInfo.NumAccVGPR, ProgInfo.NumArchVGPR, Ctx);
  }

  // Adjust number of registers used to meet default/requested minimum/maximum
  // number of waves per execution unit request.
  unsigned MaxWaves = MFI->getMaxWavesPerEU();
  ProgInfo.NumSGPRsForWavesPerEU =
      AMDGPUMCExpr::createMax({ProgInfo.NumSGPR, CreateExpr(1ul),
                               CreateExpr(STM.getMinNumSGPRs(MaxWaves))},
                              Ctx);
  ProgInfo.NumVGPRsForWavesPerEU =
      AMDGPUMCExpr::createMax({ProgInfo.NumVGPR, CreateExpr(1ul),
                               CreateExpr(STM.getMinNumVGPRs(
                                   MaxWaves, MFI->getDynamicVGPRBlockSize()))},
                              Ctx);

  if (STM.getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS ||
      STM.hasSGPRInitBug()) {
    unsigned MaxAddressableNumSGPRs = STM.getAddressableNumSGPRs();
    uint64_t NumSgpr;
    if (TryGetMCExprValue(ProgInfo.NumSGPR, NumSgpr) &&
        NumSgpr > MaxAddressableNumSGPRs) {
      // This can happen due to a compiler bug or when using inline asm to use
      // the registers which are usually reserved for vcc etc.
      LLVMContext &Ctx = MF.getFunction().getContext();
      Ctx.diagnose(DiagnosticInfoResourceLimit(
          MF.getFunction(), "scalar registers", NumSgpr, MaxAddressableNumSGPRs,
          DS_Error, DK_ResourceLimit));
      ProgInfo.NumSGPR = CreateExpr(MaxAddressableNumSGPRs);
      ProgInfo.NumSGPRsForWavesPerEU = CreateExpr(MaxAddressableNumSGPRs);
    }
  }

  if (STM.hasSGPRInitBug()) {
    ProgInfo.NumSGPR =
        CreateExpr(AMDGPU::IsaInfo::FIXED_NUM_SGPRS_FOR_INIT_BUG);
    ProgInfo.NumSGPRsForWavesPerEU =
        CreateExpr(AMDGPU::IsaInfo::FIXED_NUM_SGPRS_FOR_INIT_BUG);
  }

  if (MFI->getNumUserSGPRs() > STM.getMaxNumUserSGPRs()) {
    LLVMContext &Ctx = MF.getFunction().getContext();
    Ctx.diagnose(DiagnosticInfoResourceLimit(
        MF.getFunction(), "user SGPRs", MFI->getNumUserSGPRs(),
        STM.getMaxNumUserSGPRs(), DS_Error));
  }

  if (MFI->getLDSSize() > STM.getAddressableLocalMemorySize()) {
    LLVMContext &Ctx = MF.getFunction().getContext();
    Ctx.diagnose(DiagnosticInfoResourceLimit(
        MF.getFunction(), "local memory", MFI->getLDSSize(),
        STM.getAddressableLocalMemorySize(), DS_Error));
  }

  // When dynamic VGPRs are enabled, entry functions are launched with a single
  // VGPR block. The register allocator enforces this constraint, but we also
  // need to catch explicit physical registers in inline asm and wave dispatch
  // VGPR arguments.
  if (MFI->isDynamicVGPREnabled() &&
      AMDGPU::isEntryFunctionCC(F.getCallingConv())) {
    unsigned BlockSize = MFI->getDynamicVGPRBlockSize();
    uint64_t NumVgpr;
    if (TryGetMCExprValue(ProgInfo.NumVGPRsForWavesPerEU, NumVgpr) &&
        NumVgpr > BlockSize) {
      LLVMContext &Ctx = F.getContext();
      Ctx.diagnose(DiagnosticInfoResourceLimit(
          F, "dynamic VGPR entry point vector registers", NumVgpr, BlockSize,
          DS_Warning, DK_ResourceLimit));
    }
  }

  // The MCExpr equivalent of getNumSGPRBlocks/getNumVGPRBlocks:
  // (alignTo(max(1u, NumGPR), GPREncodingGranule) / GPREncodingGranule) - 1
  auto GetNumGPRBlocks = [&CreateExpr, &Ctx](const MCExpr *NumGPR,
                                             unsigned Granule) {
    const MCExpr *OneConst = CreateExpr(1ul);
    const MCExpr *GranuleConst = CreateExpr(Granule);
    const MCExpr *MaxNumGPR = AMDGPUMCExpr::createMax({NumGPR, OneConst}, Ctx);
    const MCExpr *AlignToGPR =
        AMDGPUMCExpr::createAlignTo(MaxNumGPR, GranuleConst, Ctx);
    const MCExpr *DivGPR =
        MCBinaryExpr::createDiv(AlignToGPR, GranuleConst, Ctx);
    const MCExpr *SubGPR = MCBinaryExpr::createSub(DivGPR, OneConst, Ctx);
    return SubGPR;
  };
  // GFX10+ will always allocate 128 SGPRs and this field must be 0
  if (STM.getGeneration() >= AMDGPUSubtarget::GFX10) {
    ProgInfo.SGPRBlocks = CreateExpr(0ul);
  } else {
    ProgInfo.SGPRBlocks = GetNumGPRBlocks(ProgInfo.NumSGPRsForWavesPerEU,
                                          IsaInfo::getSGPREncodingGranule(STM));
  }
  ProgInfo.VGPRBlocks = GetNumGPRBlocks(ProgInfo.NumVGPRsForWavesPerEU,
                                        IsaInfo::getVGPREncodingGranule(STM));

  const SIModeRegisterDefaults Mode = MFI->getMode();

  // Set the value to initialize FP_ROUND and FP_DENORM parts of the mode
  // register.
  ProgInfo.FloatMode = getFPMode(Mode);

  ProgInfo.IEEEMode = Mode.IEEE;

  // Make clamp modifier on NaN input returns 0.
  ProgInfo.DX10Clamp = Mode.DX10Clamp;
  ProgInfo.SGPRSpill = MFI->getNumSpilledSGPRs();
  ProgInfo.VGPRSpill = MFI->getNumSpilledVGPRs();

  ProgInfo.LDSSize = MFI->getLDSSize();

  unsigned LDSGranularityBytes = getLDSEncodingGranule(STM);
  ProgInfo.LDSBlocks =
      alignTo(ProgInfo.LDSSize, LDSGranularityBytes) / LDSGranularityBytes;

  // The MCExpr equivalent of divideCeil.
  auto DivideCeil = [&Ctx](const MCExpr *Numerator, const MCExpr *Denominator) {
    const MCExpr *Ceil =
        AMDGPUMCExpr::createAlignTo(Numerator, Denominator, Ctx);
    return MCBinaryExpr::createDiv(Ceil, Denominator, Ctx);
  };

  // Scratch is allocated in 64-dword or 256-dword blocks.
  unsigned ScratchAlignShift =
      STM.getGeneration() >= AMDGPUSubtarget::GFX11 ? 8 : 10;
  // We need to program the hardware with the amount of scratch memory that
  // is used by the entire wave.  ProgInfo.ScratchSize is the amount of
  // scratch memory used per thread.
  ProgInfo.ScratchBlocks = DivideCeil(
      MCBinaryExpr::createMul(ProgInfo.ScratchSize,
                              CreateExpr(STM.getWavefrontSize()), Ctx),
      CreateExpr(1ULL << ScratchAlignShift));

  if (STM.hasSupportsWGP()) {
    ProgInfo.WgpMode = STM.isCuModeEnabled() ? 0 : 1;
  }

  if (getIsaVersion(getGlobalSTI()->getCPU()).Major >= 10) {
    ProgInfo.MemOrdered = 1;
    ProgInfo.FwdProgress = !F.hasFnAttribute("amdgpu-no-fwd-progress");
  }

  // 0 = X, 1 = XY, 2 = XYZ
  unsigned TIDIGCompCnt = 0;
  if (MFI->hasWorkItemIDZ())
    TIDIGCompCnt = 2;
  else if (MFI->hasWorkItemIDY())
    TIDIGCompCnt = 1;

  // The private segment wave byte offset is the last of the system SGPRs. We
  // initially assumed it was allocated, and may have used it. It shouldn't harm
  // anything to disable it if we know the stack isn't used here. We may still
  // have emitted code reading it to initialize scratch, but if that's unused
  // reading garbage should be OK.
  ProgInfo.ScratchEnable = MCBinaryExpr::createLOr(
      MCBinaryExpr::createGT(ProgInfo.ScratchBlocks,
                             MCConstantExpr::create(0, Ctx), Ctx),
      ProgInfo.DynamicCallStack, Ctx);

  ProgInfo.UserSGPR = MFI->getNumUserSGPRs();
  // For AMDHSA, TRAP_HANDLER must be zero, as it is populated by the CP.
  ProgInfo.TrapHandlerEnable = STM.isAmdHsaOS() ? 0 : STM.hasTrapHandler();
  ProgInfo.TGIdXEnable = MFI->hasWorkGroupIDX();
  ProgInfo.TGIdYEnable = MFI->hasWorkGroupIDY();
  ProgInfo.TGIdZEnable = MFI->hasWorkGroupIDZ();
  ProgInfo.TGSizeEnable = MFI->hasWorkGroupInfo();
  ProgInfo.TIdIGCompCount = TIDIGCompCnt;
  ProgInfo.EXCPEnMSB = 0;
  // For AMDHSA, LDS_SIZE must be zero, as it is populated by the CP.
  ProgInfo.LdsSize = STM.isAmdHsaOS() ? 0 : ProgInfo.LDSBlocks;
  ProgInfo.EXCPEnable = 0;

  if (STM.hasGFX90AInsts()) {
    ProgInfo.ComputePGMRSrc3 =
        setBits(ProgInfo.ComputePGMRSrc3, ProgInfo.AccumOffset,
                amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET,
                amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET_SHIFT, Ctx);
    ProgInfo.ComputePGMRSrc3 =
        setBits(ProgInfo.ComputePGMRSrc3, CreateExpr(ProgInfo.TgSplit),
                amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT,
                amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT_SHIFT, Ctx);
  }

  if (STM.hasGFX1250Insts())
    ProgInfo.ComputePGMRSrc3 =
        setBits(ProgInfo.ComputePGMRSrc3, ProgInfo.NamedBarCnt,
                amdhsa::COMPUTE_PGM_RSRC3_GFX125_NAMED_BAR_CNT,
                amdhsa::COMPUTE_PGM_RSRC3_GFX125_NAMED_BAR_CNT_SHIFT, Ctx);

  ProgInfo.Occupancy = createOccupancy(
      STM.computeOccupancy(F, ProgInfo.LDSSize).second,
      ProgInfo.NumSGPRsForWavesPerEU, ProgInfo.NumVGPRsForWavesPerEU,
      MFI->getDynamicVGPRBlockSize(), STM, Ctx);

  const auto [MinWEU, MaxWEU] =
      AMDGPU::getIntegerPairAttribute(F, "amdgpu-waves-per-eu", {0, 0}, true);
  uint64_t Occupancy;
  if (TryGetMCExprValue(ProgInfo.Occupancy, Occupancy) && Occupancy < MinWEU) {
    DiagnosticInfoOptimizationFailure Diag(
        F, F.getSubprogram(),
        "failed to meet occupancy target given by 'amdgpu-waves-per-eu' in "
        "'" +
            F.getName() + "': desired occupancy was " + Twine(MinWEU) +
            ", final occupancy is " + Twine(Occupancy));
    F.getContext().diagnose(Diag);
  }
}

static unsigned getRsrcReg(CallingConv::ID CallConv) {
  switch (CallConv) {
  default:
    [[fallthrough]];
  case CallingConv::AMDGPU_CS:
    return R_00B848_COMPUTE_PGM_RSRC1;
  case CallingConv::AMDGPU_LS:
    return R_00B528_SPI_SHADER_PGM_RSRC1_LS;
  case CallingConv::AMDGPU_HS:
    return R_00B428_SPI_SHADER_PGM_RSRC1_HS;
  case CallingConv::AMDGPU_ES:
    return R_00B328_SPI_SHADER_PGM_RSRC1_ES;
  case CallingConv::AMDGPU_GS:
    return R_00B228_SPI_SHADER_PGM_RSRC1_GS;
  case CallingConv::AMDGPU_VS:
    return R_00B128_SPI_SHADER_PGM_RSRC1_VS;
  case CallingConv::AMDGPU_PS:
    return R_00B028_SPI_SHADER_PGM_RSRC1_PS;
  }
}

void AMDGPUAsmPrinter::EmitProgramInfoSI(
    const MachineFunction &MF, const SIProgramInfo &CurrentProgramInfo) {
  const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
  const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
  unsigned RsrcReg = getRsrcReg(MF.getFunction().getCallingConv());
  MCContext &Ctx = MF.getContext();

  // (((Value) & Mask) << Shift)
  auto SetBits = [&Ctx](const MCExpr *Value, uint32_t Mask, uint32_t Shift) {
    const MCExpr *msk = MCConstantExpr::create(Mask, Ctx);
    const MCExpr *shft = MCConstantExpr::create(Shift, Ctx);
    return MCBinaryExpr::createShl(MCBinaryExpr::createAnd(Value, msk, Ctx),
                                   shft, Ctx);
  };

  auto EmitResolvedOrExpr = [this](const MCExpr *Value, unsigned Size) {
    int64_t Val;
    if (Value->evaluateAsAbsolute(Val))
      OutStreamer->emitIntValue(static_cast<uint64_t>(Val), Size);
    else
      OutStreamer->emitValue(Value, Size);
  };

  if (AMDGPU::isCompute(MF.getFunction().getCallingConv())) {
    OutStreamer->emitInt32(R_00B848_COMPUTE_PGM_RSRC1);

    EmitResolvedOrExpr(CurrentProgramInfo.getComputePGMRSrc1(STM, Ctx),
                       /*Size=*/4);

    OutStreamer->emitInt32(R_00B84C_COMPUTE_PGM_RSRC2);
    EmitResolvedOrExpr(CurrentProgramInfo.getComputePGMRSrc2(STM, Ctx),
                       /*Size=*/4);

    OutStreamer->emitInt32(R_00B860_COMPUTE_TMPRING_SIZE);

    // Sets bits according to S_0286E8_WAVESIZE_* mask and shift values for the
    // appropriate generation.
    if (STM.getGeneration() >= AMDGPUSubtarget::GFX12) {
      EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
                                 /*Mask=*/0x3FFFF, /*Shift=*/12),
                         /*Size=*/4);
    } else if (STM.getGeneration() == AMDGPUSubtarget::GFX11) {
      EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
                                 /*Mask=*/0x7FFF, /*Shift=*/12),
                         /*Size=*/4);
    } else {
      EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
                                 /*Mask=*/0x1FFF, /*Shift=*/12),
                         /*Size=*/4);
    }

    // TODO: Should probably note flat usage somewhere. SC emits a "FlatPtr32 =
    // 0" comment but I don't see a corresponding field in the register spec.
  } else {
    OutStreamer->emitInt32(RsrcReg);

    const MCExpr *GPRBlocks = MCBinaryExpr::createOr(
        SetBits(CurrentProgramInfo.VGPRBlocks, /*Mask=*/0x3F, /*Shift=*/0),
        SetBits(CurrentProgramInfo.SGPRBlocks, /*Mask=*/0x0F, /*Shift=*/6),
        MF.getContext());
    EmitResolvedOrExpr(GPRBlocks, /*Size=*/4);
    OutStreamer->emitInt32(R_0286E8_SPI_TMPRING_SIZE);

    // Sets bits according to S_0286E8_WAVESIZE_* mask and shift values for the
    // appropriate generation.
    if (STM.getGeneration() >= AMDGPUSubtarget::GFX12) {
      EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
                                 /*Mask=*/0x3FFFF, /*Shift=*/12),
                         /*Size=*/4);
    } else if (STM.getGeneration() == AMDGPUSubtarget::GFX11) {
      EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
                                 /*Mask=*/0x7FFF, /*Shift=*/12),
                         /*Size=*/4);
    } else {
      EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
                                 /*Mask=*/0x1FFF, /*Shift=*/12),
                         /*Size=*/4);
    }
  }

  if (MF.getFunction().getCallingConv() == CallingConv::AMDGPU_PS) {
    OutStreamer->emitInt32(R_00B02C_SPI_SHADER_PGM_RSRC2_PS);
    unsigned ExtraLDSSize = STM.getGeneration() >= AMDGPUSubtarget::GFX11
                                ? divideCeil(CurrentProgramInfo.LDSBlocks, 2)
                                : CurrentProgramInfo.LDSBlocks;
    OutStreamer->emitInt32(S_00B02C_EXTRA_LDS_SIZE(ExtraLDSSize));
    OutStreamer->emitInt32(R_0286CC_SPI_PS_INPUT_ENA);
    OutStreamer->emitInt32(MFI->getPSInputEnable());
    OutStreamer->emitInt32(R_0286D0_SPI_PS_INPUT_ADDR);
    OutStreamer->emitInt32(MFI->getPSInputAddr());
  }

  OutStreamer->emitInt32(R_SPILLED_SGPRS);
  OutStreamer->emitInt32(MFI->getNumSpilledSGPRs());
  OutStreamer->emitInt32(R_SPILLED_VGPRS);
  OutStreamer->emitInt32(MFI->getNumSpilledVGPRs());
}

// Helper function to add common PAL Metadata 3.0+
static void EmitPALMetadataCommon(AMDGPUPALMetadata *MD,
                                  const SIProgramInfo &CurrentProgramInfo,
                                  CallingConv::ID CC, const GCNSubtarget &ST,
                                  unsigned DynamicVGPRBlockSize) {
  if (ST.hasFeature(AMDGPU::FeatureDX10ClampAndIEEEMode))
    MD->setHwStage(CC, ".ieee_mode", (bool)CurrentProgramInfo.IEEEMode);

  MD->setHwStage(CC, ".wgp_mode", (bool)CurrentProgramInfo.WgpMode);
  MD->setHwStage(CC, ".mem_ordered", (bool)CurrentProgramInfo.MemOrdered);
  MD->setHwStage(CC, ".forward_progress", (bool)CurrentProgramInfo.FwdProgress);

  if (AMDGPU::isCompute(CC)) {
    MD->setHwStage(CC, ".trap_present",
                   (bool)CurrentProgramInfo.TrapHandlerEnable);
    MD->setHwStage(CC, ".excp_en", CurrentProgramInfo.EXCPEnable);

    if (DynamicVGPRBlockSize != 0)
      MD->setComputeRegisters(".dynamic_vgpr_en", true);
  }

  MD->updateHwStageMaximum(
      CC, ".lds_size",
      (unsigned)(CurrentProgramInfo.LdsSize * getLDSEncodingGranule(ST)));
}

// This is the equivalent of EmitProgramInfoSI above, but for when the OS type
// is AMDPAL.  It stores each compute/SPI register setting and other PAL
// metadata items into the PALMD::Metadata, combining with any provided by the
// frontend as LLVM metadata. Once all functions are written, the PAL metadata
// is then written as a single block in the .note section.
void AMDGPUAsmPrinter::EmitPALMetadata(
    const MachineFunction &MF, const SIProgramInfo &CurrentProgramInfo) {
  const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
  auto CC = MF.getFunction().getCallingConv();
  auto *MD = getTargetStreamer()->getPALMetadata();
  auto &Ctx = MF.getContext();

  MD->setEntryPoint(CC, MF.getFunction().getName());
  MD->setNumUsedVgprs(CC, CurrentProgramInfo.NumVGPRsForWavesPerEU, Ctx);

  // For targets that support dynamic VGPRs, set the number of saved dynamic
  // VGPRs (if any) in the PAL metadata.
  const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
  if (MFI->isDynamicVGPREnabled() &&
      MFI->getScratchReservedForDynamicVGPRs() > 0)
    MD->setHwStage(CC, ".dynamic_vgpr_saved_count",
                   MFI->getScratchReservedForDynamicVGPRs() / 4);

  // Only set AGPRs for supported devices
  if (STM.hasMAIInsts()) {
    MD->setNumUsedAgprs(CC, CurrentProgramInfo.NumAccVGPR);
  }

  MD->setNumUsedSgprs(CC, CurrentProgramInfo.NumSGPRsForWavesPerEU, Ctx);
  if (MD->getPALMajorVersion() < 3) {
    MD->setRsrc1(CC, CurrentProgramInfo.getPGMRSrc1(CC, STM, Ctx), Ctx);
    if (AMDGPU::isCompute(CC)) {
      MD->setRsrc2(CC, CurrentProgramInfo.getComputePGMRSrc2(STM, Ctx), Ctx);
    } else {
      const MCExpr *HasScratchBlocks =
          MCBinaryExpr::createGT(CurrentProgramInfo.ScratchBlocks,
                                 MCConstantExpr::create(0, Ctx), Ctx);
      auto [Shift, Mask] = getShiftMask(C_00B84C_SCRATCH_EN);
      MD->setRsrc2(CC, maskShiftSet(HasScratchBlocks, Mask, Shift, Ctx), Ctx);
    }
  } else {
    MD->setHwStage(CC, ".debug_mode", (bool)CurrentProgramInfo.DebugMode);
    MD->setHwStage(CC, ".scratch_en", msgpack::Type::Boolean,
                   CurrentProgramInfo.ScratchEnable);
    EmitPALMetadataCommon(MD, CurrentProgramInfo, CC, STM,
                          MFI->getDynamicVGPRBlockSize());
  }

  // ScratchSize is in bytes, 16 aligned.
  MD->setScratchSize(
      CC,
      AMDGPUMCExpr::createAlignTo(CurrentProgramInfo.ScratchSize,
                                  MCConstantExpr::create(16, Ctx), Ctx),
      Ctx);

  if (MF.getFunction().getCallingConv() == CallingConv::AMDGPU_PS) {
    unsigned ExtraLDSSize = STM.getGeneration() >= AMDGPUSubtarget::GFX11
                                ? divideCeil(CurrentProgramInfo.LDSBlocks, 2)
                                : CurrentProgramInfo.LDSBlocks;
    if (MD->getPALMajorVersion() < 3) {
      MD->setRsrc2(
          CC,
          MCConstantExpr::create(S_00B02C_EXTRA_LDS_SIZE(ExtraLDSSize), Ctx),
          Ctx);
      MD->setSpiPsInputEna(MFI->getPSInputEnable());
      MD->setSpiPsInputAddr(MFI->getPSInputAddr());
    } else {
      // Graphics registers
      const unsigned ExtraLdsDwGranularity =
          STM.getGeneration() >= AMDGPUSubtarget::GFX11 ? 256 : 128;
      MD->setGraphicsRegisters(
          ".ps_extra_lds_size",
          (unsigned)(ExtraLDSSize * ExtraLdsDwGranularity * sizeof(uint32_t)));

      // Set PsInputEna and PsInputAddr .spi_ps_input_ena and .spi_ps_input_addr
      static StringLiteral const PsInputFields[] = {
          ".persp_sample_ena",    ".persp_center_ena",
          ".persp_centroid_ena",  ".persp_pull_model_ena",
          ".linear_sample_ena",   ".linear_center_ena",
          ".linear_centroid_ena", ".line_stipple_tex_ena",
          ".pos_x_float_ena",     ".pos_y_float_ena",
          ".pos_z_float_ena",     ".pos_w_float_ena",
          ".front_face_ena",      ".ancillary_ena",
          ".sample_coverage_ena", ".pos_fixed_pt_ena"};
      unsigned PSInputEna = MFI->getPSInputEnable();
      unsigned PSInputAddr = MFI->getPSInputAddr();
      for (auto [Idx, Field] : enumerate(PsInputFields)) {
        MD->setGraphicsRegisters(".spi_ps_input_ena", Field,
                                 (bool)((PSInputEna >> Idx) & 1));
        MD->setGraphicsRegisters(".spi_ps_input_addr", Field,
                                 (bool)((PSInputAddr >> Idx) & 1));
      }
    }
  }

  // For version 3 and above the wave front size is already set in the metadata
  if (MD->getPALMajorVersion() < 3 && STM.isWave32())
    MD->setWave32(MF.getFunction().getCallingConv());
}

void AMDGPUAsmPrinter::emitPALFunctionMetadata(const MachineFunction &MF) {
  auto *MD = getTargetStreamer()->getPALMetadata();
  const MachineFrameInfo &MFI = MF.getFrameInfo();
  StringRef FnName = MF.getFunction().getName();
  MD->setFunctionScratchSize(FnName, MFI.getStackSize());
  const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
  MCContext &Ctx = MF.getContext();

  if (MD->getPALMajorVersion() < 3) {
    // Set compute registers
    MD->setRsrc1(
        CallingConv::AMDGPU_CS,
        CurrentProgramInfo.getPGMRSrc1(CallingConv::AMDGPU_CS, ST, Ctx), Ctx);
    MD->setRsrc2(CallingConv::AMDGPU_CS,
                 CurrentProgramInfo.getComputePGMRSrc2(ST, Ctx), Ctx);
  } else {
    EmitPALMetadataCommon(
        MD, CurrentProgramInfo, CallingConv::AMDGPU_CS, ST,
        MF.getInfo<SIMachineFunctionInfo>()->getDynamicVGPRBlockSize());
  }

  // Set optional info
  MD->setFunctionLdsSize(FnName, CurrentProgramInfo.LDSSize);
  MD->setFunctionNumUsedVgprs(FnName, CurrentProgramInfo.NumVGPRsForWavesPerEU);
  MD->setFunctionNumUsedSgprs(FnName, CurrentProgramInfo.NumSGPRsForWavesPerEU);
}

// This is supposed to be log2(Size)
static amd_element_byte_size_t getElementByteSizeValue(unsigned Size) {
  switch (Size) {
  case 4:
    return AMD_ELEMENT_4_BYTES;
  case 8:
    return AMD_ELEMENT_8_BYTES;
  case 16:
    return AMD_ELEMENT_16_BYTES;
  default:
    llvm_unreachable("invalid private_element_size");
  }
}

void AMDGPUAsmPrinter::getAmdKernelCode(AMDGPUMCKernelCodeT &Out,
                                        const SIProgramInfo &CurrentProgramInfo,
                                        const MachineFunction &MF) const {
  const Function &F = MF.getFunction();
  assert(F.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
         F.getCallingConv() == CallingConv::SPIR_KERNEL);

  const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
  const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
  MCContext &Ctx = MF.getContext();

  Out.initDefault(STM, Ctx, /*InitMCExpr=*/false);

  Out.compute_pgm_resource1_registers =
      CurrentProgramInfo.getComputePGMRSrc1(STM, Ctx);
  Out.compute_pgm_resource2_registers =
      CurrentProgramInfo.getComputePGMRSrc2(STM, Ctx);
  Out.code_properties |= AMD_CODE_PROPERTY_IS_PTR64;

  Out.is_dynamic_callstack = CurrentProgramInfo.DynamicCallStack;

  AMD_HSA_BITS_SET(Out.code_properties, AMD_CODE_PROPERTY_PRIVATE_ELEMENT_SIZE,
                   getElementByteSizeValue(STM.getMaxPrivateElementSize(true)));

  const GCNUserSGPRUsageInfo &UserSGPRInfo = MFI->getUserSGPRInfo();
  if (UserSGPRInfo.hasPrivateSegmentBuffer()) {
    Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER;
  }

  if (UserSGPRInfo.hasDispatchPtr())
    Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR;

  if (UserSGPRInfo.hasQueuePtr())
    Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR;

  if (UserSGPRInfo.hasKernargSegmentPtr())
    Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR;

  if (UserSGPRInfo.hasDispatchID())
    Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID;

  if (UserSGPRInfo.hasFlatScratchInit())
    Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT;

  if (UserSGPRInfo.hasPrivateSegmentSize())
    Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE;

  if (STM.isXNACKEnabled())
    Out.code_properties |= AMD_CODE_PROPERTY_IS_XNACK_SUPPORTED;

  Align MaxKernArgAlign;
  Out.kernarg_segment_byte_size = STM.getKernArgSegmentSize(F, MaxKernArgAlign);
  Out.wavefront_sgpr_count = CurrentProgramInfo.NumSGPR;
  Out.workitem_vgpr_count = CurrentProgramInfo.NumVGPR;
  Out.workitem_private_segment_byte_size = CurrentProgramInfo.ScratchSize;
  Out.workgroup_group_segment_byte_size = CurrentProgramInfo.LDSSize;

  // kernarg_segment_alignment is specified as log of the alignment.
  // The minimum alignment is 16.
  // FIXME: The metadata treats the minimum as 4?
  Out.kernarg_segment_alignment = Log2(std::max(Align(16), MaxKernArgAlign));
}

bool AMDGPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
                                       const char *ExtraCode, raw_ostream &O) {
  // First try the generic code, which knows about modifiers like 'c' and 'n'.
  if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O))
    return false;

  if (ExtraCode && ExtraCode[0]) {
    if (ExtraCode[1] != 0)
      return true; // Unknown modifier.

    switch (ExtraCode[0]) {
    case 'r':
      break;
    default:
      return true;
    }
  }

  // TODO: Should be able to support other operand types like globals.
  const MachineOperand &MO = MI->getOperand(OpNo);
  if (MO.isReg()) {
    AMDGPUInstPrinter::printRegOperand(MO.getReg(), O,
                                       *MF->getSubtarget().getRegisterInfo());
    return false;
  }
  if (MO.isImm()) {
    int64_t Val = MO.getImm();
    if (AMDGPU::isInlinableIntLiteral(Val)) {
      O << Val;
    } else if (isUInt<16>(Val)) {
      O << format("0x%" PRIx16, static_cast<uint16_t>(Val));
    } else if (isUInt<32>(Val)) {
      O << format("0x%" PRIx32, static_cast<uint32_t>(Val));
    } else {
      O << format("0x%" PRIx64, static_cast<uint64_t>(Val));
    }
    return false;
  }
  return true;
}

void AMDGPUAsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.addRequired<AMDGPUResourceUsageAnalysisWrapperPass>();
  AU.addPreserved<AMDGPUResourceUsageAnalysisWrapperPass>();
  AU.addRequired<MachineModuleInfoWrapperPass>();
  AU.addPreserved<MachineModuleInfoWrapperPass>();
  AsmPrinter::getAnalysisUsage(AU);
}

void AMDGPUAsmPrinter::emitResourceUsageRemarks(
    const MachineFunction &MF, const SIProgramInfo &CurrentProgramInfo,
    bool isModuleEntryFunction, bool hasMAIInsts) {
  if (!ORE)
    return;

  const char *Name = "kernel-resource-usage";
  const char *Indent = "    ";

  // If the remark is not specifically enabled, do not output to yaml
  LLVMContext &Ctx = MF.getFunction().getContext();
  if (!Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(Name))
    return;

  // Currently non-kernel functions have no resources to emit.
  if (!isEntryFunctionCC(MF.getFunction().getCallingConv()))
    return;

  auto EmitResourceUsageRemark = [&](StringRef RemarkName,
                                     StringRef RemarkLabel, auto Argument) {
    // Add an indent for every line besides the line with the kernel name. This
    // makes it easier to tell which resource usage go with which kernel since
    // the kernel name will always be displayed first.
    std::string LabelStr = RemarkLabel.str() + ": ";
    if (RemarkName != "FunctionName")
      LabelStr = Indent + LabelStr;

    ORE->emit([&]() {
      return MachineOptimizationRemarkAnalysis(Name, RemarkName,
                                               MF.getFunction().getSubprogram(),
                                               &MF.front())
             << LabelStr << ore::NV(RemarkName, Argument);
    });
  };

  // FIXME: Formatting here is pretty nasty because clang does not accept
  // newlines from diagnostics. This forces us to emit multiple diagnostic
  // remarks to simulate newlines. If and when clang does accept newlines, this
  // formatting should be aggregated into one remark with newlines to avoid
  // printing multiple diagnostic location and diag opts.
  EmitResourceUsageRemark("FunctionName", "Function Name",
                          MF.getFunction().getName());
  EmitResourceUsageRemark("NumSGPR", "TotalSGPRs",
                          getMCExprStr(CurrentProgramInfo.NumSGPR));
  EmitResourceUsageRemark("NumVGPR", "VGPRs",
                          getMCExprStr(CurrentProgramInfo.NumArchVGPR));
  if (hasMAIInsts) {
    EmitResourceUsageRemark("NumAGPR", "AGPRs",
                            getMCExprStr(CurrentProgramInfo.NumAccVGPR));
  }
  EmitResourceUsageRemark("ScratchSize", "ScratchSize [bytes/lane]",
                          getMCExprStr(CurrentProgramInfo.ScratchSize));
  int64_t DynStack;
  bool DynStackEvaluatable =
      CurrentProgramInfo.DynamicCallStack->evaluateAsAbsolute(DynStack);
  StringRef DynamicStackStr =
      DynStackEvaluatable && DynStack ? "True" : "False";
  EmitResourceUsageRemark("DynamicStack", "Dynamic Stack", DynamicStackStr);
  EmitResourceUsageRemark("Occupancy", "Occupancy [waves/SIMD]",
                          getMCExprStr(CurrentProgramInfo.Occupancy));
  EmitResourceUsageRemark("SGPRSpill", "SGPRs Spill",
                          CurrentProgramInfo.SGPRSpill);
  EmitResourceUsageRemark("VGPRSpill", "VGPRs Spill",
                          CurrentProgramInfo.VGPRSpill);
  if (isModuleEntryFunction)
    EmitResourceUsageRemark("BytesLDS", "LDS Size [bytes/block]",
                            CurrentProgramInfo.LDSSize);
}

PreservedAnalyses AMDGPUAsmPrinterBeginPass::run(Module &M,
                                                 ModuleAnalysisManager &MAM) {

  AMDGPUAsmPrinter &AsmPrinter = static_cast<AMDGPUAsmPrinter &>(
      MAM.getResult<AsmPrinterAnalysis>(M).getPrinter());
  setupModuleAsmPrinter(M, MAM, AsmPrinter);
  AsmPrinter.doInitialization(M);
  return PreservedAnalyses::all();
}

PreservedAnalyses
AMDGPUAsmPrinterPass::run(MachineFunction &MF,
                          MachineFunctionAnalysisManager &MFAM) {
  AMDGPUAsmPrinter &AsmPrinter = static_cast<AMDGPUAsmPrinter &>(
      MFAM.getResult<ModuleAnalysisManagerMachineFunctionProxy>(MF)
          .getCachedResult<AsmPrinterAnalysis>(*MF.getFunction().getParent())
          ->getPrinter());
  setupMachineFunctionAsmPrinter(MFAM, MF, AsmPrinter);
  AsmPrinter.GetResourceUsage = [&MFAM](MachineFunction &MF)
      -> const AMDGPUResourceUsageAnalysisImpl::SIFunctionResourceInfo * {
    return &MFAM.getResult<AMDGPUResourceUsageAnalysis>(MF);
  };
  AsmPrinter.runOnMachineFunction(MF);
  return PreservedAnalyses::all();
}

PreservedAnalyses AMDGPUAsmPrinterEndPass::run(Module &M,
                                               ModuleAnalysisManager &MAM) {
  AMDGPUAsmPrinter &AsmPrinter = static_cast<AMDGPUAsmPrinter &>(
      MAM.getResult<AsmPrinterAnalysis>(M).getPrinter());
  setupModuleAsmPrinter(M, MAM, AsmPrinter);
  AsmPrinter.doFinalization(M);
  return PreservedAnalyses::all();
}

char AMDGPUAsmPrinter::ID = 0;

INITIALIZE_PASS(AMDGPUAsmPrinter, "amdgpu-asm-printer",
                "AMDGPU Assembly Printer", false, false)
