//===-- AMDGPUTargetParser - Parser for AMDGPU features ---------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file implements a target parser to recognise AMDGPU hardware features.
//
//===----------------------------------------------------------------------===//

#include "llvm/TargetParser/AMDGPUTargetParser.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringTable.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Triple.h"
#include <algorithm>
#include <array>
#include <cassert>

using namespace llvm;
using namespace AMDGPU;

namespace {
constexpr unsigned NumAMDGPUSubArches =
    Triple::LastAMDGPUSubArch - Triple::FirstAMDGPUSubArch + 1;

// A legacy GPU name (e.g. "tahiti") mapped to the GPUKind it aliases.
struct GPUNameAlias {
  StringTable::Offset AltName;
  GPUKind Kind;
};

// Per-GPU data for the AMDGCN GPUKinds, from the generated table below.
struct GPUInfo {
  StringTable::Offset Name;
  Triple::SubArchType SubArch;
  AMDGPUFeatureBitset Features;
  IsaVersion Version;
  StringTable::Offset FamilyName;
  uint8_t MaxWavesPerEU;
  uint32_t MaxHWAddressableLocalMemorySize;
  uint8_t LDSBankCount;
  uint8_t BufferResourceNumRecordsWidth;
};

// Per-GPU data for the R600 GPUKinds.
struct R600Info {
  StringTable::Offset Name;
  R600FeatureBitset Features;
};

#define GET_AMDGPU_NAME_TABLE
#define GET_AMDGPU_GPU_TABLE
#define GET_AMDGPU_GPU_ALIAS_TABLE
#define GET_AMDGPU_MAJOR_SUBARCH
#define GET_AMDGPU_SUBARCH_NAME
#define GET_AMDGPU_FEATURE_NAME_TABLE
#include "llvm/TargetParser/AMDGPUTargetParserDef.inc"

#define GET_R600_NAME_TABLE
#define GET_R600_GPU_TABLE
#define GET_R600_GPU_ALIAS_TABLE
#define GET_R600_FEATURE_NAME_TABLE
#include "llvm/TargetParser/R600TargetParserDef.inc"

// The string tables holding GPU-name-derived strings as offsets. R600 and
// AMDGPU come from separate generated headers, each with its own pool.
constexpr StringTable AMDGPUNameStrTab = AMDGPUNameTable;
constexpr StringTable R600NameStrTab = R600NameTable;

// Look up the GPUInfo row for an AMDGCN GPUKind, or nullptr for GK_NONE / a
// non-AMDGCN (R600) kind.
const GPUInfo *getAMDGPUInfo(GPUKind AK) {
  if (AK < AMDGPUFirstGPUKind)
    return nullptr;
  unsigned Idx = AK - AMDGPUFirstGPUKind;
  if (Idx >= std::size(AMDGPUGPUTable))
    return nullptr;
  return &AMDGPUGPUTable[Idx];
}

// Look up the R600Info row for an R600 GPUKind, or nullptr for a non-R600 kind.
const R600Info *getR600Info(GPUKind AK) {
  if (AK < R600FirstGPUKind)
    return nullptr;
  unsigned Idx = AK - R600FirstGPUKind;
  if (Idx >= std::size(R600GPUTable))
    return nullptr;
  return &R600GPUTable[Idx];
}

// Scan a name -> GPUKind table (canonical names, then aliases) for \p CPU.
template <typename InfoT, size_t N, size_t M>
GPUKind parseArchImpl(StringRef CPU, const InfoT (&Table)[N], GPUKind FirstKind,
                      const StringTable &StrTab,
                      const GPUNameAlias (&Aliases)[M]) {
  for (unsigned I = 0; I != N; ++I) {
    if (CPU == StrTab[Table[I].Name])
      return static_cast<GPUKind>(FirstKind + I);
  }

  for (const GPUNameAlias &A : Aliases) {
    if (CPU == StrTab[A.AltName])
      return A.Kind;
  }

  return GK_NONE;
}

// Reverse map: SubArch -> GPUKind, indexed by (SubArch - FirstAMDGPUSubArch).
// Subarches with no GPU (incl. the NoSubArch pseudo targets) map to GK_NONE.
constexpr std::array<GPUKind, NumAMDGPUSubArches> AMDGPUSubArchToGPUKind = [] {
  std::array<GPUKind, NumAMDGPUSubArches> Map{};

  for (unsigned I = 0; I < std::size(AMDGPUGPUTable); ++I) {
    Triple::SubArchType SubArch = AMDGPUGPUTable[I].SubArch;
    if (SubArch != Triple::NoSubArch) {
      Map[SubArch - Triple::FirstAMDGPUSubArch] =
          static_cast<GPUKind>(AMDGPUFirstGPUKind + I);
    }
  }
  return Map;
}();

/// SubArch -> major-family, indexed by (SubArch - FirstAMDGPUSubArch).
constexpr std::array<Triple::SubArchType, NumAMDGPUSubArches>
    AMDGPUMajorFamilies = [] {
      std::array<Triple::SubArchType, NumAMDGPUSubArches> Map{};

      for (unsigned I = 0; I < NumAMDGPUSubArches; ++I) {
        Map[I] =
            static_cast<Triple::SubArchType>(Triple::FirstAMDGPUSubArch + I);
      }

      for (const AMDGPUMajorSubArchEntry &Entry : AMDGPUMajorSubArch)
        Map[Entry.SubArch - Triple::FirstAMDGPUSubArch] = Entry.Major;
      return Map;
    }();

// SubArch -> name-offset, indexed by (SubArch - FirstAMDGPUSubArch). Unmapped
// subarches keep offset 0 (the empty string).
constexpr std::array<StringTable::Offset, NumAMDGPUSubArches>
    AMDGPUSubArchNameOffsets = [] {
      std::array<StringTable::Offset, NumAMDGPUSubArches> Map{};
      for (const AMDGPUSubArchNameEntry &Entry : AMDGPUSubArchNames)
        Map[Entry.SubArch - Triple::FirstAMDGPUSubArch] = Entry.NameOffset;
      return Map;
    }();

// SubArch -> triple-name-offset (e.g. "amdgpu9.00"), like
// AMDGPUSubArchNameOffsets.
constexpr std::array<StringTable::Offset, NumAMDGPUSubArches>
    AMDGPUSubArchTripleNameOffsets = [] {
      std::array<StringTable::Offset, NumAMDGPUSubArches> Map{};
      for (const AMDGPUSubArchNameEntry &Entry : AMDGPUSubArchNames)
        Map[Entry.SubArch - Triple::FirstAMDGPUSubArch] =
            Entry.TripleNameOffset;
      return Map;
    }();
} // namespace

StringRef llvm::AMDGPU::getArchFamilyNameAMDGCN(GPUKind AK) {
  const GPUInfo *Info = getAMDGPUInfo(AK);
  return Info ? AMDGPUNameStrTab[Info->FamilyName] : "";
}

Triple::SubArchType llvm::AMDGPU::getSubArch(GPUKind AK) {
  const GPUInfo *Info = getAMDGPUInfo(AK);
  return Info ? Info->SubArch : Triple::SubArchType::NoSubArch;
}

Triple::SubArchType llvm::AMDGPU::getSubArchFromGPUName(StringRef CPU) {
  return getSubArch(parseArchAMDGCN(CPU));
}

AMDGPU::GPUKind
llvm::AMDGPU::getGPUKindFromSubArch(Triple::SubArchType SubArch) {
  if (SubArch < Triple::FirstAMDGPUSubArch ||
      SubArch > Triple::LastAMDGPUSubArch)
    return GK_NONE;
  return AMDGPUSubArchToGPUKind[SubArch - Triple::FirstAMDGPUSubArch];
}

Triple::SubArchType AMDGPU::getMajorSubArch(Triple::SubArchType X) {
  if (X < Triple::FirstAMDGPUSubArch || X > Triple::LastAMDGPUSubArch)
    return Triple::NoSubArch;
  return AMDGPUMajorFamilies[X - Triple::FirstAMDGPUSubArch];
}

bool AMDGPU::isSubArchCompatible(Triple::SubArchType A, Triple::SubArchType B) {
  if (A == B || A == Triple::NoSubArch || B == Triple::NoSubArch)
    return true;

  Triple::SubArchType MajorA = AMDGPU::getMajorSubArch(A);
  Triple::SubArchType MajorB = AMDGPU::getMajorSubArch(B);

  // One side is the major-family subarch covering the other's family.
  if (A == MajorA)
    return MajorA == MajorB;
  if (B == MajorB)
    return MajorA == MajorB;

  return false;
}

bool AMDGPU::isCPUValidForSubArch(Triple::SubArchType SubArch, GPUKind AK) {
  // An unrecognized GPU is never valid.
  if (AK == GK_NONE)
    return false;
  // A legacy triple without a subarch accepts any known GPU.
  if (SubArch == Triple::NoSubArch)
    return true;

  // Reject the dummy "generic" targets
  Triple::SubArchType GPUSubArch = getSubArch(AK);
  if (GPUSubArch == Triple::NoSubArch)
    return false;

  return isSubArchCompatible(GPUSubArch, SubArch);
}

bool AMDGPU::isCPUValidForSubArch(Triple::SubArchType SubArch, StringRef CPU) {
  return isCPUValidForSubArch(SubArch, parseArchAMDGCN(CPU));
}

bool AMDGPU::isPseudoTarget(GPUKind AK) {
  const GPUInfo *Info = getAMDGPUInfo(AK);
  return Info && Info->SubArch == Triple::NoSubArch;
}

bool AMDGPU::isPseudoTarget(StringRef CPU) {
  return isPseudoTarget(parseArchAMDGCN(CPU));
}

bool AMDGPU::isSubArchCompatible(const Triple &A, const Triple &B) {
  // Tolerate subarch mismatch if one entry is none. This is a hack for bitcode
  // libraries.
  // There's a missing enum entry for an unknown subarch. Make sure the
  // subarch is really empty.
  if (A.getSubArch() == Triple::NoSubArch)
    return A.getArchName().size() == 6;

  if (B.getSubArch() == Triple::NoSubArch)
    return B.getArchName().size() == 6;

  return isSubArchCompatible(A.getSubArch(), B.getSubArch());
}

std::string AMDGPU::mergeSubArch(const Triple &A, const Triple &B) {
  if (A.getSubArch() == Triple::NoSubArch)
    return B.str();
  if (B.getSubArch() == Triple::NoSubArch)
    return A.str();

  Triple::SubArchType MajorA = AMDGPU::getMajorSubArch(A.getSubArch());
  Triple::SubArchType MajorB = AMDGPU::getMajorSubArch(B.getSubArch());

  // With a compatible major arch, return the specific subarch.
  if (A.getSubArch() == MajorA) {
    if (MajorA == MajorB)
      return B.str();
  }

  if (B.getSubArch() == MajorB) {
    if (MajorA == MajorB)
      return A.str();
  }

  // Invalid case.
  return B.str();
}

StringRef llvm::AMDGPU::getArchNameAMDGCN(GPUKind AK) {
  const GPUInfo *Info = getAMDGPUInfo(AK);
  return Info ? AMDGPUNameStrTab[Info->Name] : "";
}

StringRef llvm::AMDGPU::getArchNameFromSubArch(Triple::SubArchType SubArch) {
  if (SubArch < Triple::FirstAMDGPUSubArch ||
      SubArch > Triple::LastAMDGPUSubArch)
    return "";
  return AMDGPUNameStrTab[AMDGPUSubArchNameOffsets[SubArch -
                                                   Triple::FirstAMDGPUSubArch]];
}

StringRef llvm::AMDGPU::getSubArchName(Triple::SubArchType SubArch) {
  if (SubArch == Triple::NoSubArch)
    return AMDGPUNameStrTab[AMDGPUNoSubArchNameOffset];

  assert(SubArch >= Triple::FirstAMDGPUSubArch &&
         SubArch <= Triple::LastAMDGPUSubArch &&
         "expected an AMDGPU subarch or NoSubArch");
  return AMDGPUNameStrTab
      [AMDGPUSubArchTripleNameOffsets[SubArch - Triple::FirstAMDGPUSubArch]];
}

StringRef llvm::AMDGPU::getArchNameR600(GPUKind AK) {
  const R600Info *Info = getR600Info(AK);
  return Info ? R600NameStrTab[Info->Name] : "";
}

AMDGPU::GPUKind llvm::AMDGPU::parseArchAMDGCN(StringRef CPU) {
  return parseArchImpl(CPU, AMDGPUGPUTable, AMDGPUFirstGPUKind,
                       AMDGPUNameStrTab, AMDGPUGPUAliases);
}

AMDGPU::GPUKind llvm::AMDGPU::parseArchR600(StringRef CPU) {
  return parseArchImpl(CPU, R600GPUTable, R600FirstGPUKind, R600NameStrTab,
                       R600GPUAliases);
}

const AMDGPUFeatureBitset &AMDGPU::getFeatureBitset(GPUKind AK) {
  static constexpr AMDGPUFeatureBitset Empty{};
  const GPUInfo *Info = getAMDGPUInfo(AK);
  return Info ? Info->Features : Empty;
}

const R600FeatureBitset &AMDGPU::getFeatureBitsetR600(GPUKind AK) {
  static constexpr R600FeatureBitset Empty{};
  const R600Info *Info = getR600Info(AK);
  return Info ? Info->Features : Empty;
}

void AMDGPU::getFeatureNames(const AMDGPUFeatureBitset &Features,
                             SmallVectorImpl<StringRef> &Names) {
  for (unsigned I = 0; I != NUM_FEATURES; ++I) {
    if (Features.test(I))
      Names.push_back(AMDGPUNameStrTab[AMDGPUFeatureNames[I]]);
  }
}

void AMDGPU::fillValidArchListAMDGCN(SmallVectorImpl<StringRef> &Values,
                                     Triple::SubArchType SubArch) {
  // XXX: Should this only report unique canonical names?
  // An alias shares its GPU's GPUKind, so it is filtered alongside it.
  for (unsigned I = 0; I != std::size(AMDGPUGPUTable); ++I) {
    GPUKind Kind = static_cast<GPUKind>(AMDGPUFirstGPUKind + I);
    if (AMDGPUGPUTable[I].SubArch != Triple::NoSubArch &&
        isCPUValidForSubArch(SubArch, Kind))
      Values.push_back(AMDGPUNameStrTab[AMDGPUGPUTable[I].Name]);
  }

  for (const GPUNameAlias &A : AMDGPUGPUAliases) {
    if (isCPUValidForSubArch(SubArch, A.Kind))
      Values.push_back(AMDGPUNameStrTab[A.AltName]);
  }
}

void AMDGPU::fillValidArchListR600(SmallVectorImpl<StringRef> &Values) {
  for (const R600Info &Info : R600GPUTable)
    Values.push_back(R600NameStrTab[Info.Name]);
  for (const GPUNameAlias &A : R600GPUAliases)
    Values.push_back(R600NameStrTab[A.AltName]);
}

AMDGPU::IsaVersion AMDGPU::getIsaVersion(StringRef GPU) {
  const GPUInfo *Info = getAMDGPUInfo(parseArchAMDGCN(GPU));
  return Info ? Info->Version : IsaVersion{0, 0, 0};
}

AMDGPU::IsaVersion AMDGPU::getIsaVersion(Triple::SubArchType SubArch) {
  const GPUInfo *Info = getAMDGPUInfo(getGPUKindFromSubArch(SubArch));
  return Info ? Info->Version : IsaVersion{0, 0, 0};
}

unsigned AMDGPU::getTotalNumSGPRs(GPUKind AK) {
  IsaVersion Version = getIsaVersion(getSubArch(AK));
  if (Version.Major >= 8)
    return 800;
  return 512;
}

unsigned AMDGPU::getTotalNumSGPRs(Triple::SubArchType SubArch) {
  IsaVersion Version = getIsaVersion(SubArch);
  if (Version.Major >= 8)
    return 800;
  return 512;
}

unsigned AMDGPU::getAddressableNumSGPRs(GPUKind AK) {
  if (getFeatureBitset(AK).test(FEAT_SGPR_INIT_BUG))
    return FIXED_NUM_SGPRS_FOR_INIT_BUG;

  IsaVersion Version = getIsaVersion(getSubArch(AK));
  if (Version.Major >= 10)
    return 106;
  if (Version.Major >= 8)
    return 102;
  return 104;
}

unsigned AMDGPU::getAddressableNumSGPRs(Triple::SubArchType SubArch) {
  if (getFeatureBitset(getGPUKindFromSubArch(SubArch)).test(FEAT_SGPR_INIT_BUG))
    return FIXED_NUM_SGPRS_FOR_INIT_BUG;

  IsaVersion Version = getIsaVersion(SubArch);
  if (Version.Major >= 10)
    return 106;
  if (Version.Major >= 8)
    return 102;
  return 104;
}

unsigned AMDGPU::getSGPRAllocGranule(GPUKind AK) {
  IsaVersion Version = getIsaVersion(getSubArch(AK));
  if (Version.Major >= 10)
    return getAddressableNumSGPRs(AK);
  if (Version.Major >= 8)
    return 16;
  return 8;
}

unsigned AMDGPU::getSGPRAllocGranule(Triple::SubArchType SubArch) {
  IsaVersion Version = getIsaVersion(SubArch);
  if (Version.Major >= 10)
    return getAddressableNumSGPRs(SubArch);
  if (Version.Major >= 8)
    return 16;
  return 8;
}

unsigned AMDGPU::getVGPRAllocGranule(GPUKind AK, bool IsWave32) {
  const AMDGPUFeatureBitset &Features = getFeatureBitset(AK);
  if (Features.test(FEAT_GFX90A_INSTS))
    return 8;
  if (Features.test(FEAT_1536_PHYSICAL_VGPRS))
    return IsWave32 ? 24 : 12;
  if (Features.test(FEAT_GFX10_3_INSTS))
    return IsWave32 ? 16 : 8;
  return IsWave32 ? 8 : 4;
}

unsigned AMDGPU::getVGPRAllocGranule(Triple::SubArchType SubArch,
                                     bool IsWave32) {
  return getVGPRAllocGranule(getGPUKindFromSubArch(SubArch), IsWave32);
}

unsigned AMDGPU::getTotalNumVGPRs(GPUKind AK, bool IsWave32) {
  const AMDGPUFeatureBitset &Features = getFeatureBitset(AK);
  if (Features.test(FEAT_GFX90A_INSTS))
    return 512;
  if (!Features.test(FEAT_GFX10_INSTS))
    return 256;
  if (Features.test(FEAT_1536_PHYSICAL_VGPRS))
    return IsWave32 ? 1536 : 768;
  return IsWave32 ? 1024 : 512;
}

unsigned AMDGPU::getTotalNumVGPRs(Triple::SubArchType SubArch, bool IsWave32) {
  return getTotalNumVGPRs(getGPUKindFromSubArch(SubArch), IsWave32);
}

unsigned AMDGPU::getAddressableNumVGPRs(GPUKind AK, bool IsWave32) {
  const AMDGPUFeatureBitset &Features = getFeatureBitset(AK);
  // The unified register file makes the AGPRs addressable as VGPRs.
  if (Features.test(FEAT_GFX90A_INSTS))
    return 512;
  if (Features.test(FEAT_1024_ADDRESSABLE_VGPRS))
    return IsWave32 ? 1024 : 512;
  return 256;
}

unsigned AMDGPU::getAddressableNumVGPRs(Triple::SubArchType SubArch,
                                        bool IsWave32) {
  return getAddressableNumVGPRs(getGPUKindFromSubArch(SubArch), IsWave32);
}

unsigned AMDGPU::getMaxHWAddressableLocalMemorySize(GPUKind AK) {
  const GPUInfo *Info = getAMDGPUInfo(AK);
  return Info ? Info->MaxHWAddressableLocalMemorySize : 32768;
}

unsigned
AMDGPU::getMaxHWAddressableLocalMemorySize(Triple::SubArchType SubArch) {
  return getMaxHWAddressableLocalMemorySize(getGPUKindFromSubArch(SubArch));
}

unsigned AMDGPU::getLocalMemorySize(GPUKind AK, bool FullSIMDMode) {
  // gfx6 and gfx10/11/12 address half of the physical block.
  unsigned Size = getMaxHWAddressableLocalMemorySize(AK);
  if (getFeatureBitset(AK).test(FEAT_HALF_ADDRESSABLE_PHYSICAL_LOCAL_MEMORY))
    Size *= 2;

  // In half-SIMD mode the work-group reaches only half of the block.
  if (!FullSIMDMode)
    Size /= 2;

  return Size;
}

unsigned AMDGPU::getLocalMemorySize(Triple::SubArchType SubArch,
                                    bool FullSIMDMode) {
  return getLocalMemorySize(getGPUKindFromSubArch(SubArch), FullSIMDMode);
}

unsigned AMDGPU::getAddressableLocalMemorySize(GPUKind AK, bool FullSIMDMode) {
  return std::min(getMaxHWAddressableLocalMemorySize(AK),
                  getLocalMemorySize(AK, FullSIMDMode));
}

unsigned AMDGPU::getAddressableLocalMemorySize(Triple::SubArchType SubArch,
                                               bool FullSIMDMode) {
  return getAddressableLocalMemorySize(getGPUKindFromSubArch(SubArch),
                                       FullSIMDMode);
}

unsigned AMDGPU::getLDSBankCount(GPUKind AK) {
  const GPUInfo *Info = getAMDGPUInfo(AK);
  return Info ? Info->LDSBankCount : 32;
}

unsigned AMDGPU::getLDSBankCount(Triple::SubArchType SubArch) {
  return getLDSBankCount(getGPUKindFromSubArch(SubArch));
}

std::optional<unsigned> AMDGPU::getBufferResourceNumRecordsWidth(GPUKind AK) {
  const GPUInfo *Info = getAMDGPUInfo(AK);
  if (!Info || Info->BufferResourceNumRecordsWidth == 0)
    return std::nullopt;
  return Info->BufferResourceNumRecordsWidth;
}

std::optional<unsigned>
AMDGPU::getBufferResourceNumRecordsWidth(Triple::SubArchType SubArch) {
  return getBufferResourceNumRecordsWidth(getGPUKindFromSubArch(SubArch));
}

unsigned AMDGPU::getLDSAllocGranule(GPUKind AK) {
  const AMDGPUFeatureBitset &Features = getFeatureBitset(AK);
  if (Features.none())
    return 256;
  assert((Features.test(FEAT_LDS_ALLOC_GRANULARITY_256) ||
          Features.test(FEAT_LDS_ALLOC_GRANULARITY_512) ||
          Features.test(FEAT_LDS_ALLOC_GRANULARITY_1024) ||
          Features.test(FEAT_LDS_ALLOC_GRANULARITY_1280) ||
          Features.test(FEAT_LDS_ALLOC_GRANULARITY_2048)) &&
         "missing LDS allocation granularity feature");
  if (Features.test(FEAT_LDS_ALLOC_GRANULARITY_256))
    return 256;
  if (Features.test(FEAT_LDS_ALLOC_GRANULARITY_512))
    return 512;
  if (Features.test(FEAT_LDS_ALLOC_GRANULARITY_1024))
    return 1024;
  if (Features.test(FEAT_LDS_ALLOC_GRANULARITY_1280))
    return 1280;
  if (Features.test(FEAT_LDS_ALLOC_GRANULARITY_2048))
    return 2048;

  return 256;
}

unsigned AMDGPU::getLDSAllocGranule(Triple::SubArchType SubArch) {
  return getLDSAllocGranule(getGPUKindFromSubArch(SubArch));
}

unsigned AMDGPU::getLDSEncodingGranule(GPUKind AK) {
  const AMDGPUFeatureBitset &Features = getFeatureBitset(AK);
  if (Features.test(FEAT_LDS_ENCODING_GRANULARITY_256))
    return 256;
  if (Features.test(FEAT_LDS_ENCODING_GRANULARITY_512))
    return 512;
  if (Features.test(FEAT_LDS_ENCODING_GRANULARITY_1024))
    return 1024;
  if (Features.test(FEAT_LDS_ENCODING_GRANULARITY_1280))
    return 1280;
  if (Features.test(FEAT_LDS_ENCODING_GRANULARITY_2048))
    return 2048;

  return 0;
}

unsigned AMDGPU::getLDSEncodingGranule(Triple::SubArchType SubArch) {
  return getLDSEncodingGranule(getGPUKindFromSubArch(SubArch));
}

unsigned AMDGPU::getMaxWavesPerEU(GPUKind AK) {
  const GPUInfo *Info = getAMDGPUInfo(AK);
  return Info ? Info->MaxWavesPerEU : 10;
}

unsigned AMDGPU::getMaxWavesPerEU(Triple::SubArchType SubArch) {
  return getMaxWavesPerEU(getGPUKindFromSubArch(SubArch));
}

StringRef AMDGPU::getCanonicalArchName(const Triple &T, StringRef Arch) {
  assert(T.isAMDGPU());
  auto ProcKind = T.isAMDGCN() ? parseArchAMDGCN(Arch) : parseArchR600(Arch);
  if (ProcKind == GK_NONE)
    return StringRef();

  return T.isAMDGCN() ? getArchNameAMDGCN(ProcKind) : getArchNameR600(ProcKind);
}

// Capability features clang queries via the feature bitset but must not
// serialize into the target-feature string.
//
// FIXME: This is hacky, we shouldn't have mismatches between the bitset and
// feature string map.
static const AMDGPUFeatureBitset FrontendOnlyFeatures = {
    FEAT_FAST_FMAF,
    FEAT_FAST_DENORMAL_F32,
    FEAT_SUPPORTS_WAVE32,
    FEAT_SUPPORTS_WGP,
    FEAT_XNACK_SUPPORT,
    FEAT_SRAMECC_SUPPORT,
    FEAT_XNACK_ON_OFF_MODES,
    FEAT_SRAMECC_ON_OFF_MODES,
    FEAT_APERTURE_REGS,
    FEAT_GET_DOORBELL_ID,
    FEAT_AGPR_ALLOC,
    FEAT_1536_PHYSICAL_VGPRS,
    FEAT_HALF_ADDRESSABLE_PHYSICAL_LOCAL_MEMORY,
    FEAT_1024_ADDRESSABLE_VGPRS,
    FEAT_LDS_ALLOC_GRANULARITY_256,
    FEAT_LDS_ALLOC_GRANULARITY_512,
    FEAT_LDS_ALLOC_GRANULARITY_1024,
    FEAT_LDS_ALLOC_GRANULARITY_1280,
    FEAT_LDS_ALLOC_GRANULARITY_2048,
    FEAT_LDS_ENCODING_GRANULARITY_256,
    FEAT_LDS_ENCODING_GRANULARITY_512,
    FEAT_LDS_ENCODING_GRANULARITY_1024,
    FEAT_LDS_ENCODING_GRANULARITY_1280,
    FEAT_LDS_ENCODING_GRANULARITY_2048};

// Add a GPU's features (minus the frontend-only ones) to \p Features. With \p
// Overwrite false, existing entries are kept so user -mattr overrides win.
static void addGPUFeatures(const GPUInfo &Info, bool Overwrite,
                           StringMap<bool> &Features) {
  SmallVector<StringRef, NUM_FEATURES> Names;
  getFeatureNames(Info.Features & ~FrontendOnlyFeatures, Names);
  for (StringRef Name : Names) {
    if (Overwrite)
      Features[Name] = true;
    else
      Features.insert({Name, true});
  }
}

/// Add a GPU's default features to \p Features (preserving user overrides) and
/// validate any requested wavesize.
static std::pair<FeatureError, StringRef>
fillAMDGCNFeatureMap(StringRef GPU, const Triple &T,
                     StringMap<bool> &Features) {
  // With no explicit GPU, the triple's subarch identifies the target.
  GPUKind Kind = GPU.empty() && T.getSubArch() != Triple::NoSubArch
                     ? getGPUKindFromSubArch(T.getSubArch())
                     : parseArchAMDGCN(GPU);
  const GPUInfo *Info = getAMDGPUInfo(Kind);

  // A bare subarch triple (no -target-cpu) still pins down the target, so it is
  // not a null GPU. The target's native wavesize (if single-mode) is in the
  // feature bitset; a dual-mode GPU has neither wave bit set.
  const bool IsNullGPU = T.getSubArch() == Triple::NoSubArch && GPU.empty();
  const bool TargetHasWave32 =
      Info && Info->Features.test(FEAT_WAVEFRONTSIZE32);
  const bool TargetHasWave64 =
      Info && Info->Features.test(FEAT_WAVEFRONTSIZE64);

  auto Wave32Itr = Features.find("wavefrontsize32");
  auto Wave64Itr = Features.find("wavefrontsize64");
  const bool EnableWave32 =
      Wave32Itr != Features.end() && Wave32Itr->getValue();
  const bool EnableWave64 =
      Wave64Itr != Features.end() && Wave64Itr->getValue();
  const bool DisableWave32 =
      Wave32Itr != Features.end() && !Wave32Itr->getValue();
  const bool DisableWave64 =
      Wave64Itr != Features.end() && !Wave64Itr->getValue();

  if (EnableWave32 && EnableWave64)
    return {AMDGPU::INVALID_FEATURE_COMBINATION,
            "'+wavefrontsize32' and '+wavefrontsize64' are mutually exclusive"};
  if (DisableWave32 && DisableWave64)
    return {AMDGPU::INVALID_FEATURE_COMBINATION,
            "'-wavefrontsize32' and '-wavefrontsize64' are mutually exclusive"};

  if (!IsNullGPU) {
    if (TargetHasWave64) {
      if (EnableWave32)
        return {AMDGPU::UNSUPPORTED_TARGET_FEATURE, "+wavefrontsize32"};
      if (DisableWave64)
        return {AMDGPU::UNSUPPORTED_TARGET_FEATURE, "-wavefrontsize64"};
    }

    if (TargetHasWave32) {
      if (EnableWave64)
        return {AMDGPU::UNSUPPORTED_TARGET_FEATURE, "+wavefrontsize64"};
      if (DisableWave32)
        return {AMDGPU::UNSUPPORTED_TARGET_FEATURE, "-wavefrontsize32"};
    }
  }

  // Don't assume any wavesize with an unknown subtarget.
  // Default to wave32 if target supports both.
  if (!IsNullGPU && !EnableWave32 && !EnableWave64 && !TargetHasWave32 &&
      !TargetHasWave64)
    Features.insert({"wavefrontsize32", true});

  // Merge the target defaults, keeping any user -mattr overrides.
  if (Info)
    addGPUFeatures(*Info, /*Overwrite=*/false, Features);

  return {NO_ERROR, StringRef()};
}

/// Fills Features map with default values for given target GPU.
/// \p Features contains overriding target features and this function returns
/// default target features with entries overridden by \p Features.
std::pair<FeatureError, StringRef>
AMDGPU::fillAMDGPUFeatureMap(StringRef GPU, const Triple &T,
                             StringMap<bool> &Features) {
  // XXX - What does the member GPU mean if device name string passed here?
  if (T.isSPIRV() && T.getOS() == Triple::OSType::AMDHSA) {
    // AMDGCN SPIRV must support the union of all AMDGCN features.
    SmallVector<StringRef> GPUs;
    fillValidArchListAMDGCN(GPUs);
    for (StringRef G : GPUs)
      if (const GPUInfo *Info = getAMDGPUInfo(parseArchAMDGCN(G)))
        addGPUFeatures(*Info, /*Overwrite=*/true, Features);
    Features["wavefrontsize32"] = true;
    Features["wavefrontsize64"] = true;
  } else if (T.isAMDGCN()) {
    return fillAMDGCNFeatureMap(GPU, T, Features);
  } else {
    if (GPU.empty())
      GPU = "r600";

    switch (llvm::AMDGPU::parseArchR600(GPU)) {
    case GK_CAYMAN:
    case GK_CYPRESS:
    case GK_RV770:
    case GK_RV670:
      // TODO: Add fp64 when implemented.
      break;
    case GK_TURKS:
    case GK_CAICOS:
    case GK_BARTS:
    case GK_SUMO:
    case GK_REDWOOD:
    case GK_JUNIPER:
    case GK_CEDAR:
    case GK_RV730:
    case GK_RV710:
    case GK_RS880:
    case GK_R630:
    case GK_R600:
      break;
    default:
      llvm_unreachable("Unhandled GPU!");
    }
  }
  return {NO_ERROR, StringRef()};
}

TargetID::TargetID(GPUKind Arch, const Triple &TT, TargetIDSetting XnackSetting,
                   TargetIDSetting SramEccSetting)
    : Arch(Arch),
      TargetTripleString(TT.normalize(Triple::CanonicalForm::FOUR_IDENT)),
      XnackSetting(XnackSetting), SramEccSetting(SramEccSetting),
      IsAMDHSA(TT.getOS() == Triple::AMDHSA) {}

// Parse a feature modifier sign ("+"/"-"). Returns "Unsupported" if \p Sign is
// neither (i.e. the modifier is malformed).
static TargetIDSetting getTargetIDSettingFromFeatureString(StringRef Sign) {
  if (Sign == "+")
    return TargetIDSetting::On;
  if (Sign == "-")
    return TargetIDSetting::Off;

  return TargetIDSetting::Unsupported;
}

// Derive the architecture from the processor name in \p TargetIDStr. "generic"
// and the empty processor name act as a wildcard.
static GPUKind getGPUKindFromTargetID(const Triple &TT, StringRef TargetIDStr) {
  StringRef CPUName = TargetIDStr.split(':').first;
  return (CPUName.empty() || CPUName == "generic")
             ? getGPUKindFromSubArch(TT.getSubArch())
             : parseArchAMDGCN(CPUName);
}

// Compute the default xnack/sramecc settings for processor \p Arch, before any
// explicit feature modifiers are applied.
static void getDefaultTargetIDFeatures(GPUKind Arch,
                                       TargetIDSetting &XnackSetting,
                                       TargetIDSetting &SramEccSetting) {
  const AMDGPUFeatureBitset &Features = getFeatureBitset(Arch);
  // Features with on/off modes default to Any; supported without on/off modes
  // is hardwired On; unsupported is Unsupported.
  if (!Features.test(FEAT_XNACK_SUPPORT))
    XnackSetting = TargetIDSetting::Unsupported;
  else if (Features.test(FEAT_XNACK_ON_OFF_MODES))
    XnackSetting = TargetIDSetting::Any;
  else
    XnackSetting = TargetIDSetting::On;
  if (!Features.test(FEAT_SRAMECC_SUPPORT))
    SramEccSetting = TargetIDSetting::Unsupported;
  else if (Features.test(FEAT_SRAMECC_ON_OFF_MODES))
    SramEccSetting = TargetIDSetting::Any;
  else
    SramEccSetting = TargetIDSetting::On;
}

// Compute the xnack/sramecc settings for processor \p Arch from the
// processor+features string \p TargetIDStr
// (e.g. "gfx90a:xnack+:sramecc-"). Returns false if a modifier names an unknown
// or repeated feature, names one the processor does not support, or has a
// malformed sign.
static bool computeTargetIDFeatures(GPUKind Arch, StringRef TargetIDStr,
                                    TargetIDSetting &XnackSetting,
                                    TargetIDSetting &SramEccSetting) {
  const AMDGPUFeatureBitset &Features = getFeatureBitset(Arch);
  getDefaultTargetIDFeatures(Arch, XnackSetting, SramEccSetting);

  // The first component is the processor; the rest are feature modifiers of the
  // form "<feature><+|->".
  SmallVector<StringRef, 3> Split;
  TargetIDStr.split(Split, ':');
  bool SeenXnack = false;
  bool SeenSramEcc = false;
  bool Valid = true;
  for (unsigned I = 1, E = Split.size(); I != E; ++I) {
    StringRef FeatureString = Split[I];
    if (FeatureString.consume_front("xnack")) {
      TargetIDSetting Sign = getTargetIDSettingFromFeatureString(FeatureString);
      // An xnack modifier is only valid with on/off modes: rejected when xnack
      // is unsupported or hardwired on (e.g. gfx1250).
      if (SeenXnack || !Features.test(FEAT_XNACK_ON_OFF_MODES) ||
          Sign == TargetIDSetting::Unsupported)
        Valid = false;
      else
        XnackSetting = Sign;
      SeenXnack = true;
    } else if (FeatureString.consume_front("sramecc")) {
      TargetIDSetting Sign = getTargetIDSettingFromFeatureString(FeatureString);
      if (SeenSramEcc || !Features.test(FEAT_SRAMECC_ON_OFF_MODES) ||
          Sign == TargetIDSetting::Unsupported)
        Valid = false;
      else
        SramEccSetting = Sign;
      SeenSramEcc = true;
    } else {
      // Unknown feature name.
      Valid = false;
    }
  }
  return Valid;
}

TargetID::TargetID(const Triple &TT, StringRef TargetIDStr)
    : TargetID(getGPUKindFromTargetID(TT, TargetIDStr), TT,
               TargetIDSetting::Unsupported, TargetIDSetting::Unsupported) {
  // Derive the feature settings from the string. Validity is not checked here;
  // parseTargetIDString validates untrusted input.
  computeTargetIDFeatures(Arch, TargetIDStr, XnackSetting, SramEccSetting);
}

TargetID TargetID::createFromSubtargetFeatures(const Triple &TT, StringRef CPU,
                                               StringRef FeatureString) {
  GPUKind Arch = parseArchAMDGCN(CPU);
  TargetIDSetting XnackSetting, SramEccSetting;
  getDefaultTargetIDFeatures(Arch, XnackSetting, SramEccSetting);

  // Apply the +/-xnack and +/-sramecc modifiers from the feature string, only
  // for targets that can toggle the corresponding mode.
  bool XnackToggleable = XnackSetting == TargetIDSetting::Any;
  bool SramEccToggleable = SramEccSetting == TargetIDSetting::Any;
  SmallVector<StringRef, 4> Features;
  FeatureString.split(Features, ',', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
  for (StringRef Feature : Features) {
    TargetIDSetting Sign =
        getTargetIDSettingFromFeatureString(Feature.take_front());
    if (Sign == TargetIDSetting::Unsupported)
      continue;
    StringRef Name = Feature.drop_front();
    if (Name == "xnack" && XnackToggleable)
      XnackSetting = Sign;
    else if (Name == "sramecc" && SramEccToggleable)
      SramEccSetting = Sign;
  }

  return TargetID(Arch, TT, XnackSetting, SramEccSetting);
}

std::optional<TargetID> TargetID::parse(const Triple &TT,
                                        StringRef ProcAndFeatures) {
  if (!TT.isAMDGCN())
    return std::nullopt;

  // Filter out unrecognized subarch suffixes.
  if (TT.getSubArch() == Triple::NoSubArch && TT.getArchName() != "amdgcn")
    return std::nullopt;

  // A named processor (i.e. not the empty/generic wildcard, which is resolved
  // from the triple's subarch) must be a recognized GPU that is consistent with
  // the triple's subarch.
  StringRef CPUName = ProcAndFeatures.split(':').first;
  if (!CPUName.empty() && CPUName != "generic" &&
      !isCPUValidForSubArch(TT.getSubArch(), CPUName))
    return std::nullopt;

  // Parse the processor and its feature modifiers, then construct directly from
  // the resulting fields.
  GPUKind Arch = getGPUKindFromTargetID(TT, ProcAndFeatures);
  TargetIDSetting XnackSetting, SramEccSetting;
  if (!computeTargetIDFeatures(Arch, ProcAndFeatures, XnackSetting,
                               SramEccSetting))
    return std::nullopt;

  return TargetID(Arch, TT, XnackSetting, SramEccSetting);
}

std::optional<TargetID>
TargetID::parseTargetIDString(StringRef TargetIDDirective) {
  // Split on '-' to get arch-vendor-os-environment-processor:features. There is
  // a single dash separator after the 4-component triple, so the
  // processor+features field must be present (even if empty).
  SmallVector<StringRef, 5> Parts;
  TargetIDDirective.split(Parts, '-', /*MaxSplit=*/4);
  if (Parts.size() < 5)
    return std::nullopt;

  return parse(Triple(Parts[0], Parts[1], Parts[2], Parts[3]), Parts[4]);
}

// Returns true if \p Arch hardwires xnack on (supports xnack but has no on/off
// modes, e.g. gfx1250), so xnack is not a selectable target-id modifier.
static bool isXnackHardwiredOn(GPUKind Arch) {
  const AMDGPUFeatureBitset &Features = getFeatureBitset(Arch);
  return Features.test(FEAT_XNACK_SUPPORT) &&
         !Features.test(FEAT_XNACK_ON_OFF_MODES);
}

static bool isSramEccHardwiredOn(GPUKind Arch) {
  const AMDGPUFeatureBitset &Features = getFeatureBitset(Arch);
  return Features.test(FEAT_SRAMECC_SUPPORT) &&
         !Features.test(FEAT_SRAMECC_ON_OFF_MODES);
}

// Append the explicit (On/Off) sramecc/xnack feature modifiers in canonical
// order, e.g. ":sramecc-:xnack+". Hardwired-on features are never emitted.
static void printFeatureModifiers(raw_ostream &OS, TargetIDSetting SramEcc,
                                  TargetIDSetting Xnack,
                                  bool SramEccHardwiredOn,
                                  bool XnackHardwiredOn) {
  if (!SramEccHardwiredOn) {
    if (SramEcc == TargetIDSetting::Off)
      OS << ":sramecc-";
    else if (SramEcc == TargetIDSetting::On)
      OS << ":sramecc+";
  }

  if (XnackHardwiredOn)
    return;

  if (Xnack == TargetIDSetting::Off)
    OS << ":xnack-";
  else if (Xnack == TargetIDSetting::On)
    OS << ":xnack+";
}

void TargetID::print(raw_ostream &StreamRep) const {
  StreamRep << TargetTripleString << '-' << getArchNameAMDGCN(Arch);

  if (IsAMDHSA) {
    printFeatureModifiers(StreamRep, getSramEccSetting(), getXnackSetting(),
                          isSramEccHardwiredOn(Arch), isXnackHardwiredOn(Arch));
  }
}

std::string TargetID::toString() const {
  std::string Str;
  raw_string_ostream OS(Str);
  OS << *this;
  return Str;
}

void TargetID::printCanonicalTargetIDString(raw_ostream &OS) const {
  OS << getArchNameAMDGCN(Arch);
  printFeatureModifiers(OS, getSramEccSetting(), getXnackSetting(),
                        isSramEccHardwiredOn(Arch), isXnackHardwiredOn(Arch));
}

std::string TargetID::getCanonicalFeatureString() const {
  std::string Str;
  raw_string_ostream OS(Str);
  printCanonicalTargetIDString(OS);
  return Str;
}

bool TargetID::operator==(const TargetID &Other) const {
  return Arch == Other.Arch && XnackSetting == Other.XnackSetting &&
         SramEccSetting == Other.SramEccSetting && IsAMDHSA == Other.IsAMDHSA &&
         TargetTripleString == Other.TargetTripleString;
}

static bool featureProvidesFor(TargetIDSetting Provided,
                               TargetIDSetting Requested) {
  return Provided == TargetIDSetting::Any ||
         Provided == TargetIDSetting::Unsupported || Provided == Requested;
}

bool TargetID::isEquivalent(const TargetID &Other) const {
  // The processor and feature settings must match exactly
  if (Arch != Other.Arch || XnackSetting != Other.XnackSetting ||
      SramEccSetting != Other.SramEccSetting)
    return false;

  return Triple(getTargetTripleString())
      .isCompatibleWith(Triple(Other.getTargetTripleString()));
}

bool TargetID::providesFor(const TargetID &Other) const {
  // A major-family/generic processor (e.g. amdgpu9) provides for a specific
  // member of its family (e.g. gfx900), but not the reverse. Otherwise the
  // processors must match.
  if (Arch != Other.Arch && Arch != GK_NONE && Other.Arch != GK_NONE) {
    Triple::SubArchType ThisSubArch = getSubArch(Arch);
    if (ThisSubArch != getMajorSubArch(ThisSubArch) ||
        ThisSubArch != getMajorSubArch(getSubArch(Other.Arch)))
      return false;
  }

  if (!featureProvidesFor(XnackSetting, Other.XnackSetting) ||
      !featureProvidesFor(SramEccSetting, Other.SramEccSetting))
    return false;

  return Triple(getTargetTripleString())
      .isCompatibleWith(Triple(Other.getTargetTripleString()));
}
