Skip to content

[AMDGPU] Add SRAMECC on/off mode capability - #225540

Open
chinmaydd wants to merge 1 commit into
mainfrom
users/chinmaydd/sramecc-on-off-modes
Open

chinmaydd wants to merge 1 commit into
mainfrom
users/chinmaydd/sramecc-on-off-modes

Conversation

@chinmaydd

@chinmaydd chinmaydd commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Distinguish SRAMECC hardware support from selectable on/off modes, mirroring XNACK. Preserve selectable modes on existing targets and use the new capability for target-ID validation, defaults and printing, module flags, and disassembly.

Assisted by: Codex (Astra)

Distinguish SRAMECC hardware support from selectable on/off modes, mirroring XNACK. Preserve selectable modes on existing targets and use the new capability for target-ID validation, defaults and printing, module flags, and disassembly.

Expose the generated frontend capability as read only and exclude it from serialized target features. Add parser, driver, frontend, and disassembler coverage and document module-flag behavior.

Change-Id: I9b212be27631106749fe54c3bd88a1c72a1fefc3
Validation: rebuilt Clang and LLVM tools; 30 AMDGPU TargetParser unit tests and 22 focused lit tests passed.
@chinmaydd
chinmaydd marked this pull request as ready for review September 23, 2026 16:38
@llvmorg-github-actions llvmorg-github-actions Bot added backend:AMDGPU clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Sep 23, 2026
@llvmorg-github-actions

llvmorg-github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

@llvm/pr-subscribers-clang-driver

@llvm/pr-subscribers-backend-amdgpu

Author: Chinmay Deshpande (chinmaydd)

Changes

Distinguish SRAMECC hardware support from selectable on/off modes, mirroring XNACK. Preserve selectable modes on existing targets and use the new capability for target-ID validation, defaults and printing, module flags, and disassembly.

Assisted by: Codex (Astra)


Full diff: https://github.com/llvm/llvm-project/pull/225540.diff

12 Files Affected:

  • (modified) clang/lib/Basic/TargetID.cpp (+2-2)
  • (modified) clang/lib/Basic/Targets/AMDGPU.cpp (+1-1)
  • (modified) clang/test/CodeGenOpenCL/amdgpu-features-readonly.cl (+7)
  • (modified) clang/test/Driver/amdgpu-xnack-sramecc-flags.c (+6)
  • (modified) llvm/docs/AMDGPUUsage.rst (+2-1)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPU.td (+13-4)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp (+1-1)
  • (modified) llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp (+7-2)
  • (modified) llvm/lib/Target/AMDGPU/GCNSubtarget.cpp (+3-2)
  • (modified) llvm/lib/TargetParser/AMDGPUTargetParser.cpp (+26-14)
  • (modified) llvm/test/MC/AMDGPU/amdgcn_target_directive_from_eflags.s (+4)
  • (modified) llvm/unittests/TargetParser/TargetParserTest.cpp (+56)
diff --git a/clang/lib/Basic/TargetID.cpp b/clang/lib/Basic/TargetID.cpp
index cc3c302bd9e76..8db670a2fd8e5 100644
--- a/clang/lib/Basic/TargetID.cpp
+++ b/clang/lib/Basic/TargetID.cpp
@@ -32,9 +32,9 @@ getAllPossibleAMDGPUTargetIDFeatures(const llvm::Triple &T,
     return Ret;
   const llvm::AMDGPU::AMDGPUFeatureBitset &Features =
       llvm::AMDGPU::getFeatureBitset(ProcKind);
-  if (Features.test(llvm::AMDGPU::FEAT_SRAMECC_SUPPORT))
+  // Only allow features in target IDs if the processor supports on/off modes.
+  if (Features.test(llvm::AMDGPU::FEAT_SRAMECC_ON_OFF_MODES))
     Ret.push_back("sramecc");
-  // Only allow xnack in target ID if the processor supports on/off modes.
   if (Features.test(llvm::AMDGPU::FEAT_XNACK_ON_OFF_MODES))
     Ret.push_back("xnack");
   return Ret;
diff --git a/clang/lib/Basic/Targets/AMDGPU.cpp b/clang/lib/Basic/Targets/AMDGPU.cpp
index c01e4c8074b24..c3e6f8bbcafa8 100644
--- a/clang/lib/Basic/Targets/AMDGPU.cpp
+++ b/clang/lib/Basic/Targets/AMDGPU.cpp
@@ -238,7 +238,7 @@ AMDGPUTargetInfo::AMDGPUTargetInfo(const llvm::Triple &Triple,
 
   for (auto F : {"image-insts", "gws", "vmem-to-lds-load-insts", "supports-wgp",
                  "supports-wave32", "xnack-support", "sramecc-support",
-                 "xnack-on-off-modes"}) {
+                 "xnack-on-off-modes", "sramecc-on-off-modes"}) {
     if (GPUKind != llvm::AMDGPU::GK_NONE)
       ReadOnlyFeatures.insert(F);
   }
diff --git a/clang/test/CodeGenOpenCL/amdgpu-features-readonly.cl b/clang/test/CodeGenOpenCL/amdgpu-features-readonly.cl
index f55988085ad74..96648397eec09 100644
--- a/clang/test/CodeGenOpenCL/amdgpu-features-readonly.cl
+++ b/clang/test/CodeGenOpenCL/amdgpu-features-readonly.cl
@@ -3,4 +3,11 @@
 
 // GWS: warning: feature flag '+gws' is ignored since the feature is read only [-Winvalid-command-line-argument]
 
+// RUN: %clang_cc1 -triple amdgpu9.06 -target-feature +sramecc-on-off-modes -o /dev/null %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=SRAMECC-MODES %s
+// RUN: %clang_cc1 -triple amdgpu9.06 -target-feature -sramecc-on-off-modes -o /dev/null %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=SRAMECC-MODES %s
+
+// SRAMECC-MODES: warning: feature flag '{{[+-]}}sramecc-on-off-modes' is ignored since the feature is read only [-Winvalid-command-line-argument]
+
 kernel void test() {}
diff --git a/clang/test/Driver/amdgpu-xnack-sramecc-flags.c b/clang/test/Driver/amdgpu-xnack-sramecc-flags.c
index b0e23b884e284..0936234903f0d 100644
--- a/clang/test/Driver/amdgpu-xnack-sramecc-flags.c
+++ b/clang/test/Driver/amdgpu-xnack-sramecc-flags.c
@@ -17,6 +17,12 @@
 // RUN:   FileCheck -check-prefix=SRAMECC-OFF %s
 // SRAMECC-OFF: "-mno-sramecc"
 
+// SRAMECC remains selectable on gfx12.5 even though XNACK is hardwired on.
+// RUN: %clang -### --target=amdgcn-amd-amdhsa -mcpu=gfx1250:sramecc+ %s 2>&1 | \
+// RUN:   FileCheck -check-prefix=SRAMECC-ON %s
+// RUN: %clang -### --target=amdgcn-amd-amdhsa -mcpu=gfx1250:sramecc- %s 2>&1 | \
+// RUN:   FileCheck -check-prefix=SRAMECC-OFF %s
+
 // Test that target ID takes precedence over explicit flags
 // RUN: %clang -### --target=amdgcn-amd-amdhsa -mcpu=gfx90a:xnack+ -mno-xnack %s 2>&1 | \
 // RUN:   FileCheck -check-prefix=TARGETID-OVERRIDES-XNACK %s
diff --git a/llvm/docs/AMDGPUUsage.rst b/llvm/docs/AMDGPUUsage.rst
index 2d6263402164f..ba68defd35d75 100644
--- a/llvm/docs/AMDGPUUsage.rst
+++ b/llvm/docs/AMDGPUUsage.rst
@@ -1025,7 +1025,8 @@ consumed by the AMDGPU backend during code generation.
      - ``i32``
      - Error
      - Controls SRAMECC mode. This is ignored on targets which do not
-       support sramecc.
+       support SRAMECC on/off modes. Targets that support SRAMECC without
+       on/off modes always have SRAMECC enabled.
 
        - absent: **any**. The module can be loaded and executed in a process
          with SRAMECC either enabled or disabled.
diff --git a/llvm/lib/Target/AMDGPU/AMDGPU.td b/llvm/lib/Target/AMDGPU/AMDGPU.td
index c3b4d53a7effa..be5c6b6828842 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPU.td
+++ b/llvm/lib/Target/AMDGPU/AMDGPU.td
@@ -1200,6 +1200,14 @@ def FeatureSupportsSRAMECC : SubtargetFeature<"sramecc-support",
   [], InlineIgnore
 >;
 
+defm SRAMECCOnOffModes : AMDGPUSubtargetFeature<"sramecc-on-off-modes",
+  "Target supports SRAMECC on/off modes",
+  /*GenPredicate=*/1,
+  /*GenAssemblerPredicate=*/0,
+  [FeatureSupportsSRAMECC],
+  InlineIgnore
+>;
+
 defm NoSdstCMPX : AMDGPUSubtargetFeature<"no-sdst-cmpx",
   "V_CMPX does not write VCC/SGPR in addition to EXEC"
 >;
@@ -1995,7 +2003,7 @@ def FeatureISAVersion9_0_MI_Common : FeatureSet<
      FeatureMAIInsts,
      FeaturePkFmacF16Inst,
      FeatureAtomicFaddNoRtnInsts,
-     FeatureSupportsSRAMECC])>;
+     FeatureSRAMECCOnOffModes])>;
 
 def FeatureISAVersion9_0_0 : FeatureSet<
   !listconcat(FeatureISAVersion9_0_Consumer_Common.Features,
@@ -2018,7 +2026,7 @@ def FeatureISAVersion9_0_6 : FeatureSet<
      FeatureDot2Insts,
      FeatureDot7Insts,
      FeatureDot10Insts,
-     FeatureSupportsSRAMECC])>;
+     FeatureSRAMECCOnOffModes])>;
 
 def FeatureISAVersion9_0_8 : FeatureSet<
   !listconcat(FeatureISAVersion9_0_MI_Common.Features,
@@ -2090,7 +2098,7 @@ def FeatureISAVersion9_4_Common : FeatureSet<
    FeatureAtomicBufferGlobalPkAddF16Insts,
    FeatureAtomicGlobalPkAddBF16Inst,
    FeatureFlatAtomicFaddF32Inst,
-   FeatureSupportsSRAMECC,
+   FeatureSRAMECCOnOffModes,
    FeaturePackedTID,
    FeatureArchitectedFlatScratch,
    FeatureFullRate64Ops,
@@ -2481,7 +2489,7 @@ def FeatureISAVersion12_50_Common : FeatureSet<
    FeaturePrngInst,
    FeaturePermlane16Swap,
    FeatureAshrPkInsts,
-   FeatureSupportsSRAMECC,
+   FeatureSRAMECCOnOffModes,
    FeatureMaxHardClauseLength63,
    FeatureWaitXcnt,
    FeatureAsynccnt,
@@ -3336,6 +3344,7 @@ def AMDGPUFrontendVisibleFeatures {
   FeatureWavefrontSize32, FeatureWavefrontSize64, FeatureSupportsWGP,
   FeatureSupportsWave32, FeatureFastFMAF32, FeatureFastDenormalF32,
   FeatureSupportsXNACK, FeatureSupportsSRAMECC, FeatureXNACKOnOffModes,
+  FeatureSRAMECCOnOffModes,
   FeatureSGPRInitBug, FeatureApertureRegs, FeatureGetDoorbellID,
   FeatureAGPRAlloc, Feature1536VGPRs, Feature1024AddressableVGPRs,
   FeatureHalfAddressablePhysicalLocalMemory, FeatureBackOffBarrier,
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
index c18b840c36791..a295a1c14e66c 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
@@ -1228,7 +1228,7 @@ void AMDGPUAsmPrinter::initializeTargetID(const Module &M) {
       TSTargetID->setXnackSetting(Setting);
   }
 
-  if (getGlobalSTI()->getFeatureBits().test(AMDGPU::FeatureSupportsSRAMECC)) {
+  if (getGlobalSTI()->getFeatureBits().test(AMDGPU::FeatureSRAMECCOnOffModes)) {
     AMDGPU::TargetIDSetting Setting =
         GCNTargetMachine::getTargetIDSettingFromModuleFlag(M, "amdgpu.sramecc");
     if (Setting != AMDGPU::TargetIDSetting::Any)
diff --git a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
index 3b200d412eb0d..da039141fd2a3 100644
--- a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
+++ b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
@@ -101,6 +101,9 @@ void AMDGPUDisassembler::emitTargetIDIfSupported(raw_ostream &OS,
 
   // Add xnack and sramecc from ELF flags (v4 format)
   if (CodeObjectVersion >= AMDGPU::AMDHSA_COV4) {
+    // Hardwired-on features are not selectable target-ID modifiers.
+    bool SramEccHardwiredOn = TargetID.isSramEccSupported() &&
+                              !STI.hasFeature(AMDGPU::FeatureSRAMECCOnOffModes);
     unsigned SrameccSetting = EFlags & ELF::EF_AMDGPU_FEATURE_SRAMECC_V4;
     switch (SrameccSetting) {
     case ELF::EF_AMDGPU_FEATURE_SRAMECC_UNSUPPORTED_V4:
@@ -110,11 +113,13 @@ void AMDGPUDisassembler::emitTargetIDIfSupported(raw_ostream &OS,
       break;
     case ELF::EF_AMDGPU_FEATURE_SRAMECC_OFF_V4:
       TargetID.setSramEccSetting(AMDGPU::TargetIDSetting::Off);
-      OS << ":sramecc-";
+      if (!SramEccHardwiredOn)
+        OS << ":sramecc-";
       break;
     case ELF::EF_AMDGPU_FEATURE_SRAMECC_ON_V4:
       TargetID.setSramEccSetting(AMDGPU::TargetIDSetting::On);
-      OS << ":sramecc+";
+      if (!SramEccHardwiredOn)
+        OS << ":sramecc+";
       break;
     }
 
diff --git a/llvm/lib/Target/AMDGPU/GCNSubtarget.cpp b/llvm/lib/Target/AMDGPU/GCNSubtarget.cpp
index 34d987cd6d266..63a2ffcc4450a 100644
--- a/llvm/lib/Target/AMDGPU/GCNSubtarget.cpp
+++ b/llvm/lib/Target/AMDGPU/GCNSubtarget.cpp
@@ -241,8 +241,9 @@ GCNSubtarget::GCNSubtarget(const Triple &TT, StringRef GPU, StringRef FS,
   if (hasXNACKOnOffModes())
     TargetID.setXnackSetting(XnackSetting);
 
-  // Apply the module flag's sramecc setting if the target supports it.
-  if (supportsSRAMECC())
+  // Apply the module flag's sramecc setting if the target supports on/off
+  // modes. Targets with sramecc hardwired on ignore module flags.
+  if (hasSRAMECCOnOffModes())
     TargetID.setSramEccSetting(SramEccSetting);
 
   LLVM_DEBUG(dbgs() << "xnack setting for subtarget: "
diff --git a/llvm/lib/TargetParser/AMDGPUTargetParser.cpp b/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
index 756d665353c45..116014826ed67 100644
--- a/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
+++ b/llvm/lib/TargetParser/AMDGPUTargetParser.cpp
@@ -607,6 +607,7 @@ static const AMDGPUFeatureBitset FrontendOnlyFeatures = {
     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,
@@ -787,17 +788,20 @@ static void getDefaultTargetIDFeatures(GPUKind Arch,
                                        TargetIDSetting &XnackSetting,
                                        TargetIDSetting &SramEccSetting) {
   const AMDGPUFeatureBitset &Features = getFeatureBitset(Arch);
-  // xnack with on/off modes defaults to Any; supported without on/off modes is
-  // hardwired On (e.g. gfx1250); unsupported is Unsupported.
+  // 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;
-  SramEccSetting = Features.test(FEAT_SRAMECC_SUPPORT)
-                       ? TargetIDSetting::Any
-                       : TargetIDSetting::Unsupported;
+  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
@@ -832,7 +836,7 @@ static bool computeTargetIDFeatures(GPUKind Arch, StringRef TargetIDStr,
       SeenXnack = true;
     } else if (FeatureString.consume_front("sramecc")) {
       TargetIDSetting Sign = getTargetIDSettingFromFeatureString(FeatureString);
-      if (SeenSramEcc || SramEccSetting == TargetIDSetting::Unsupported ||
+      if (SeenSramEcc || !Features.test(FEAT_SRAMECC_ON_OFF_MODES) ||
           Sign == TargetIDSetting::Unsupported)
         Valid = false;
       else
@@ -930,16 +934,24 @@ static bool isXnackHardwiredOn(GPUKind Arch) {
          !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+". Xnack is never emitted for hardwired-on
-// targets.
+// 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 (SramEcc == TargetIDSetting::Off)
-    OS << ":sramecc-";
-  else if (SramEcc == TargetIDSetting::On)
-    OS << ":sramecc+";
+  if (!SramEccHardwiredOn) {
+    if (SramEcc == TargetIDSetting::Off)
+      OS << ":sramecc-";
+    else if (SramEcc == TargetIDSetting::On)
+      OS << ":sramecc+";
+  }
 
   if (XnackHardwiredOn)
     return;
@@ -955,7 +967,7 @@ void TargetID::print(raw_ostream &StreamRep) const {
 
   if (IsAMDHSA) {
     printFeatureModifiers(StreamRep, getSramEccSetting(), getXnackSetting(),
-                          isXnackHardwiredOn(Arch));
+                          isSramEccHardwiredOn(Arch), isXnackHardwiredOn(Arch));
   }
 }
 
@@ -969,7 +981,7 @@ std::string TargetID::toString() const {
 void TargetID::printCanonicalTargetIDString(raw_ostream &OS) const {
   OS << getArchNameAMDGCN(Arch);
   printFeatureModifiers(OS, getSramEccSetting(), getXnackSetting(),
-                        isXnackHardwiredOn(Arch));
+                        isSramEccHardwiredOn(Arch), isXnackHardwiredOn(Arch));
 }
 
 std::string TargetID::getCanonicalFeatureString() const {
diff --git a/llvm/test/MC/AMDGPU/amdgcn_target_directive_from_eflags.s b/llvm/test/MC/AMDGPU/amdgcn_target_directive_from_eflags.s
index 6a40519c48a5d..b63f7a2cc88b8 100644
--- a/llvm/test/MC/AMDGPU/amdgcn_target_directive_from_eflags.s
+++ b/llvm/test/MC/AMDGPU/amdgcn_target_directive_from_eflags.s
@@ -47,6 +47,10 @@
 // RUN: llvm-mc -triple=amdgpu9.08-amd-amdhsa -filetype=obj %t/sramecc-off-only.s -o %t-sramecc-off-only.o
 // RUN: llvm-objdump --disassemble-all %t-sramecc-off-only.o | FileCheck --check-prefix=CHECK-SRAMECC-OFF-ONLY %s
 
+// Model a target with SRAMECC hardwired on: neither explicit mode is printed.
+// RUN: llvm-objdump --disassemble-all --mattr=-sramecc-on-off-modes %t-sramecc-only.o | FileCheck --check-prefix=CHECK-DEFAULT %s
+// RUN: llvm-objdump --disassemble-all --mattr=-sramecc-on-off-modes %t-sramecc-off-only.o | FileCheck --check-prefix=CHECK-DEFAULT %s
+
 // CHECK-GFX900: .amdgcn_target "amdgpu-amd-amdhsa-unknown-gfx900"
 
 // CHECK-GFX908: .amdgcn_target "amdgpu-amd-amdhsa-unknown-gfx908"
diff --git a/llvm/unittests/TargetParser/TargetParserTest.cpp b/llvm/unittests/TargetParser/TargetParserTest.cpp
index 62d6f3a4c955b..445174ee9c94c 100644
--- a/llvm/unittests/TargetParser/TargetParserTest.cpp
+++ b/llvm/unittests/TargetParser/TargetParserTest.cpp
@@ -2826,6 +2826,8 @@ TEST(TargetParserTest, testAMDGPUfillAMDGPUFeatureMap) {
 
   // A capability feature is queried through the bitset only.
   EXPECT_FALSE(HasFeature("gfx1030", "half-addressable-physical-local-memory"));
+  EXPECT_FALSE(HasFeature("gfx906", "sramecc-on-off-modes"));
+  EXPECT_FALSE(HasFeature("gfx1250", "sramecc-on-off-modes"));
 
   // LDS allocation granularity is queried through the bitset only.
   EXPECT_FALSE(HasFeature("gfx600", "lds-alloc-granularity-256"));
@@ -3636,6 +3638,60 @@ TEST(TargetParserTest, testAMDGPUParseTargetIDString) {
       TargetID::parse(Triple("r600-unknown-unknown"), "cypress").has_value());
 }
 
+TEST(TargetParserTest, testAMDGPUSramEccOnOffModes) {
+  using namespace AMDGPU;
+  Triple AMDHSA("amdgcn-amd-amdhsa");
+
+  // Existing SRAMECC targets retain their selectable modes, including generic
+  // targets and gfx12.5, where XNACK is hardwired on.
+  for (StringRef GPU :
+       {"gfx906", "gfx908", "gfx90a", "gfx942", "gfx950", "gfx9-4-generic",
+        "gfx1250-strict", "gfx1250", "gfx1251", "gfx12-5-generic"}) {
+    SCOPED_TRACE(GPU);
+    GPUKind Kind = parseArchAMDGCN(GPU);
+    const AMDGPUFeatureBitset &Features = getFeatureBitset(Kind);
+    EXPECT_TRUE(Features.test(FEAT_SRAMECC_SUPPORT));
+    EXPECT_TRUE(Features.test(FEAT_SRAMECC_ON_OFF_MODES));
+
+    auto Default = TargetID::parse(AMDHSA, GPU);
+    ASSERT_TRUE(Default);
+    EXPECT_EQ(Default->getSramEccSetting(), TargetIDSetting::Any);
+    EXPECT_EQ(Default->getCanonicalFeatureString(), GPU);
+
+    // Resolving the GPU through its triple subarch uses the same default.
+    Triple SubArchTriple(getSubArchName(getSubArch(Kind)), "amd", "amdhsa");
+    EXPECT_EQ(TargetID(SubArchTriple, "").getSramEccSetting(),
+              TargetIDSetting::Any);
+
+    for (bool Enabled : {false, true}) {
+      std::string ID = (GPU + (Enabled ? ":sramecc+" : ":sramecc-")).str();
+      TargetIDSetting Setting =
+          Enabled ? TargetIDSetting::On : TargetIDSetting::Off;
+      auto Explicit = TargetID::parse(AMDHSA, ID);
+      ASSERT_TRUE(Explicit);
+      EXPECT_EQ(Explicit->getSramEccSetting(), Setting);
+      EXPECT_EQ(Explicit->getCanonicalFeatureString(), ID);
+      EXPECT_EQ(Explicit->toString(), "amdgcn-amd-amdhsa-unknown-" + ID);
+      EXPECT_EQ(TargetID::createFromSubtargetFeatures(
+                    AMDHSA, GPU, Enabled ? "+sramecc" : "-sramecc"),
+                *Explicit);
+    }
+  }
+
+  for (StringRef GPU : {"gfx600", "gfx900", "gfx1100", "gfx1200"}) {
+    SCOPED_TRACE(GPU);
+    EXPECT_FALSE(
+        getFeatureBitset(parseArchAMDGCN(GPU)).test(FEAT_SRAMECC_ON_OFF_MODES));
+    EXPECT_EQ(TargetID(AMDHSA, GPU).getSramEccSetting(),
+              TargetIDSetting::Unsupported);
+    EXPECT_FALSE(TargetID::parse(AMDHSA, (GPU + ":sramecc+").str()));
+    EXPECT_FALSE(TargetID::parse(AMDHSA, (GPU + ":sramecc-").str()));
+    EXPECT_EQ(TargetID::createFromSubtargetFeatures(AMDHSA, GPU, "+sramecc")
+                  .getSramEccSetting(),
+              TargetIDSetting::Unsupported);
+  }
+}
+
 TEST(TargetParserTest, testAMDGPUTargetIDProvidesFor) {
   using AMDGPU::TargetID;
   Triple AMDHSA("amdgcn-amd-amdhsa");

@chinmaydd
chinmaydd requested a review from lamb-j September 23, 2026 16:39

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend:AMDGPU clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang:frontend Language frontend issues, e.g. anything involving "Sema"

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant