Skip to content

Conversation

@arichardson
Copy link
Member

Having duplicate mode entries previously asserted (or silently replaced
the last value with a new one in release builds). Report an error with
a helpful message instead.

Created using spr 1.3.8-beta.1
@llvmbot
Copy link
Member

llvmbot commented Dec 10, 2025

@llvm/pr-subscribers-tablegen

Author: Alexander Richardson (arichardson)

Changes

Having duplicate mode entries previously asserted (or silently replaced
the last value with a new one in release builds). Report an error with
a helpful message instead.


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

2 Files Affected:

  • (modified) llvm/test/TableGen/RegClassByHwModeErrors.td (+21)
  • (modified) llvm/utils/TableGen/Common/InfoByHwMode.cpp (+28-18)
diff --git a/llvm/test/TableGen/RegClassByHwModeErrors.td b/llvm/test/TableGen/RegClassByHwModeErrors.td
index 0ee6370ccd0ce..08193873a8d7b 100644
--- a/llvm/test/TableGen/RegClassByHwModeErrors.td
+++ b/llvm/test/TableGen/RegClassByHwModeErrors.td
@@ -9,6 +9,8 @@
 // RUN:   %t/compress-regclass-by-hwmode-2.td -o /dev/null 2>&1 | FileCheck %t/compress-regclass-by-hwmode-2.td --implicit-check-not="error:"
 // RUN: not llvm-tblgen --gen-dag-isel  -I %p/../../include -I %t -I %S \
 // RUN:   %t/vt-by-hwmode-missing.td -o /dev/null 2>&1 | FileCheck %t/vt-by-hwmode-missing.td --implicit-check-not="error:"
+// RUN: not llvm-tblgen --gen-dag-isel -I %p/../../include -I %t -I %S \
+// RUN:   %t/multiple-entries-for-same-mode.td -o /dev/null 2>&1 | FileCheck %t/multiple-entries-for-same-mode.td --implicit-check-not="error:"
 
 //--- Common.td
 include "Common/RegClassByHwModeCommon.td"
@@ -119,3 +121,22 @@ def TEST : TestInstruction {
 
 def MyTargetISA : InstrInfo;
 def MyTarget : Target { let InstructionSet = MyTargetISA; }
+
+
+//--- multiple-entries-for-same-mode.td
+include "Common.td"
+/// We should get an error if the same mode is listed more than once
+defvar Ptr64Alias = Ptr64;
+def BadRegClass : RegClassByHwMode<[Ptr32, Ptr64, Ptr64Alias], [XRegs, YRegs, YRegs]>;
+// CHECK: [[#@LINE-1]]:5: error: Duplicate RegisterClass entry for HwMode Ptr64: YRegs
+// Need at least one CompressPat use of the bad reg class to trigger the error:
+def USE_BAD_REG_CLASS : TestInstruction {
+  let OutOperandList = (outs BadRegClass:$dst);
+  let InOperandList = (ins BadRegClass:$src1, BadRegClass:$src2);
+  let AsmString = "bad $dst";
+  let Pattern = [(set BadRegClass:$dst, (add BadRegClass:$src1, BadRegClass:$src2))];
+}
+def MyTargetISA : InstrInfo;
+def MyTarget : Target {
+  let InstructionSet = MyTargetISA;
+}
diff --git a/llvm/utils/TableGen/Common/InfoByHwMode.cpp b/llvm/utils/TableGen/Common/InfoByHwMode.cpp
index a3f8909c36090..20ad89822c881 100644
--- a/llvm/utils/TableGen/Common/InfoByHwMode.cpp
+++ b/llvm/utils/TableGen/Common/InfoByHwMode.cpp
@@ -32,10 +32,12 @@ std::string llvm::getModeName(unsigned Mode) {
 ValueTypeByHwMode::ValueTypeByHwMode(const Record *R, const CodeGenHwModes &CGH)
     : InfoByHwMode<llvm::MVT>(R) {
   const HwModeSelect &MS = CGH.getHwModeSelect(R);
-  for (const HwModeSelect::PairType &P : MS.Items) {
-    auto I = Map.try_emplace(P.first, MVT(llvm::getValueType(P.second)));
-    assert(I.second && "Duplicate entry?");
-    (void)I;
+  for (auto [ModeID, VT] : MS.Items) {
+    assert(VT && VT->isSubClassOf("ValueType"));
+    if (!Map.try_emplace(ModeID, MVT(llvm::getValueType(VT))).second)
+      PrintFatalError(R->getLoc(), "duplicate RegInfo entry for HwMode " +
+                                       CGH.getModeName(ModeID, true) + ": " +
+                                       VT->getName());
   }
   if (R->isSubClassOf("PtrValueType"))
     PtrAddrSpace = R->getValueAsInt("AddrSpace");
@@ -143,10 +145,12 @@ RegSizeInfoByHwMode::RegSizeInfoByHwMode(const Record *R,
                                          const CodeGenHwModes &CGH)
     : InfoByHwMode<llvm::RegSizeInfo>(R) {
   const HwModeSelect &MS = CGH.getHwModeSelect(R);
-  for (const HwModeSelect::PairType &P : MS.Items) {
-    auto I = Map.try_emplace(P.first, RegSizeInfo(P.second));
-    assert(I.second && "Duplicate entry?");
-    (void)I;
+  for (auto [ModeID, RegInfo] : MS.Items) {
+    assert(RegInfo && RegInfo->isSubClassOf("RegInfo"));
+    if (!Map.try_emplace(ModeID, RegSizeInfo(RegInfo)).second)
+      PrintFatalError(R->getLoc(), "duplicate RegInfo entry for HwMode " +
+                                       CGH.getModeName(ModeID, true) + ": " +
+                                       RegInfo->getName());
   }
 }
 
@@ -198,7 +202,9 @@ RegClassByHwMode::RegClassByHwMode(const Record *R, const CodeGenHwModes &CGH,
            "Register class must subclass RegisterClass");
     const CodeGenRegisterClass *RegClass = RegBank.getRegClass(RegClassRec);
     if (!Map.try_emplace(ModeID, RegClass).second)
-      llvm_unreachable("duplicate entry");
+      PrintFatalError(R->getLoc(), "duplicate RegisterClass entry for HwMode " +
+                                       CGH.getModeName(ModeID, true) + ": " +
+                                       RegClass->getName());
   }
 }
 
@@ -211,10 +217,12 @@ SubRegRangeByHwMode::SubRegRangeByHwMode(const Record *R,
                                          const CodeGenHwModes &CGH)
     : InfoByHwMode<llvm::SubRegRange>(R) {
   const HwModeSelect &MS = CGH.getHwModeSelect(R);
-  for (const HwModeSelect::PairType &P : MS.Items) {
-    auto I = Map.try_emplace(P.first, SubRegRange(P.second));
-    assert(I.second && "Duplicate entry?");
-    (void)I;
+  for (auto [ModeID, Range] : MS.Items) {
+    assert(Range && Range->isSubClassOf("SubRegRange"));
+    if (!Map.try_emplace(ModeID, SubRegRange(Range)).second)
+      PrintFatalError(R->getLoc(), "duplicate SubRegRange entry for HwMode " +
+                                       CGH.getModeName(ModeID, true) + ": " +
+                                       Range->getName());
   }
 }
 
@@ -222,12 +230,14 @@ EncodingInfoByHwMode::EncodingInfoByHwMode(const Record *R,
                                            const CodeGenHwModes &CGH)
     : InfoByHwMode<const llvm::Record *>(R) {
   const HwModeSelect &MS = CGH.getHwModeSelect(R);
-  for (const HwModeSelect::PairType &P : MS.Items) {
-    assert(P.second && P.second->isSubClassOf("InstructionEncoding") &&
+  for (auto [ModeID, Encoding] : MS.Items) {
+    assert(Encoding && Encoding->isSubClassOf("InstructionEncoding") &&
            "Encoding must subclass InstructionEncoding");
-    auto I = Map.try_emplace(P.first, P.second);
-    assert(I.second && "Duplicate entry?");
-    (void)I;
+    if (!Map.try_emplace(ModeID, Encoding).second)
+      PrintFatalError(R->getLoc(),
+                      "duplicate InstructionEncoding entry for HwMode " +
+                          CGH.getModeName(ModeID, true) + ": " +
+                          Encoding->getName());
   }
 }
 

Created using spr 1.3.8-beta.1
@github-actions
Copy link

github-actions bot commented Dec 10, 2025

🪟 Windows x64 Test Results

  • 128545 tests passed
  • 2805 tests skipped

✅ The build succeeded and all tests passed.

@github-actions
Copy link

github-actions bot commented Dec 10, 2025

🐧 Linux x64 Test Results

  • 187272 tests passed
  • 4940 tests skipped

✅ The build succeeded and all tests passed.

Created using spr 1.3.8-beta.1
@arichardson arichardson merged commit 3abaed8 into main Dec 11, 2025
10 checks passed
@arichardson arichardson deleted the users/arichardson/spr/tablegen-replace-reachable-assertion-with-error-in-byhwmode branch December 11, 2025 00:38
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Dec 11, 2025
…Mode

Having duplicate mode entries previously asserted (or silently replaced
the last value with a new one in release builds). Report an error with
a helpful message instead.

Pull Request: llvm/llvm-project#171715
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants