//===-- 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;
  }
  const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
  if (STM.isWave32() &&
      STM.getFeatureBits().test(AMDGPU::FeatureSupportsWave32) &&
      STM.getFeatureBits().test(AMDGPU::FeatureSupportsWave64)) {
    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::FeatureSRAMECCOnOffModes)) {
    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)
