[llvm] [TableGen] Check for duplicate register tuple definitions. (PR #95725)

Jason Eckhardt via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 16 16:55:16 PDT 2024


https://github.com/nvjle created https://github.com/llvm/llvm-project/pull/95725

Currently TableGen does not directly detect duplicate synthesized registers as can happen in this example:

def GPR128 : RegisterTuples<[sub0, sub1, sub2, sub3],
                            [(decimate (shl GPR32, 0), 1),
                             (decimate (shl GPR32, 1), 1),
                             (decimate (shl GPR32, 2), 1),
                             (decimate (shl GPR32, 3), 1)]>;

def GPR128_Aligned : RegisterTuples<[sub0, sub1, sub2, sub3],
                                    [(decimate (shl GPR32, 0), 4),
                                     (decimate (shl GPR32, 1), 4),
                                     (decimate (shl GPR32, 2), 4),
                                     (decimate (shl GPR32, 3), 4)]>;

TableGen does fail, but with an unrelated and difficult to understand error that happens downstream of tuple expansion:
"error: No SubRegIndex for R0_R1_R2_R3 in R0_R1_R2_R3".

This patch detects the problem directly during expansion and emits an error pointing the user to the actual issue:
"error: Register tuple redefines register 'R0_R1_R2_R3'".

>From 82d62ea2bfd08896ef5f9306d30555568791695b Mon Sep 17 00:00:00 2001
From: Jason Eckhardt <jeckhardt at nvidia.com>
Date: Sun, 16 Jun 2024 11:59:50 -0500
Subject: [PATCH] [TableGen] Check for duplicate register tuple definitions.

Currently TableGen does not directly detect duplicate synthesized
registers as can happen in this example:

def GPR128 : RegisterTuples<[sub0, sub1, sub2, sub3],
                            [(decimate (shl GPR32, 0), 1),
                             (decimate (shl GPR32, 1), 1),
                             (decimate (shl GPR32, 2), 1),
                             (decimate (shl GPR32, 3), 1)]>;

def GPR128_Aligned : RegisterTuples<[sub0, sub1, sub2, sub3],
                                    [(decimate (shl GPR32, 0), 4),
                                     (decimate (shl GPR32, 1), 4),
                                     (decimate (shl GPR32, 2), 4),
                                     (decimate (shl GPR32, 3), 4)]>;

TableGen does fail, but with an unrelated and difficult to understand
error that happens downstream of tuple expansion:
"error: No SubRegIndex for R0_R1_R2_R3 in R0_R1_R2_R3".

This patch detects the problem directly during expansion and emits an
error pointing the user to the actual issue:
"error: Register tuple redefines register 'R0_R1_R2_R3'".
---
 llvm/test/TableGen/check-duplicate-tuple-regs.td | 10 ++++++++++
 llvm/utils/TableGen/Common/CodeGenRegisters.cpp  | 10 ++++++++++
 2 files changed, 20 insertions(+)
 create mode 100644 llvm/test/TableGen/check-duplicate-tuple-regs.td

diff --git a/llvm/test/TableGen/check-duplicate-tuple-regs.td b/llvm/test/TableGen/check-duplicate-tuple-regs.td
new file mode 100644
index 0000000000000..e39345a1ef2c6
--- /dev/null
+++ b/llvm/test/TableGen/check-duplicate-tuple-regs.td
@@ -0,0 +1,10 @@
+// RUN: not llvm-tblgen -gen-register-info -I %p/../../include -I %p/Common %s 2>&1 | FileCheck %s
+
+include "reg-with-subregs-common.td"
+
+// CHECK: error: Register tuple redefines register 'R0_R1_R2_R3'
+def GPR128_Aligned : RegisterTuples<[sub0, sub1, sub2, sub3],
+                                    [(decimate (shl GPR32, 0), 4),
+                                     (decimate (shl GPR32, 1), 4),
+                                     (decimate (shl GPR32, 2), 4),
+                                     (decimate (shl GPR32, 3), 4)]>;
diff --git a/llvm/utils/TableGen/Common/CodeGenRegisters.cpp b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp
index 3c868b1e8f4fe..b5a6c1395c60e 100644
--- a/llvm/utils/TableGen/Common/CodeGenRegisters.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp
@@ -22,6 +22,7 @@
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
@@ -618,6 +619,9 @@ struct TupleExpander : SetTheory::Expander {
   // the synthesized definitions for their lifetime.
   std::vector<std::unique_ptr<Record>> &SynthDefs;
 
+  // Track all synthesized tuple names in order to detect duplicate definitions.
+  llvm::StringSet<> TupleNames;
+
   TupleExpander(std::vector<std::unique_ptr<Record>> &SynthDefs)
       : SynthDefs(SynthDefs) {}
 
@@ -684,6 +688,12 @@ struct TupleExpander : SetTheory::Expander {
       Record *NewReg = SynthDefs.back().get();
       Elts.insert(NewReg);
 
+      // Detect duplicates among synthesized registers.
+      const auto Res = TupleNames.insert(NewReg->getName());
+      if (!Res.second)
+        PrintFatalError(Def->getLoc(),
+                        "Register tuple redefines register '" + Name + "'.");
+
       // Copy Proto super-classes.
       ArrayRef<std::pair<Record *, SMRange>> Supers = Proto->getSuperClasses();
       for (const auto &SuperPair : Supers)



More information about the llvm-commits mailing list