[llvm] [TableGen] Add asserts for a few register related checks (PR #182680)

via llvm-commits llvm-commits at lists.llvm.org
Sat Feb 21 12:07:21 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-tablegen

Author: Rahul Joshi (jurahul)

<details>
<summary>Changes</summary>

Move some register file related error checking from C++ code to asserts in Target.td file. Rename and extend the lit test to exercise these errors.

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


5 Files Affected:

- (modified) llvm/include/llvm/Target/Target.td (+9) 
- (removed) llvm/test/TableGen/RegisterClass.td (-7) 
- (added) llvm/test/TableGen/RegisterInfoEmitter-errors.td (+57) 
- (modified) llvm/utils/TableGen/Common/CodeGenRegisters.cpp (+1-18) 
- (modified) llvm/utils/TableGen/RegisterBankEmitter.cpp (+3) 


``````````diff
diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td
index eeef9cee7fd73..847753f6db211 100644
--- a/llvm/include/llvm/Target/Target.td
+++ b/llvm/include/llvm/Target/Target.td
@@ -191,6 +191,9 @@ class Register<string n, list<string> altNames = []> {
   // SubRegs.
   list<SubRegIndex> SubRegIndices = [];
 
+  assert !eq(!size(SubRegs), !size(SubRegIndices)),
+    "SubRegs and SubRegIndices must have the same size";
+
   // RegAltNameIndices - The alternate name indices which are valid for this
   // register.
   list<RegAltNameIndex> RegAltNameIndices = [];
@@ -301,6 +304,7 @@ class RegisterClass<string namespace, list<ValueType> regTypes, int alignment,
   // but different count/size of items, like SSE on x86.
   //
   list<ValueType> RegTypes = regTypes;
+  assert !not(!empty(RegTypes)), "RegTypes list must not be empty";
 
   // Size - Specify the spill size in bits of the registers. A default value of
   // zero lets tablegen pick an appropriate size.
@@ -470,6 +474,11 @@ class RegisterTuples<list<SubRegIndex> Indices, list<dag> Regs,
   // sub-registers in the synthesized super-registers.
   list<SubRegIndex> SubRegIndices = Indices;
 
+  assert !eq(!size(SubRegs), !size(SubRegIndices)),
+    "SubRegs and SubRegIndices must have the same size";
+
+  assert !ge(!size(SubRegs), 2), "Tuples must have at least 2 sub-registers";
+
   // List of asm names for the generated tuple registers.
   list<string> RegAsmNames = RegNames;
 
diff --git a/llvm/test/TableGen/RegisterClass.td b/llvm/test/TableGen/RegisterClass.td
deleted file mode 100644
index b7520bc76972e..0000000000000
--- a/llvm/test/TableGen/RegisterClass.td
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: not llvm-tblgen -gen-register-bank -I %p/../../include %s 2>&1 | FileCheck %s
-
-include "llvm/Target/Target.td"
-
-def MyTarget : Target;
-def R0 : Register<"r0">;
-def ClassA : RegisterClass<"MyTarget", [], 32, (add R0)>; // CHECK: [[@LINE]]:5: error: RegTypes list must not be empty!
diff --git a/llvm/test/TableGen/RegisterInfoEmitter-errors.td b/llvm/test/TableGen/RegisterInfoEmitter-errors.td
new file mode 100644
index 0000000000000..cb1a1e9136e95
--- /dev/null
+++ b/llvm/test/TableGen/RegisterInfoEmitter-errors.td
@@ -0,0 +1,57 @@
+// RUN: not llvm-tblgen -gen-register-info -I %p/../../include %s -DERROR0 2>&1 | FileCheck %s --check-prefix=ERROR0
+// RUN: not llvm-tblgen -gen-register-info -I %p/../../include %s -DERROR1 2>&1 | FileCheck %s --check-prefix=ERROR1
+// RUN: not llvm-tblgen -gen-register-info -I %p/../../include %s -DERROR2 2>&1 | FileCheck %s --check-prefix=ERROR2
+// RUN: not llvm-tblgen -gen-register-info -I %p/../../include %s -DERROR3 2>&1 | FileCheck %s --check-prefix=ERROR3
+// RUN: not llvm-tblgen -gen-register-info -I %p/../../include %s -DERROR4 2>&1 | FileCheck %s --check-prefix=ERROR4
+// RUN: not llvm-tblgen -gen-register-bank -I %p/../../include %s -DERROR5 2>&1 | FileCheck %s --check-prefix=ERROR5
+
+include "llvm/Target/Target.td"
+
+def MyTarget : Target;
+
+foreach Index = 0-15 in {
+  def R#Index : Register <"r"#Index>;
+}
+
+def GPR32 : RegisterClass<"MyTarget", [i32], 32, (sequence "R%u", 0, 15)>;
+
+def sub0 : SubRegIndex<32, 0>;
+def sub1 : SubRegIndex<32, 32>;
+
+#ifdef ERROR0
+// ERROR0: error: assertion failed: RegTypes list must not be empty
+// ERROR0: [[@LINE+1]]:5: error: assertion failed in this record
+def ClassA : RegisterClass<"MyTarget", [], 32, (add R0)>;
+#endif
+
+#ifdef ERROR1
+// ERROR1: error: assertion failed: SubRegs and SubRegIndices must have the same size
+// ERROR1: error: assertion failed: Tuples must have at least 2 sub-registers
+// ERROR1: [[@LINE+1]]:5: error: assertion failed in this record
+def Tuple0 : RegisterTuples<[sub0, sub1], [(shl GPR32, 0)]>;
+#endif
+
+#ifdef ERROR2
+// ERROR2: error: assertion failed: SubRegs and SubRegIndices must have the same size
+// ERROR2: [[@LINE+1]]:5: error: assertion failed in this record
+def Tuple1 : RegisterTuples<[sub0], [(shl GPR32, 0), (shl GPR32, 1)]>;
+#endif
+
+#ifdef ERROR3
+// ERROR3: error: assertion failed: SubRegs and SubRegIndices must have the same size
+// ERROR3: [[@LINE+1]]:5: error: assertion failed in this record
+def R0_R1 : RegisterWithSubRegs<"r0_r1", [R0, R1]>;
+#endif
+
+#ifdef ERROR4
+// ERROR4: error: assertion failed: SubRegs and SubRegIndices must have the same size
+// ERROR4: [[@LINE+1]]:5: error: assertion failed in this record
+def R0_R1 : RegisterWithSubRegs<"r0_r1", [R0]> {
+    let SubRegIndices = [sub0, sub1];
+}
+#endif
+
+#ifdef ERROR5
+// ERROR5: error: No register banks defined
+#endif
+
diff --git a/llvm/utils/TableGen/Common/CodeGenRegisters.cpp b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp
index 84a58e8c38052..cc90b14e87bc1 100644
--- a/llvm/utils/TableGen/Common/CodeGenRegisters.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp
@@ -174,10 +174,6 @@ void CodeGenRegister::buildObjectGraph(CodeGenRegBank &RegBank) {
       TheDef->getValueAsListOfDefs("SubRegIndices");
   std::vector<const Record *> SRs = TheDef->getValueAsListOfDefs("SubRegs");
 
-  if (SRIs.size() != SRs.size())
-    PrintFatalError(TheDef->getLoc(),
-                    "SubRegs and SubRegIndices must have the same size");
-
   for (const auto &[SRI, SR] : zip_equal(SRIs, SRs)) {
     ExplicitSubRegIndices.push_back(RegBank.getSubRegIdx(SRI));
     ExplicitSubRegs.push_back(RegBank.getReg(SR));
@@ -555,11 +551,6 @@ struct TupleExpander : SetTheory::Expander {
         Def->getValueAsListOfDefs("SubRegIndices");
     unsigned Dim = Indices.size();
     const ListInit *SubRegs = Def->getValueAsListInit("SubRegs");
-    if (Dim != SubRegs->size())
-      PrintFatalError(Def->getLoc(), "SubRegIndices and SubRegs size mismatch");
-    if (Dim < 2)
-      PrintFatalError(Def->getLoc(),
-                      "Tuples must have at least 2 sub-registers");
 
     // Evaluate the sub-register lists to be zipped.
     unsigned Length = ~0u;
@@ -684,16 +675,8 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank,
       RegsWithSuperRegsTopoSigs(RegBank.getNumTopoSigs()), EnumValue(-1),
       TSFlags(0) {
   GeneratePressureSet = R->getValueAsBit("GeneratePressureSet");
-  std::vector<const Record *> TypeList = R->getValueAsListOfDefs("RegTypes");
-  if (TypeList.empty())
-    PrintFatalError(R->getLoc(), "RegTypes list must not be empty!");
-  for (const Record *Type : TypeList) {
-    if (!Type->isSubClassOf("ValueType"))
-      PrintFatalError(R->getLoc(),
-                      "RegTypes list member '" + Type->getName() +
-                          "' does not derive from the ValueType class!");
+  for (const Record *Type : R->getValueAsListOfDefs("RegTypes"))
     VTs.push_back(getValueTypeByHwMode(Type, RegBank.getHwModes()));
-  }
 
   // Allocation order 0 is the full set. AltOrders provides others.
   const SetTheory::RecVec *Elements = RegBank.getSets().expand(R);
diff --git a/llvm/utils/TableGen/RegisterBankEmitter.cpp b/llvm/utils/TableGen/RegisterBankEmitter.cpp
index 0612bf1e636ae..c2cb06fe456c7 100644
--- a/llvm/utils/TableGen/RegisterBankEmitter.cpp
+++ b/llvm/utils/TableGen/RegisterBankEmitter.cpp
@@ -406,6 +406,9 @@ void RegisterBankEmitter::run(raw_ostream &OS) {
     Banks.push_back(Bank);
   }
 
+  if (Banks.empty())
+    PrintFatalError("No register banks defined");
+
   // Warn about ambiguous MIR caused by register bank/class name clashes.
   Timer.startTimer("Warn ambiguous");
   for (const auto &Class : RegisterClassHierarchy.getRegClasses()) {

``````````

</details>


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


More information about the llvm-commits mailing list