[llvm-branch-commits] [llvm] AMDGPU: Remove xnack and sramecc subtarget features (PR #212792)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Jul 29 08:18:02 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-amdgpu

Author: Matt Arsenault (arsenm)

<details>
<summary>Changes</summary>

Now that these are controlled by module flags, the subtarget
features were just used for assembler and disassembler controls.
Now that the assembler and disassembler can infer these from
the e_flags and target directives, they are no longer necessary.

Co-authored-by: Claude (Opus 4.8) <noreply@<!-- -->anthropic.com>

---

Patch is 59.89 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/212792.diff


27 Files Affected:

- (modified) llvm/docs/AMDGPUUsage.rst (+7) 
- (modified) llvm/lib/Target/AMDGPU/AMDGPU.td (+2-24) 
- (modified) llvm/lib/Target/AMDGPU/AMDGPUTargetParser.td (+1-1) 
- (modified) llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp (+1-2) 
- (modified) llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp (+20-6) 
- (modified) llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h (+2-3) 
- (modified) llvm/lib/Target/AMDGPU/GCNSubtarget.h (+1-3) 
- (modified) llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp (+1-2) 
- (modified) llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp (+27-71) 
- (modified) llvm/lib/TargetParser/AMDGPUTargetParser.cpp (+29-8) 
- (modified) llvm/test/MC/AMDGPU/amdgcn-target-directive-conflict.s (+30-16) 
- (modified) llvm/test/MC/AMDGPU/amdgcn_target_directive_from_eflags.s (+44-14) 
- (modified) llvm/test/MC/AMDGPU/hsa-diag-v4.s (+4-4) 
- (modified) llvm/test/MC/AMDGPU/hsa-tg-split.s (+2-2) 
- (modified) llvm/test/MC/AMDGPU/hsa-v4.s (+2-2) 
- (modified) llvm/test/MC/AMDGPU/hsa-v5-uses-dynamic-stack.s (+4-4) 
- (modified) llvm/test/MC/AMDGPU/user-sgpr-count.s (+1-1) 
- (modified) llvm/test/MC/AMDGPU/xnack-mask.s (+3-3) 
- (modified) llvm/test/tools/llvm-objdump/ELF/AMDGPU/kd-cov5.s (+3-3) 
- (modified) llvm/test/tools/llvm-objdump/ELF/AMDGPU/kd-gfx10.s (+16-12) 
- (modified) llvm/test/tools/llvm-objdump/ELF/AMDGPU/kd-gfx90a.s (+12-9) 
- (modified) llvm/test/tools/llvm-objdump/ELF/AMDGPU/kd-gfx950.s (+5-3) 
- (modified) llvm/test/tools/llvm-objdump/ELF/AMDGPU/kd-sgpr.s (+12-9) 
- (modified) llvm/test/tools/llvm-objdump/ELF/AMDGPU/kd-vgpr.s (+12-9) 
- (modified) llvm/test/tools/llvm-objdump/ELF/AMDGPU/kd-zeroed-gfx10.s (+2-1) 
- (modified) llvm/test/tools/llvm-objdump/ELF/AMDGPU/kd-zeroed-gfx9.s (+4-3) 
- (modified) llvm/test/tools/llvm-objdump/ELF/AMDGPU/kd-zeroed-raw.s (+5-3) 


``````````diff
diff --git a/llvm/docs/AMDGPUUsage.rst b/llvm/docs/AMDGPUUsage.rst
index 2a4f290effc6d..4f91f7ffb69ac 100644
--- a/llvm/docs/AMDGPUUsage.rst
+++ b/llvm/docs/AMDGPUUsage.rst
@@ -1014,6 +1014,13 @@ consumed by the AMDGPU backend during code generation.
        produce an error. Modules with **any** (absent flag) are compatible
        with any setting.
 
+       XNACK is disabled if ``SH_MEM_CONFIG.ADDRESS_MODE = GPUVM`` on chips
+       that support XNACK. The current default kernel driver setting is XNACK
+       disabled on the graphics ring and XNACK enabled on the compute ring.
+       If XNACK is enabled, the VMEM latency can be worse. If XNACK is
+       disabled, the 2 SGPRs otherwise reserved for the XNACK mask can be used
+       for general purposes.
+
    * - ``amdgpu.sramecc``
      - ``i32``
      - Error
diff --git a/llvm/lib/Target/AMDGPU/AMDGPU.td b/llvm/lib/Target/AMDGPU/AMDGPU.td
index fbfd0e2f6937f..374204f7224dc 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPU.td
+++ b/llvm/lib/Target/AMDGPU/AMDGPU.td
@@ -223,21 +223,6 @@ defm XNACKOnOffModes : AMDGPUSubtargetFeature<"xnack-on-off-modes",
   InlineIgnore
 >;
 
-// XNACK is disabled if SH_MEM_CONFIG.ADDRESS_MODE = GPUVM on chips that support
-// XNACK. The current default kernel driver setting is:
-// - graphics ring: XNACK disabled
-// - compute ring: XNACK enabled
-//
-// If XNACK is enabled, the VMEM latency can be worse.
-// If XNACK is disabled, the 2 SGPRs can be used for general purposes.
-def FeatureXNACK : SubtargetFeature<"xnack",
-  "EnableXNACK",
-  "true",
-  "Enable XNACK support",
-  [FeatureSupportsXNACK],
-  InlineIgnore
->;
-
 def FeatureCuMode : SubtargetFeature<"cumode",
   "EnableCuMode",
   "true",
@@ -1080,12 +1065,6 @@ def FeatureSupportsSRAMECC : SubtargetFeature<"sramecc-support",
   [], InlineIgnore
 >;
 
-def FeatureSRAMECC : SubtargetFeature<"sramecc",
-  "EnableSRAMECC",
-  "true",
-  "Enable SRAMECC"
->;
-
 defm NoSdstCMPX : AMDGPUSubtargetFeature<"no-sdst-cmpx",
   "V_CMPX does not write VCC/SGPR in addition to EXEC"
 >;
@@ -2273,7 +2252,7 @@ def FeatureISAVersion12_50_Common : FeatureSet<
    FeatureSetPrioIncWgInst,
    FeatureSWakeupBarrier,
    Feature45BitNumRecordsBufferResource,
-   FeatureXNACK,
+   FeatureSupportsXNACK,
    FeatureClusters,
    FeatureD16Writes32BitVgpr,
    FeatureMcastLoadInsts,
@@ -2347,7 +2326,6 @@ def FeatureISAVersion12_5_Generic: FeatureSet<
   [FeatureAddressableLocalMemorySize327680,
    FeatureSetregVGPRMSBFixup,
    FeatureRequiresCOV6,
-   FeatureSupportsXNACK,
    FeatureGFX125xLowestRateWMMA,
    FeatureTransCoexecutionHazard,
    FeatureWMMACoexecutionHazards,
@@ -2799,7 +2777,7 @@ def HasUnrestrictedSOffset : Predicate<"!Subtarget->hasRestrictedSOffset()">,
 
 def D16PreservesUnusedBits :
   Predicate<"Subtarget->d16PreservesUnusedBits()">,
-  AssemblerPredicate<(all_of FeatureGFX9Insts, (not FeatureSRAMECC))>;
+  AssemblerPredicate<(all_of FeatureGFX9Insts, (not FeatureSupportsSRAMECC))>;
 
 def LDSRequiresM0Init : Predicate<"Subtarget->ldsRequiresM0Init()">;
 def NotLDSRequiresM0Init : Predicate<"!Subtarget->ldsRequiresM0Init()">;
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetParser.td b/llvm/lib/Target/AMDGPU/AMDGPUTargetParser.td
index d03493d924b13..a11dd460407ca 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUTargetParser.td
+++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetParser.td
@@ -12,7 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 // FIXME: These duplicate real SubtargetFeatures and should be unified
-// (e.g. FEATURE_XNACK mirrors FeatureXNACK).
+// (e.g. R600_FEATURE_FMA mirrors FeatureFMA).
 class AMDGPUArchFeature<string spelling> {
   string Spelling = spelling;
 }
diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
index d3027d831aaf1..f040f07fb81dc 100644
--- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
+++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
@@ -6297,8 +6297,7 @@ bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() {
         return Error(IDRange.Start, "directive requires gfx8+", IDRange);
       if (!isUInt<1>(Val))
         return OutOfRangeError(ValRange);
-      bool XnackOn = getTargetStreamer().getTargetID()->isXnackOnOrAny() ||
-                     getSTI().hasFeature(AMDGPU::FeatureXNACK);
+      bool XnackOn = getTargetStreamer().getTargetID()->isXnackOnOrAny();
       if (Val != XnackOn) {
         return getParser().Error(
             IDRange.Start,
diff --git a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
index c9f4624014a5e..eb7999f102a6f 100644
--- a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
+++ b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
@@ -60,6 +60,7 @@ AMDGPUDisassembler::AMDGPUDisassembler(const MCSubtargetInfo &STI,
       MAI(Ctx.getAsmInfo()),
       HwModeRegClass(STI.getHwMode(MCSubtargetInfo::HwMode_RegInfo)),
       TargetMaxInstBytes(MAI.getMaxInstLength(&STI)),
+      TargetID(AMDGPU::createAMDGPUTargetID(STI, "")),
       CodeObjectVersion(AMDGPU::getDefaultAMDHSACodeObjectVersion()) {
   // ToDo: AMDGPUDisassembler supports only VI ISA.
   if (!STI.hasFeature(AMDGPU::FeatureGCN3Encoding) && !isGFX10Plus())
@@ -98,32 +99,46 @@ void AMDGPUDisassembler::emitTargetIDIfSupported(raw_ostream &OS,
   }
 #undef X
 
-  // Add xnack and sramecc from ELF flags (v4 format)
+  // Add xnack and sramecc from ELF flags (v4 format), recording the decoded
+  // modes in TargetID for later use (e.g. .amdhsa_reserve_xnack_mask).
   if (CodeObjectVersion >= AMDGPU::AMDHSA_COV4) {
     unsigned SrameccSetting = EFlags & ELF::EF_AMDGPU_FEATURE_SRAMECC_V4;
     switch (SrameccSetting) {
     case ELF::EF_AMDGPU_FEATURE_SRAMECC_UNSUPPORTED_V4:
+      break;
     case ELF::EF_AMDGPU_FEATURE_SRAMECC_ANY_V4:
+      TargetID.setSramEccSetting(AMDGPU::TargetIDSetting::Any);
       break;
     case ELF::EF_AMDGPU_FEATURE_SRAMECC_OFF_V4:
+      TargetID.setSramEccSetting(AMDGPU::TargetIDSetting::Off);
       OS << ":sramecc-";
       break;
     case ELF::EF_AMDGPU_FEATURE_SRAMECC_ON_V4:
+      TargetID.setSramEccSetting(AMDGPU::TargetIDSetting::On);
       OS << ":sramecc+";
       break;
     }
 
+    // Targets that hardwire xnack on (e.g. gfx1250) don't expose it as a
+    // selectable modifier, so don't print it.
+    bool XnackHardwiredOn = TargetID.isXnackSupported() &&
+                            !STI.hasFeature(AMDGPU::FeatureXNACKOnOffModes);
     unsigned XnackSetting = EFlags & ELF::EF_AMDGPU_FEATURE_XNACK_V4;
     switch (XnackSetting) {
     case ELF::EF_AMDGPU_FEATURE_XNACK_UNSUPPORTED_V4:
+      break;
     case ELF::EF_AMDGPU_FEATURE_XNACK_ANY_V4:
+      TargetID.setXnackSetting(AMDGPU::TargetIDSetting::Any);
       break;
     case ELF::EF_AMDGPU_FEATURE_XNACK_OFF_V4:
-      OS << ":xnack-";
+      TargetID.setXnackSetting(AMDGPU::TargetIDSetting::Off);
+      if (!XnackHardwiredOn)
+        OS << ":xnack-";
       break;
     case ELF::EF_AMDGPU_FEATURE_XNACK_ON_V4:
-      OS << ":xnack+";
-      XnackOnFromEFlags = true;
+      TargetID.setXnackSetting(AMDGPU::TargetIDSetting::On);
+      if (!XnackHardwiredOn)
+        OS << ":xnack+";
       break;
     }
   }
@@ -2472,8 +2487,7 @@ Expected<bool> AMDGPUDisassembler::decodeCOMPUTE_PGM_RSRC1(
   // Only print the directive on xnack-supporting targets (matching the
   // asmprinter), unless the binary erronously set xnack on an unsupported
   // target
-  bool ReservedXnackMask =
-      STI.hasFeature(AMDGPU::FeatureXNACK) || XnackOnFromEFlags;
+  bool ReservedXnackMask = TargetID.isXnackOnOrAny();
   if (STI.hasFeature(AMDGPU::FeatureSupportsXNACK) || ReservedXnackMask) {
     KdStream << Indent << ".amdhsa_reserve_xnack_mask " << ReservedXnackMask
              << '\n';
diff --git a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h
index c38637020782a..5277de4cacff4 100644
--- a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h
+++ b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h
@@ -22,6 +22,7 @@
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCInstrInfo.h"
 #include "llvm/Support/DataExtractor.h"
+#include "llvm/TargetParser/AMDGPUTargetParser.h"
 #include <memory>
 
 namespace llvm {
@@ -47,9 +48,7 @@ class AMDGPUDisassembler : public MCDisassembler {
   mutable uint64_t Literal;
   mutable bool HasLiteral;
   mutable std::optional<bool> EnableWavefrontSize32;
-
-  // If the object's ELF e_flags enable xnack. TODO: Replace with TargetID
-  mutable bool XnackOnFromEFlags = false;
+  mutable AMDGPU::TargetID TargetID;
   unsigned CodeObjectVersion;
   const MCExpr *UCVersionW64Expr;
   const MCExpr *UCVersionW32Expr;
diff --git a/llvm/lib/Target/AMDGPU/GCNSubtarget.h b/llvm/lib/Target/AMDGPU/GCNSubtarget.h
index c7937d8d33ed5..647c36e7409a7 100644
--- a/llvm/lib/Target/AMDGPU/GCNSubtarget.h
+++ b/llvm/lib/Target/AMDGPU/GCNSubtarget.h
@@ -352,9 +352,7 @@ class GCNSubtarget final : public AMDGPUGenSubtargetInfo,
     return HasUnalignedScratchAccess && HasUnalignedAccessMode;
   }
 
-  bool isXNACKEnabled() const {
-    return enableXNACK() || TargetID.isXnackOnOrAny();
-  }
+  bool isXNACKEnabled() const { return TargetID.isXnackOnOrAny(); }
 
   bool hasRelaxedBufferOOBMode() const { return BufferOOBRelaxed; }
   bool hasRelaxedTBufferOOBMode() const { return TBufferOOBRelaxed; }
diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp
index ea752e44b7fad..b5cedeaf6321e 100644
--- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp
+++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp
@@ -564,8 +564,7 @@ void AMDGPUTargetAsmStreamer::EmitAmdhsaKernelDescriptor(
   case AMDGPU::AMDHSA_COV4:
   case AMDGPU::AMDHSA_COV5:
     if (STI.hasFeature(AMDGPU::FeatureSupportsXNACK)) {
-      bool XnackOn = getTargetID()->isXnackOnOrAny() ||
-                     STI.hasFeature(AMDGPU::FeatureXNACK);
+      bool XnackOn = getTargetID()->isXnackOnOrAny();
       OS << "\t\t.amdhsa_reserve_xnack_mask " << XnackOn << '\n';
     }
     break;
diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
index 25b36d99960a1..b271e3ebefd34 100644
--- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
@@ -1086,75 +1086,25 @@ VOPD::InstInfo getVOPDInstInfo(unsigned VOPDOpcode,
 
 TargetID createAMDGPUTargetID(const MCSubtargetInfo &STI,
                               StringRef FeatureString) {
-  TargetID TargetID(parseArchAMDGCN(STI.getCPU()), STI.getTargetTriple(),
-                    STI.getFeatureBits().test(FeatureXNACKOnOffModes)
-                        ? TargetIDSetting::Any
-                        : TargetIDSetting::Unsupported,
-                    STI.getFeatureBits().test(FeatureSupportsSRAMECC)
-                        ? TargetIDSetting::Any
-                        : TargetIDSetting::Unsupported);
-
-  // Check if xnack or sramecc is explicitly enabled or disabled.  In the
-  // absence of the target features we assume we must generate code that can run
-  // in any environment.
-  SubtargetFeatures Features(FeatureString);
-  std::optional<bool> XnackRequested;
-  std::optional<bool> SramEccRequested;
-
-  for (const std::string &Feature : Features.getFeatures()) {
-    if (Feature == "+xnack")
-      XnackRequested = true;
-    else if (Feature == "-xnack")
-      XnackRequested = false;
-    else if (Feature == "+sramecc")
-      SramEccRequested = true;
-    else if (Feature == "-sramecc")
-      SramEccRequested = false;
-  }
-
-  // Only allow changing xnack setting if the target supports on/off modes.
-  // Targets without on/off mode support keep their initial setting
-  // (Unsupported).
-
-  bool XnackSupported = STI.getFeatureBits().test(FeatureXNACKOnOffModes);
-  bool SramEccSupported = TargetID.isSramEccSupported();
-
-  if (XnackRequested) {
-    if (XnackSupported) {
-      TargetID.setXnackSetting(*XnackRequested ? TargetIDSetting::On
-                                               : TargetIDSetting::Off);
-    } else {
-      // If a specific xnack setting was requested and this GPU does not support
-      // xnack emit a warning. Setting will remain set to "Unsupported".
-      if (*XnackRequested) {
-        errs() << "warning: xnack 'On' was requested for a processor that does "
-                  "not support it!\n";
-      } else {
-        errs() << "warning: xnack 'Off' was requested for a processor that "
-                  "does not support it!\n";
-      }
-    }
-  }
-
-  if (SramEccRequested) {
-    if (SramEccSupported) {
-      TargetID.setSramEccSetting(*SramEccRequested ? TargetIDSetting::On
-                                                   : TargetIDSetting::Off);
-    } else {
-      // If a specific sramecc setting was requested and this GPU does not
-      // support sramecc emit a warning. Setting will remain set to
-      // "Unsupported".
-      if (*SramEccRequested) {
-        errs() << "warning: sramecc 'On' was requested for a processor that "
-                  "does not support it!\n";
-      } else {
-        errs() << "warning: sramecc 'Off' was requested for a processor that "
-                  "does not support it!\n";
-      }
-    }
-  }
+  // xnack/sramecc are derived from capability features alone; the actual mode
+  // comes later from module flags / directives / e_flags. A target supporting
+  // xnack without on/off modes has it hardwired On (gfx1250).
+  bool SupportsXNACK = STI.getFeatureBits().test(FeatureSupportsXNACK);
+  bool XNACKOnOffModes = STI.getFeatureBits().test(FeatureXNACKOnOffModes);
+
+  TargetIDSetting XnackSetting;
+  if (!SupportsXNACK)
+    XnackSetting = TargetIDSetting::Unsupported;
+  else if (XNACKOnOffModes)
+    XnackSetting = TargetIDSetting::Any;
+  else
+    XnackSetting = TargetIDSetting::On;
 
-  return TargetID;
+  return TargetID(parseArchAMDGCN(STI.getCPU()), STI.getTargetTriple(),
+                  XnackSetting,
+                  STI.getFeatureBits().test(FeatureSupportsSRAMECC)
+                      ? TargetIDSetting::Any
+                      : TargetIDSetting::Unsupported);
 }
 
 namespace IsaInfo {
@@ -1353,8 +1303,11 @@ unsigned getNumExtraSGPRs(const MCSubtargetInfo &STI, bool VCCUsed,
 
 unsigned getNumExtraSGPRs(const MCSubtargetInfo &STI, bool VCCUsed,
                           bool FlatScrUsed) {
-  return getNumExtraSGPRs(STI, VCCUsed, FlatScrUsed,
-                          STI.getFeatureBits().test(AMDGPU::FeatureXNACK));
+  // Without a TargetID mode, only hardwired-on xnack (gfx1250) is knowable from
+  // the subtarget, and it reserves SGPRs.
+  bool XNACKUsed = STI.getFeatureBits().test(AMDGPU::FeatureSupportsXNACK) &&
+                   !STI.getFeatureBits().test(AMDGPU::FeatureXNACKOnOffModes);
+  return getNumExtraSGPRs(STI, VCCUsed, FlatScrUsed, XNACKUsed);
 }
 
 static unsigned getGranulatedNumRegisterBlocks(unsigned NumRegs,
@@ -2478,7 +2431,10 @@ unsigned getDynamicVGPRBlockSize(const Function &F) {
 }
 
 bool hasXNACK(const MCSubtargetInfo &STI) {
-  return STI.hasFeature(AMDGPU::FeatureXNACK);
+  // Only hardwired-on xnack (gfx1250) is knowable from the subtarget alone;
+  // toggleable targets take their mode from the TargetID.
+  return STI.hasFeature(AMDGPU::FeatureSupportsXNACK) &&
+         !STI.hasFeature(AMDGPU::FeatureXNACKOnOffModes);
 }
 
 bool hasMIMG_R128(const MCSubtargetInfo &STI) {
diff --git a/llvm/lib/TargetParser/AMDGPUTargetParser.cpp b/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
index de6ed11f2d242..93263eda87300 100644
--- a/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
+++ b/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
@@ -1059,9 +1059,14 @@ static bool computeTargetIDFeatures(GPUKind Arch, StringRef TargetIDStr,
                                     TargetIDSetting &XnackSetting,
                                     TargetIDSetting &SramEccSetting) {
   unsigned ArchAttr = getArchAttrAMDGCN(Arch);
-  XnackSetting = (ArchAttr & FEATURE_XNACK_ON_OFF_MODES)
-                     ? TargetIDSetting::Any
-                     : TargetIDSetting::Unsupported;
+  // xnack with on/off modes defaults to Any; supported without on/off modes is
+  // hardwired On (e.g. gfx1250); unsupported is Unsupported.
+  if (!(ArchAttr & FEATURE_XNACK))
+    XnackSetting = TargetIDSetting::Unsupported;
+  else if (ArchAttr & FEATURE_XNACK_ON_OFF_MODES)
+    XnackSetting = TargetIDSetting::Any;
+  else
+    XnackSetting = TargetIDSetting::On;
   SramEccSetting = (ArchAttr & FEATURE_SRAMECC) ? TargetIDSetting::Any
                                                 : TargetIDSetting::Unsupported;
 
@@ -1076,7 +1081,9 @@ static bool computeTargetIDFeatures(GPUKind Arch, StringRef TargetIDStr,
     StringRef FeatureString = Split[I];
     if (FeatureString.consume_front("xnack")) {
       TargetIDSetting Sign = getTargetIDSettingFromFeatureString(FeatureString);
-      if (SeenXnack || XnackSetting == TargetIDSetting::Unsupported ||
+      // An xnack modifier is only valid with on/off modes: rejected when xnack
+      // is unsupported or hardwired on (e.g. gfx1250).
+      if (SeenXnack || !(ArchAttr & FEATURE_XNACK_ON_OFF_MODES) ||
           Sign == TargetIDSetting::Unsupported)
         Valid = false;
       else
@@ -1147,15 +1154,27 @@ TargetID::parseTargetIDString(StringRef TargetIDDirective) {
   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) {
+  unsigned ArchAttr = getArchAttrAMDGCN(Arch);
+  return (ArchAttr & FEATURE_XNACK) && !(ArchAttr & FEATURE_XNACK_ON_OFF_MODES);
+}
+
 // Append the explicit (On/Off) sramecc/xnack feature modifiers in canonical
-// order, e.g. ":sramecc-:xnack+".
+// order, e.g. ":sramecc-:xnack+". Xnack is never emitted for hardwired-on
+// targets.
 static void printFeatureModifiers(raw_ostream &OS, TargetIDSetting SramEcc,
-                                  TargetIDSetting Xnack) {
+                                  TargetIDSetting Xnack,
+                                  bool XnackHardwiredOn) {
   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)
@@ -1166,7 +1185,8 @@ void TargetID::print(raw_ostream &StreamRep) const {
   StreamRep << TargetTripleString << '-' << getArchNameAMDGCN(Arch);
 
   if (IsAMDHSA)
-    printFeatureModifiers(StreamRep, getSramEccSetting(), getXnackSetting());
+    printFeatureModifiers(StreamRep, getSramEccSetting(), getXnackSetting(),
+                          isXnackHardwiredOn(Arch));
 }
 
 std::string TargetID::toString() const {
@@ -1178,7 +1198,8 @@ std::string TargetID::toString() const {
 
 void TargetID::printCanonicalTargetIDString(raw_ostream &OS) const {
   OS << getArchNameAMDGCN(Arch);
-  printFeatureModifiers(OS, getSramEccSetting(), getXnackSetting());
+  printFeatureModifiers(OS, getSramEccSetting(), getXnackSetting(),
+                        isXnackHardwiredOn(Arch));
 }
 
 std::string TargetID::getCanonicalFeatureString() const {
diff --git a/llvm/test/MC/AMDGPU/amdgcn-target-directive-conflict.s b/llvm/test/MC/AMDGPU/amdgcn-target-directive-conflict.s
index 4a93666474116..73cc40fab9e41 100644
--- a/llvm/test/MC/AMDGPU/amdgcn-target-directive-conflict.s
+++ b/llvm/test/MC/AMDGPU/amdgcn-target-directive-conflict.s
@@ -1,55 +1,69 @@
 // RUN: split-file %s %t
 
 // Test that .amdgcn_target emits separate warnings for conflicting xnack and
-// sramecc settings between the directive and the command line.
+// sramecc settings between two .amdgcn_target directives. The first directive
+// establishes the target id's xnack/sramecc modes; a second directive with
+// different specific modes conflicts.
 
-// RUN: llvm-mc -triple=amdgpu9.08-amd-amdhsa -mattr=+xnack,+sramecc %t/xnack.s 2>&1 | FileCheck --check-prefix=XNACK --implicit-check-not=warning %s
-// RUN: llvm-mc -triple=amdgpu9.08-amd-amdhsa -m...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/212792


More information about the llvm-branch-commits mailing list