[llvm] [TableGen][CodeGen] Give every leaf register a unique regunit (PR #139526)

Jay Foad via llvm-commits llvm-commits at lists.llvm.org
Mon May 12 03:10:27 PDT 2025


https://github.com/jayfoad created https://github.com/llvm/llvm-project/pull/139526

Give every leaf register a unique regunit, even if it has ad hoc
aliases.

Previously only leaf registers *without* ad hoc aliases would get a
unique regunit, but that caused situations where regunits could not be
used to distinguish a register from its subregs. For example:

- Registers A and B alias. They both get regunit 0 only.
- Register C has subregs A and B. It inherits regunits from its subregs,
  so it also gets regunit 0 only.

After this fix, registers A and B will get a unique regunit in addition
to the regunit representing the alias, for example:

- A will get regunits 0 and 1.
- B will get regunits 0 and 2.
- C will get regunits 0, 1 and 2.


>From 03f02eaf3a4fd8e741f5421f46d091fe2818a10d Mon Sep 17 00:00:00 2001
From: Jay Foad <jay.foad at amd.com>
Date: Mon, 12 May 2025 11:01:42 +0100
Subject: [PATCH] [TableGen][CodeGen] Give every leaf register a unique regunit

Give every leaf register a unique regunit, even if it has ad hoc
aliases.

Previously only leaf registers *without* ad hoc aliases would get a
unique regunit, but that caused situations where regunits could not be
used to distinguish a register from its subregs. For example:

- Registers A and B alias. They both get regunit 0 only.
- Register C has subregs A and B. It inherits regunits from its subregs,
  so it also gets regunit 0 only.

After this fix, registers A and B will get a unique regunit in addition
to the regunit representing the alias, for example:

- A will get regunits 0 and 1.
- B will get regunits 0 and 2.
- C will get regunits 0, 1 and 2.
---
 llvm/test/TableGen/SubRegsAndAliases.td       | 80 +++++++++++++++++++
 .../TableGen/Common/CodeGenRegisters.cpp      | 27 +++----
 llvm/utils/TableGen/RegisterInfoEmitter.cpp   |  2 +
 3 files changed, 93 insertions(+), 16 deletions(-)
 create mode 100644 llvm/test/TableGen/SubRegsAndAliases.td

diff --git a/llvm/test/TableGen/SubRegsAndAliases.td b/llvm/test/TableGen/SubRegsAndAliases.td
new file mode 100644
index 0000000000000..ec450f8945b49
--- /dev/null
+++ b/llvm/test/TableGen/SubRegsAndAliases.td
@@ -0,0 +1,80 @@
+// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o /dev/null 2>&1 | FileCheck %s
+include "llvm/Target/Target.td"
+def TestTarget : Target;
+
+def lo : SubRegIndex<32, 0>;
+def hi : SubRegIndex<32, 32>;
+
+// One superreg with two subregs.
+def Alo : Register<"">;
+def Ahi : Register<"">;
+def A : Register<""> {
+  let SubRegs = [Alo, Ahi];
+  let SubRegIndices = [lo, hi];
+}
+
+// Same but the subregs alias.
+def Blo : Register<"">;
+def Bhi : Register<""> {
+  let Aliases = [Blo];
+}
+def B : Register<""> {
+  let SubRegs = [Blo, Bhi];
+  let SubRegIndices = [lo, hi];
+}
+
+// Same but the superreg has an alias.
+def Clo : Register<"">;
+def Chi : Register<"">;
+def D : Register<"">;
+def C : Register<""> {
+  let SubRegs = [Clo, Chi];
+  let SubRegIndices = [lo, hi];
+  let Aliases = [D];
+}
+
+def TestRC : RegisterClass<"Test", [i64], 0, (add A, B)>;
+
+// CHECK-LABEL: Register A:
+// CHECK: SubReg hi = Ahi
+// CHECK: SubReg lo = Alo
+// CHECK: RegUnit 0
+// CHECK: RegUnit 1
+
+// CHECK-LABEL: Register Ahi:
+// CHECK: RegUnit 1
+
+// CHECK-LABEL: Register Alo:
+// CHECK: RegUnit 0
+
+// CHECK-LABEL: Register B:
+// CHECK: SubReg hi = Bhi
+// CHECK: SubReg lo = Blo
+// CHECK: RegUnit 2
+// CHECK: RegUnit 3
+// CHECK: RegUnit 4
+
+// CHECK-LABEL: Register Bhi:
+// CHECK: RegUnit 3
+// CHECK: RegUnit 4
+
+// CHECK-LABEL: Register Blo:
+// CHECK: RegUnit 2
+// CHECK: RegUnit 3
+
+// CHECK-LABEL: Register C:
+// CHECK: SubReg hi = Chi
+// CHECK: SubReg lo = Clo
+// CHECK: RegUnit 5
+// CHECK: RegUnit 6
+// CHECK: RegUnit 7
+
+// CHECK-LABEL: Register Chi:
+// CHECK: RegUnit 6
+
+// CHECK-LABEL: Register Clo:
+// CHECK: RegUnit 5
+
+// CHECK-LABEL: Register D:
+// CHECK: RegUnit 7
+// CHECK: RegUnit 8
diff --git a/llvm/utils/TableGen/Common/CodeGenRegisters.cpp b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp
index 639f94f79ecd7..3b7604a05fa88 100644
--- a/llvm/utils/TableGen/Common/CodeGenRegisters.cpp
+++ b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp
@@ -414,16 +414,17 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
 
   // Initialize RegUnitList. Because getSubRegs is called recursively, this
   // processes the register hierarchy in postorder.
-  //
-  // Inherit all sub-register units. It is good enough to look at the explicit
-  // sub-registers, the other registers won't contribute any more units.
-  for (const CodeGenRegister *SR : ExplicitSubRegs)
-    RegUnits |= SR->RegUnits;
-
-  // Absent any ad hoc aliasing, we create one register unit per leaf register.
-  // These units correspond to the maximal cliques in the register overlap
-  // graph which is optimal.
-  //
+  if (ExplicitSubRegs.empty()) {
+    // Create one register unit per leaf register. These units correspond to the
+    // maximal cliques in the register overlap graph which is optimal.
+    RegUnits.set(RegBank.newRegUnit(this));
+  } else {
+    // Inherit all sub-register units. It is good enough to look at the explicit
+    // sub-registers, the other registers won't contribute any more units.
+    for (const CodeGenRegister *SR : ExplicitSubRegs)
+      RegUnits |= SR->RegUnits;
+  }
+
   // When there is ad hoc aliasing, we simply create one unit per edge in the
   // undirected ad hoc aliasing graph. Technically, we could do better by
   // identifying maximal cliques in the ad hoc graph, but cliques larger than 2
@@ -440,12 +441,6 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
     AR->RegUnits.set(Unit);
   }
 
-  // Finally, create units for leaf registers without ad hoc aliases. Note that
-  // a leaf register with ad hoc aliases doesn't get its own unit - it isn't
-  // necessary. This means the aliasing leaf registers can share a single unit.
-  if (RegUnits.empty())
-    RegUnits.set(RegBank.newRegUnit(this));
-
   // We have now computed the native register units. More may be adopted later
   // for balancing purposes.
   NativeRegUnits = RegUnits;
diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
index 98f0d7eaaff38..c2c6ab1f77aaa 100644
--- a/llvm/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
@@ -1934,6 +1934,8 @@ void RegisterInfoEmitter::debugDump(raw_ostream &OS) {
       OS << "\tSubReg " << SubIdx->getName() << " = " << SubReg->getName()
          << '\n';
     }
+    for (unsigned U : R.getNativeRegUnits())
+      OS << "\tRegUnit " << U << '\n';
   }
 }
 



More information about the llvm-commits mailing list