[llvm-branch-commits] [llvm] TableGen: Look up sub-register index compositions in an array (PR #232818)

Matt Arsenault via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sat Oct 17 01:29:58 PDT 2026


https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/232818

>From 1662c23ba91ff7088dc7d8a0ed9f9cf8c0661807 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Fri, 16 Oct 2026 05:42:31 -0700
Subject: [PATCH 1/2] TableGen: Look up sub-register index compositions in an
 array

compose() looked up each composition in a std::map. It is called for
every super-register class set in extendSuperRegClasses, and by
addComposite. Sub-register indices are numbered densely, so also keep
each index's compositions in an array indexed by enum value. For
AMDGPU's 400 indices this is about 1 MB.

AMDGPU tablegen runs that build the register bank:

            Gigainstructions  Gigacycles     CPU seconds
  Before    746               474            148
  After     721 (-3.4%)       446 (-6.1%)    139 (-5.8%)

Co-authored-by: Claude Opus 5.5 <noreply at anthropic.com>
---
 llvm/utils/TableGen/Common/CodeGenRegisters.h | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/llvm/utils/TableGen/Common/CodeGenRegisters.h b/llvm/utils/TableGen/Common/CodeGenRegisters.h
index 333bc4aa07314..4b648db3c9103 100644
--- a/llvm/utils/TableGen/Common/CodeGenRegisters.h
+++ b/llvm/utils/TableGen/Common/CodeGenRegisters.h
@@ -99,9 +99,9 @@ class CodeGenSubRegIndex {
 
   // Returns the subreg index that results from composing this with Idx.
   // Returns NULL if this and Idx don't compose.
-  CodeGenSubRegIndex *compose(CodeGenSubRegIndex *Idx) const {
-    CompMap::const_iterator I = Composed.find(Idx);
-    return I == Composed.end() ? nullptr : I->second;
+  CodeGenSubRegIndex *compose(const CodeGenSubRegIndex *Idx) const {
+    return Idx->EnumValue < ComposedByIdx.size() ? ComposedByIdx[Idx->EnumValue]
+                                                 : nullptr;
   }
 
   // Add a composite subreg index: this+A = B.
@@ -109,15 +109,20 @@ class CodeGenSubRegIndex {
   CodeGenSubRegIndex *addComposite(CodeGenSubRegIndex *A, CodeGenSubRegIndex *B,
                                    const CodeGenHwModes &CGH) {
     assert(A && B);
-    std::pair<CompMap::iterator, bool> Ins = Composed.try_emplace(A, B);
     unsigned NumModes = CGH.getNumModeIds();
 
     // An earlier identical call already added the ranges for every mode, so
     // there is nothing left to do once B has an offset in all of them.
-    if (!Ins.second && Ins.first->second == B &&
-        B->hasOffsetInAllModes(NumModes))
+    if (compose(A) == B && B->hasOffsetInAllModes(NumModes))
       return nullptr;
 
+    std::pair<CompMap::iterator, bool> Ins = Composed.try_emplace(A, B);
+    if (Ins.second) {
+      if (ComposedByIdx.size() <= A->EnumValue)
+        ComposedByIdx.resize(A->EnumValue + 1);
+      ComposedByIdx[A->EnumValue] = B;
+    }
+
     // Synthetic subreg indices that aren't contiguous (for instance ARM
     // register tuples) don't have a bit range, so it's OK to let
     // B->Offset == -1. For the other cases, accumulate the offset and set
@@ -186,6 +191,8 @@ class CodeGenSubRegIndex {
 
   bool OffsetInAllModes = false;
   CompMap Composed;
+  // Composed indexed by the EnumValue of the first index, for compose().
+  SmallVector<CodeGenSubRegIndex *, 0> ComposedByIdx;
 };
 
 /// CodeGenRegister - Represents a register definition.

>From f499a0766a1582f7e04c04512c0110fd7259c2b8 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Sat, 17 Oct 2026 01:05:36 -0700
Subject: [PATCH 2/2] Return conflicting compositions from addComposite
 immediately

Check for an existing composition up front: return a conflicting one
right away, instead of after updating B's ranges from a composition that
isn't recorded. This no longer needs the try_emplace result. The
generated code for all in-tree targets is unchanged, and the instruction
count is the same.

Co-authored-by: Claude Opus 5.5 <noreply at anthropic.com>
---
 llvm/utils/TableGen/Common/CodeGenRegisters.h | 22 ++++++++++++-------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/llvm/utils/TableGen/Common/CodeGenRegisters.h b/llvm/utils/TableGen/Common/CodeGenRegisters.h
index 4b648db3c9103..3666469f5726f 100644
--- a/llvm/utils/TableGen/Common/CodeGenRegisters.h
+++ b/llvm/utils/TableGen/Common/CodeGenRegisters.h
@@ -111,13 +111,19 @@ class CodeGenSubRegIndex {
     assert(A && B);
     unsigned NumModes = CGH.getNumModeIds();
 
-    // An earlier identical call already added the ranges for every mode, so
-    // there is nothing left to do once B has an offset in all of them.
-    if (compose(A) == B && B->hasOffsetInAllModes(NumModes))
-      return nullptr;
-
-    std::pair<CompMap::iterator, bool> Ins = Composed.try_emplace(A, B);
-    if (Ins.second) {
+    CodeGenSubRegIndex *Prev = compose(A);
+    if (Prev == B) {
+      // An earlier identical call already added the ranges for every mode, so
+      // there is nothing left to do once B has an offset in all of them.
+      if (B->hasOffsetInAllModes(NumModes))
+        return nullptr;
+    } else {
+      // Keep an existing conflicting composition, and return it.
+      if (Prev)
+        return Prev;
+
+      if (!Composed.try_emplace(A, B).second)
+        llvm_unreachable("ComposedByIdx out of sync with Composed");
       if (ComposedByIdx.size() <= A->EnumValue)
         ComposedByIdx.resize(A->EnumValue + 1);
       ComposedByIdx[A->EnumValue] = B;
@@ -153,7 +159,7 @@ class CodeGenSubRegIndex {
       BRange.Size = ARange.Size;
     }
 
-    return (Ins.second || Ins.first->second == B) ? nullptr : Ins.first->second;
+    return nullptr;
   }
 
   // Update the composite maps of components specified in 'ComposedOf'.



More information about the llvm-branch-commits mailing list