[llvm] [PowerPC][NFC] Refactor Register class and operand definitons (PR #185647)

Lei Huang via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 10 06:26:39 PDT 2026


https://github.com/lei137 created https://github.com/llvm/llvm-project/pull/185647

Main change is to add a multiclass to generate RegisterOperands and it's required AsmOperand to reduce code
duplication.

Asissted by AI.

>From e20613c0d0df38b566ca1dc5cfd7cb4452356a12 Mon Sep 17 00:00:00 2001
From: Lei Huang <lei at ca.ibm.com>
Date: Fri, 6 Mar 2026 08:58:32 -0500
Subject: [PATCH 1/3] initial refactor of register classes

---
 llvm/lib/Target/PowerPC/PPCRegisterClasses.td | 136 ++++++++++
 llvm/lib/Target/PowerPC/PPCRegisterInfo.td    | 240 ++++++++----------
 llvm/lib/Target/PowerPC/PPCRegisterInfoDMR.td |  36 +--
 llvm/lib/Target/PowerPC/PPCRegisterInfoMMA.td |  69 +++--
 4 files changed, 278 insertions(+), 203 deletions(-)
 create mode 100644 llvm/lib/Target/PowerPC/PPCRegisterClasses.td

diff --git a/llvm/lib/Target/PowerPC/PPCRegisterClasses.td b/llvm/lib/Target/PowerPC/PPCRegisterClasses.td
new file mode 100644
index 0000000000000..4a44b9915e9e2
--- /dev/null
+++ b/llvm/lib/Target/PowerPC/PPCRegisterClasses.td
@@ -0,0 +1,136 @@
+//===-- PPCRegisterClasses.td - PPC Register Class Definitions -*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines base classes for PowerPC register classes to reduce
+// repetition and make it easier to define new register classes.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Base Register Class Definitions
+//===----------------------------------------------------------------------===//
+
+// Base class for all PPC register classes - sets namespace to "PPC"
+class PPCRegisterClass<list<ValueType> regTypes, int alignment, dag regList>
+  : RegisterClass<"PPC", regTypes, alignment, regList>;
+
+// Register class with explicit size
+class PPCRegisterClassWithSize<list<ValueType> regTypes, int alignment,
+                               dag regList, int size>
+  : PPCRegisterClass<regTypes, alignment, regList> {
+  let Size = size;
+}
+
+// Register class that is not allocatable
+class PPCNonAllocatableRegisterClass<list<ValueType> regTypes, int alignment,
+                                     dag regList>
+  : PPCRegisterClass<regTypes, alignment, regList> {
+  let isAllocatable = 0;
+}
+
+// Register class with custom copy cost
+class PPCRegisterClassWithCopyCost<list<ValueType> regTypes, int alignment,
+                                   dag regList, int copyCost>
+  : PPCRegisterClass<regTypes, alignment, regList> {
+  let CopyCost = copyCost;
+}
+
+// Register class with allocation priority
+class PPCRegisterClassWithPriority<list<ValueType> regTypes, int alignment,
+                                   dag regList, int allocPriority,
+                                   bit globalPriority = 0, int size = 0>
+  : PPCRegisterClass<regTypes, alignment, regList> {
+  let AllocationPriority = allocPriority;
+  let GlobalPriority = globalPriority;
+  let Size = size;
+}
+
+// Register class with alternative allocation orders
+class PPCRegisterClassWithAltOrders<list<ValueType> regTypes, int alignment,
+                                    dag regList, list<dag> altOrders,
+                                    code altOrderSelect>
+  : PPCRegisterClass<regTypes, alignment, regList> {
+  let AltOrders = altOrders;
+  let AltOrderSelect = altOrderSelect;
+}
+
+// Register class with alternative orders and size
+class PPCRegisterClassWithAltOrdersAndSize<list<ValueType> regTypes, int alignment,
+                                           dag regList, list<dag> altOrders,
+                                           code altOrderSelect, int size>
+  : PPCRegisterClass<regTypes, alignment, regList> {
+  let AltOrders = altOrders;
+  let AltOrderSelect = altOrderSelect;
+  let Size = size;
+}
+
+// Non-allocatable register class with copy cost
+class PPCNonAllocatableRegisterClassWithCopyCost<list<ValueType> regTypes,
+                                                 int alignment, dag regList,
+                                                 int copyCost>
+  : PPCRegisterClass<regTypes, alignment, regList> {
+  let isAllocatable = 0;
+  let CopyCost = copyCost;
+}
+
+//===----------------------------------------------------------------------===//
+// Specialized Base Classes for Common PPC Patterns
+//===----------------------------------------------------------------------===//
+
+// GPR-style register class with alternative orders for different ABIs
+class PPCGPRRegisterClass<list<ValueType> regTypes, int alignment, dag regList,
+                          dag altOrder1, dag altOrder2>
+  : PPCRegisterClassWithAltOrders<regTypes, alignment, regList,
+      [altOrder1, altOrder2],
+      [{
+        return MF.getSubtarget<PPCSubtarget>().getGPRAllocationOrderIdx();
+      }]>;
+
+// Vector/VSX register class with size
+class PPCVectorRegisterClass<list<ValueType> regTypes, int alignment,
+                             dag regList, int size>
+  : PPCRegisterClassWithSize<regTypes, alignment, regList, size>;
+
+// Accumulator register class with high allocation priority
+class PPCAccumulatorRegisterClass<list<ValueType> regTypes, int alignment,
+                                  dag regList, int allocPriority,
+                                  bit globalPriority, int size>
+  : PPCRegisterClassWithPriority<regTypes, alignment, regList,
+                                 allocPriority, globalPriority, size>;
+
+// DMR-style register class with size
+class PPCDMRRegisterClass<list<ValueType> regTypes, int alignment,
+                          dag regList, int size>
+  : PPCRegisterClassWithSize<regTypes, alignment, regList, size>;
+
+// Condition register class with alternative orders for ELFv2 ABI
+class PPCCRRegisterClass<list<ValueType> regTypes, int alignment, dag regList,
+                         dag altOrder, int size = 0>
+  : PPCRegisterClass<regTypes, alignment, regList> {
+  let AltOrders = [altOrder];
+  let AltOrderSelect = [{
+    return MF.getSubtarget<PPCSubtarget>().isELFv2ABI() &&
+           MF.getInfo<PPCFunctionInfo>()->isNonVolatileCRDisabled();
+  }];
+  let Size = !if(!ne(size, 0), size, 0);
+}
+
+// Special purpose register class (non-allocatable)
+class PPCSPRegisterClass<list<ValueType> regTypes, int alignment, dag regList>
+  : PPCNonAllocatableRegisterClass<regTypes, alignment, regList>;
+
+// Paired register class with alternative orders for 64-bit ELF ABI
+class PPCPairedRegisterClass<list<ValueType> regTypes, int alignment,
+                             dag regList, dag altOrder, int size>
+  : PPCRegisterClass<regTypes, alignment, regList> {
+  let AltOrders = [altOrder];
+  let AltOrderSelect = [{
+    return MF.getSubtarget<PPCSubtarget>().is64BitELFABI();
+  }];
+  let Size = size;
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
index 28cfbc9991c3c..eab077fde5266 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
@@ -10,6 +10,7 @@
 //===----------------------------------------------------------------------===//
 
 include "PPCOperands.td"
+include "PPCRegisterClasses.td"
 
 let Namespace = "PPC" in {
   def sub_lt : SubRegIndex<1>;
@@ -167,10 +168,10 @@ let isArtificial = 1 in {
   }
 }
 
-let isAllocatable = 0, CopyCost = -1 in {
-  def VFHRC : RegisterClass<"PPC", [f64], 64, (sequence "VFH%u", 0, 31)>;
-  def FHRC : RegisterClass<"PPC", [f64], 64, (sequence "FH%u", 0, 31)>;
-}
+def VFHRC : PPCNonAllocatableRegisterClassWithCopyCost<[f64], 64,
+              (sequence "VFH%u", 0, 31), -1>;
+def FHRC : PPCNonAllocatableRegisterClassWithCopyCost<[f64], 64,
+             (sequence "FH%u", 0, 31), -1>;
 
 // Floating-point pair registers
 foreach Index = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 } in {
@@ -296,71 +297,60 @@ def CARRY: SPR<1, "xer">, DwarfRegNum<[76]> {
 // that do nothing but change RM will not get deleted.
 def RM: PPCReg<"**ROUNDING MODE**">;
 
-let isAllocatable = 0 in
-def GPRC32 : RegisterClass<"PPC", [i32,f32], 32, (add (sequence "H%u", 2, 12),
-                                                      (sequence "H%u", 30, 13),
-                                                      H31, H0, H1)>;
+def GPRC32 : PPCNonAllocatableRegisterClass<[i32,f32], 32,
+               (add (sequence "H%u", 2, 12),
+                    (sequence "H%u", 30, 13),
+                    H31, H0, H1)>;
 
 /// Register classes
 // Allocate volatiles first
 // then nonvolatiles in reverse order since stmw/lmw save from rN to r31
-def GPRC : RegisterClass<"PPC", [i32,f32], 32, (add (sequence "R%u", 2, 12),
-                                                    (sequence "R%u", 30, 13),
-                                                    R31, R0, R1, FP, BP)> {
-  // On non-Darwin PPC64 systems, R2 can be allocated, but must be restored, so
-  // put it at the end of the list.
-  // On AIX, CSRs are allocated starting from R31 according to:
-  // https://www.ibm.com/docs/en/ssw_aix_72/assembler/assembler_pdf.pdf.
-  // This also helps setting the correct `NumOfGPRsSaved' in traceback table.
-  let AltOrders = [(add (sub GPRC, R2), R2),
-                   (add (sequence "R%u", 2, 12),
-                        (sequence "R%u", 31, 13), R0, R1, FP, BP)];
-  let AltOrderSelect = [{
-    return MF.getSubtarget<PPCSubtarget>().getGPRAllocationOrderIdx();
-  }];
-}
-
-def G8RC : RegisterClass<"PPC", [i64], 64, (add (sequence "X%u", 2, 12),
-                                                (sequence "X%u", 30, 14),
-                                                X31, X13, X0, X1, FP8, BP8)> {
-  // On non-Darwin PPC64 systems, R2 can be allocated, but must be restored, so
-  // put it at the end of the list.
-  let AltOrders = [(add (sub G8RC, X2), X2),
-                   (add (sequence "X%u", 2, 12),
-                        (sequence "X%u", 31, 13), X0, X1, FP8, BP8)];
-  let AltOrderSelect = [{
-    return MF.getSubtarget<PPCSubtarget>().getGPRAllocationOrderIdx();
-  }];
-}
+def GPRC : PPCGPRRegisterClass<[i32,f32], 32,
+             (add (sequence "R%u", 2, 12),
+                  (sequence "R%u", 30, 13),
+                  R31, R0, R1, FP, BP),
+             // On non-Darwin PPC64 systems, R2 can be allocated, but must be restored, so
+             // put it at the end of the list.
+             (add (sub GPRC, R2), R2),
+             // On AIX, CSRs are allocated starting from R31 according to:
+             // https://www.ibm.com/docs/en/ssw_aix_72/assembler/assembler_pdf.pdf.
+             // This also helps setting the correct `NumOfGPRsSaved' in traceback table.
+             (add (sequence "R%u", 2, 12),
+                  (sequence "R%u", 31, 13), R0, R1, FP, BP)>;
+
+def G8RC : PPCGPRRegisterClass<[i64], 64,
+             (add (sequence "X%u", 2, 12),
+                  (sequence "X%u", 30, 14),
+                  X31, X13, X0, X1, FP8, BP8),
+             // On non-Darwin PPC64 systems, R2 can be allocated, but must be restored, so
+             // put it at the end of the list.
+             (add (sub G8RC, X2), X2),
+             (add (sequence "X%u", 2, 12),
+                  (sequence "X%u", 31, 13), X0, X1, FP8, BP8)>;
 
 // For some instructions r0 is special (representing the value 0 instead of
 // the value in the r0 register), and we use these register subclasses to
 // prevent r0 from being allocated for use by those instructions.
-def GPRC_NOR0 : RegisterClass<"PPC", [i32,f32], 32, (add (sub GPRC, R0), ZERO)> {
-  // On non-Darwin PPC64 systems, R2 can be allocated, but must be restored, so
-  // put it at the end of the list.
-  let AltOrders = [(add (sub GPRC_NOR0, R2), R2),
-                   (add (sequence "R%u", 2, 12),
-                        (sequence "R%u", 31, 13), R1, FP, BP, ZERO)];
-  let AltOrderSelect = [{
-    return MF.getSubtarget<PPCSubtarget>().getGPRAllocationOrderIdx();
-  }];
-}
-
-def G8RC_NOX0 : RegisterClass<"PPC", [i64], 64, (add (sub G8RC, X0), ZERO8)> {
-  // On non-Darwin PPC64 systems, R2 can be allocated, but must be restored, so
-  // put it at the end of the list.
-  let AltOrders = [(add (sub G8RC_NOX0, X2), X2),
-                   (add (sequence "X%u", 2, 12),
-                        (sequence "X%u", 31, 13), X1, FP8, BP8, ZERO8)];
-  let AltOrderSelect = [{
-    return MF.getSubtarget<PPCSubtarget>().getGPRAllocationOrderIdx();
-  }];
-}
-
-def SPERC : RegisterClass<"PPC", [f64], 64, (add (sequence "S%u", 2, 12),
-                                                (sequence "S%u", 30, 13),
-                                                S31, S0, S1)>;
+def GPRC_NOR0 : PPCGPRRegisterClass<[i32,f32], 32,
+                  (add (sub GPRC, R0), ZERO),
+                  // On non-Darwin PPC64 systems, R2 can be allocated, but must be restored, so
+                  // put it at the end of the list.
+                  (add (sub GPRC_NOR0, R2), R2),
+                  (add (sequence "R%u", 2, 12),
+                       (sequence "R%u", 31, 13), R1, FP, BP, ZERO)>;
+
+def G8RC_NOX0 : PPCGPRRegisterClass<[i64], 64,
+                  (add (sub G8RC, X0), ZERO8),
+                  // On non-Darwin PPC64 systems, R2 can be allocated, but must be restored, so
+                  // put it at the end of the list.
+                  (add (sub G8RC_NOX0, X2), X2),
+                  (add (sequence "X%u", 2, 12),
+                       (sequence "X%u", 31, 13), X1, FP8, BP8, ZERO8)>;
+
+def SPERC : PPCRegisterClass<[f64], 64,
+              (add (sequence "S%u", 2, 12),
+                   (sequence "S%u", 30, 13),
+                   S31, S0, S1)>;
 
 // Allocate volatiles first, then non-volatiles in reverse order. With the SVR4
 // ABI the size of the Floating-point register save area is determined by the
@@ -369,9 +359,10 @@ def SPERC : RegisterClass<"PPC", [f64], 64, (add (sequence "S%u", 2, 12),
 // previous stack frame. By allocating non-volatiles in reverse order we make
 // sure that the Floating-point register save area is always as small as
 // possible because there aren't any unused spill slots.
-def F8RC : RegisterClass<"PPC", [f64], 64, (add (sequence "F%u", 0, 13),
-                                                (sequence "F%u", 31, 14))>;
-def F4RC : RegisterClass<"PPC", [f32], 32, (add F8RC)>;
+def F8RC : PPCRegisterClass<[f64], 64,
+             (add (sequence "F%u", 0, 13),
+                  (sequence "F%u", 31, 14))>;
+def F4RC : PPCRegisterClass<[f32], 32, (add F8RC)>;
 
 // Floating point pair registers.
 // Note that the type used for this register class is ppcf128. This is not
@@ -380,47 +371,44 @@ def F4RC : RegisterClass<"PPC", [f32], 32, (add F8RC)>;
 // scheduling any of these instructions it should be safe to do this.
 // The reason we didn't use the correct type (Decimal Floating Point) is that
 // at the time of this implementation the correct type was not available.
-def FpRC :
-  RegisterClass<"PPC", [ppcf128], 128,
-                (add Fpair0, Fpair2, Fpair4, Fpair6, Fpair8, Fpair10, Fpair12,
-                     Fpair14, Fpair16, Fpair18, Fpair20, Fpair22, Fpair24,
-                     Fpair26, Fpair28, Fpair30)> {
-  let Size = 128;
-}
+def FpRC : PPCRegisterClassWithSize<[ppcf128], 128,
+             (add Fpair0, Fpair2, Fpair4, Fpair6, Fpair8, Fpair10, Fpair12,
+                  Fpair14, Fpair16, Fpair18, Fpair20, Fpair22, Fpair24,
+                  Fpair26, Fpair28, Fpair30), 128>;
 
-def VRRC : RegisterClass<"PPC",
-                         [v16i8,v8i16,v4i32,v2i64,v1i128,v4f32,v2f64, f128],
-                         128,
-                         (add V2, V3, V4, V5, V0, V1, V6, V7, V8, V9, V10, V11,
-                             V12, V13, V14, V15, V16, V17, V18, V19, V31, V30,
-                             V29, V28, V27, V26, V25, V24, V23, V22, V21, V20)>;
+def VRRC : PPCVectorRegisterClass<[v16i8,v8i16,v4i32,v2i64,v1i128,v4f32,v2f64, f128],
+             128,
+             (add V2, V3, V4, V5, V0, V1, V6, V7, V8, V9, V10, V11,
+                  V12, V13, V14, V15, V16, V17, V18, V19, V31, V30,
+                  V29, V28, V27, V26, V25, V24, V23, V22, V21, V20), 128>;
 
 // VSX register classes (the allocation order mirrors that of the corresponding
 // subregister classes).
-def VSLRC : RegisterClass<"PPC", [v4i32,v4f32,v2f64,v2i64], 128,
-                          (add (sequence "VSL%u", 0, 13),
-                               (sequence "VSL%u", 31, 14))>;
-def VSRC  : RegisterClass<"PPC", [v4i32,v4f32,v2f64,v2i64], 128,
-                          (add VSLRC, VRRC)>;
+def VSLRC : PPCVectorRegisterClass<[v4i32,v4f32,v2f64,v2i64], 128,
+              (add (sequence "VSL%u", 0, 13),
+                   (sequence "VSL%u", 31, 14)), 128>;
+def VSRC  : PPCVectorRegisterClass<[v4i32,v4f32,v2f64,v2i64], 128,
+              (add VSLRC, VRRC), 128>;
 
 // Register classes for the 64-bit "scalar" VSX subregisters.
-def VFRC :  RegisterClass<"PPC", [f64], 64,
-                          (add VF2, VF3, VF4, VF5, VF0, VF1, VF6, VF7,
-                               VF8, VF9, VF10, VF11, VF12, VF13, VF14,
-                               VF15, VF16, VF17, VF18, VF19, VF31, VF30,
-                               VF29, VF28, VF27, VF26, VF25, VF24, VF23,
-                               VF22, VF21, VF20)>;
-def VSFRC : RegisterClass<"PPC", [f64], 64, (add F8RC, VFRC)>;
+def VFRC :  PPCRegisterClass<[f64], 64,
+              (add VF2, VF3, VF4, VF5, VF0, VF1, VF6, VF7,
+                   VF8, VF9, VF10, VF11, VF12, VF13, VF14,
+                   VF15, VF16, VF17, VF18, VF19, VF31, VF30,
+                   VF29, VF28, VF27, VF26, VF25, VF24, VF23,
+                   VF22, VF21, VF20)>;
+def VSFRC : PPCRegisterClass<[f64], 64, (add F8RC, VFRC)>;
 
 // Allow spilling GPR's into caller-saved VSR's.
-def SPILLTOVSRRC : RegisterClass<"PPC", [i64, f64], 64, (add G8RC, (sub VSFRC,
-				(sequence "VF%u", 31, 20),
-				(sequence "F%u", 31, 14)))>;
+def SPILLTOVSRRC : PPCRegisterClass<[i64, f64], 64,
+                     (add G8RC, (sub VSFRC,
+                          (sequence "VF%u", 31, 20),
+                          (sequence "F%u", 31, 14)))>;
 
 // Register class for single precision scalars in VSX registers
-def VSSRC : RegisterClass<"PPC", [f32], 32, (add VSFRC)>;
+def VSSRC : PPCRegisterClass<[f32], 32, (add VSFRC)>;
 
-def CRBITRC : RegisterClass<"PPC", [i1], 32,
+def CRBITRC : PPCCRRegisterClass<[i1], 32,
   (add CR2LT, CR2GT, CR2EQ, CR2UN,
        CR3LT, CR3GT, CR3EQ, CR3UN,
        CR4LT, CR4GT, CR4EQ, CR4UN,
@@ -428,62 +416,36 @@ def CRBITRC : RegisterClass<"PPC", [i1], 32,
        CR6LT, CR6GT, CR6EQ, CR6UN,
        CR7LT, CR7GT, CR7EQ, CR7UN,
        CR1LT, CR1GT, CR1EQ, CR1UN,
-       CR0LT, CR0GT, CR0EQ, CR0UN)> {
-  let Size = 32;
-  let AltOrders = [(sub CRBITRC, CR2LT, CR2GT, CR2EQ, CR2UN, CR3LT, CR3GT,
-                        CR3EQ, CR3UN, CR4LT, CR4GT, CR4EQ, CR4UN)];
-  let AltOrderSelect = [{
-    return MF.getSubtarget<PPCSubtarget>().isELFv2ABI() &&
-           MF.getInfo<PPCFunctionInfo>()->isNonVolatileCRDisabled();
-  }];
-}
+       CR0LT, CR0GT, CR0EQ, CR0UN),
+  (sub CRBITRC, CR2LT, CR2GT, CR2EQ, CR2UN, CR3LT, CR3GT,
+       CR3EQ, CR3UN, CR4LT, CR4GT, CR4EQ, CR4UN), 32>;
 
-def CRRC : RegisterClass<"PPC", [i32], 32,
+def CRRC : PPCCRRegisterClass<[i32], 32,
   (add CR0, CR1, CR5, CR6,
-       CR7, CR2, CR3, CR4)> {
-  let AltOrders = [(sub CRRC, CR2, CR3, CR4)];
-  let AltOrderSelect = [{
-    return MF.getSubtarget<PPCSubtarget>().isELFv2ABI() &&
-           MF.getInfo<PPCFunctionInfo>()->isNonVolatileCRDisabled();
-  }];
-}
+       CR7, CR2, CR3, CR4),
+  (sub CRRC, CR2, CR3, CR4)>;
+
 // The CTR registers are not allocatable because they're used by the
 // decrement-and-branch instructions, and thus need to stay live across
 // multiple basic blocks.
-def CTRRC : RegisterClass<"PPC", [i32], 32, (add CTR)> {
-  let isAllocatable = 0;
-}
-def CTRRC8 : RegisterClass<"PPC", [i64], 64, (add CTR8)> {
-  let isAllocatable = 0;
-}
+def CTRRC : PPCSPRegisterClass<[i32], 32, (add CTR)>;
+def CTRRC8 : PPCSPRegisterClass<[i64], 64, (add CTR8)>;
 
-def LRRC : RegisterClass<"PPC", [i32], 32, (add LR)> {
-  let isAllocatable = 0;
-}
-def LR8RC : RegisterClass<"PPC", [i64], 64, (add LR8)> {
-  let isAllocatable = 0;
-}
+def LRRC : PPCSPRegisterClass<[i32], 32, (add LR)>;
+def LR8RC : PPCSPRegisterClass<[i64], 64, (add LR8)>;
 
-def VRSAVERC : RegisterClass<"PPC", [i32], 32, (add VRSAVE)>;
-def CARRYRC : RegisterClass<"PPC", [i32], 32, (add CARRY, XER)> {
-  let CopyCost = -1;
-  let isAllocatable = 0;
-}
+def VRSAVERC : PPCRegisterClass<[i32], 32, (add VRSAVE)>;
+def CARRYRC : PPCNonAllocatableRegisterClassWithCopyCost<[i32], 32,
+                (add CARRY, XER), -1>;
 
 // Make AllocationOrder as similar as G8RC's to avoid potential spilling.
 // Similarly, we have an AltOrder for 64-bit ELF ABI which r2 is allocated
 // at last.
-def G8pRC :
-  RegisterClass<"PPC", [untyped], 128,
-                (add (sequence "G8p%u", 1, 5),
-                     (sequence "G8p%u", 14, 7),
-                     G8p15, G8p6, G8p0)> {
-  let AltOrders = [(add (sub G8pRC, G8p1), G8p1)];
-  let AltOrderSelect = [{
-    return MF.getSubtarget<PPCSubtarget>().is64BitELFABI();
-  }];
-  let Size = 128;
-}
+def G8pRC : PPCPairedRegisterClass<[untyped], 128,
+              (add (sequence "G8p%u", 1, 5),
+                   (sequence "G8p%u", 14, 7),
+                   G8p15, G8p6, G8p0),
+              (add (sub G8pRC, G8p1), G8p1), 128>;
 
 include "PPCRegisterInfoMMA.td"
 include "PPCRegisterInfoDMR.td"
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfoDMR.td b/llvm/lib/Target/PowerPC/PPCRegisterInfoDMR.td
index 1c3e7621825bd..145cff5e1c9cb 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfoDMR.td
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfoDMR.td
@@ -133,32 +133,20 @@ let SubRegIndices = [sub_dmr0, sub_dmr1] in {
   def DMRp3 : DMRp<3, "dmrp3", [DMR6, DMR7]>, DwarfRegNum<[-1, -1]>;
 }
 
-def DMRROWRC :  RegisterClass<"PPC", [v128i1], 128,
-                               (add (sequence "DMRROW%u", 0, 63))> {
-  let Size = 128;
-}
+def DMRROWRC : PPCDMRRegisterClass<[v128i1], 128,
+                 (add (sequence "DMRROW%u", 0, 63)), 128>;
 
-def DMRROWpRC :  RegisterClass<"PPC", [v256i1], 128,
-                               (add (sequence "DMRROWp%u", 0, 31))> {
-  let Size = 256;
-}
+def DMRROWpRC : PPCDMRRegisterClass<[v256i1], 128,
+                  (add (sequence "DMRROWp%u", 0, 31)), 256>;
 
-def WACCRC : RegisterClass<"PPC", [v512i1], 128,
-                           (add (sequence "WACC%u", 0, 7))> {
-  let Size = 512;
-}
+def WACCRC : PPCDMRRegisterClass<[v512i1], 128,
+               (add (sequence "WACC%u", 0, 7)), 512>;
 
-def WACC_HIRC : RegisterClass<"PPC", [v512i1], 128,
-                              (add (sequence "WACC_HI%u", 0, 7))> {
-  let Size = 512;
-}
+def WACC_HIRC : PPCDMRRegisterClass<[v512i1], 128,
+                  (add (sequence "WACC_HI%u", 0, 7)), 512>;
 
-def DMRRC : RegisterClass<"PPC", [v1024i1], 128,
-                           (add (sequence "DMR%u", 0, 7))> {
-  let Size = 1024;
-}
+def DMRRC : PPCDMRRegisterClass<[v1024i1], 128,
+              (add (sequence "DMR%u", 0, 7)), 1024>;
 
-def DMRpRC : RegisterClass<"PPC", [v2048i1], 128,
-                           (add DMRp0, DMRp1, DMRp2, DMRp3)> {
-  let Size = 2048;
-}
+def DMRpRC : PPCDMRRegisterClass<[v2048i1], 128,
+               (add DMRp0, DMRp1, DMRp2, DMRp3), 2048>;
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfoMMA.td b/llvm/lib/Target/PowerPC/PPCRegisterInfoMMA.td
index 57f4545516a00..2029a61c9409c 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfoMMA.td
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfoMMA.td
@@ -45,20 +45,15 @@ let SubRegIndices = [sub_pair0, sub_pair1] in {
   def ACC6 : ACC<6, "acc6", [VSRp12, VSRp13]>, DwarfRegNum<[-1, -1]>;
   def ACC7 : ACC<7, "acc7", [VSRp14, VSRp15]>, DwarfRegNum<[-1, -1]>;
 }
-def ACCRC : RegisterClass<"PPC", [v512i1], 128, (add ACC0, ACC1, ACC2, ACC3,
-                                                      ACC4, ACC5, ACC6, ACC7)> {
-  // The AllocationPriority is in the range [0, 31]. Assigned the ACC registers
-  // the highest possible priority in this range to force the register allocator
-  // to assign these registers first. This is done because the ACC registers
-  // must represent 4 advacent vector registers. For example ACC1 must be
-  // VS4 - VS7.
-  let AllocationPriority = 31;
-
-  // We want to allocate these registers even before we allocate
-  // global ranges.
-  let GlobalPriority = true;
-  let Size = 512;
-}
+// The AllocationPriority is in the range [0, 31]. Assigned the ACC registers
+// the highest possible priority in this range to force the register allocator
+// to assign these registers first. This is done because the ACC registers
+// must represent 4 advacent vector registers. For example ACC1 must be
+// VS4 - VS7.
+// We want to allocate these registers even before we allocate global ranges.
+def ACCRC : PPCAccumulatorRegisterClass<[v512i1], 128,
+              (add ACC0, ACC1, ACC2, ACC3, ACC4, ACC5, ACC6, ACC7),
+              31, 1, 512>;
 
 let SubRegIndices = [sub_pair0, sub_pair1] in {
   def UACC0 : UACC<0, "acc0", [VSRp0, VSRp1]>, DwarfRegNum<[-1, -1]>;
@@ -70,17 +65,14 @@ let SubRegIndices = [sub_pair0, sub_pair1] in {
   def UACC6 : UACC<6, "acc6", [VSRp12, VSRp13]>, DwarfRegNum<[-1, -1]>;
   def UACC7 : UACC<7, "acc7", [VSRp14, VSRp15]>, DwarfRegNum<[-1, -1]>;
 }
-def UACCRC : RegisterClass<"PPC", [v512i1], 128,
-                           (add UACC0, UACC1, UACC2, UACC3,
-                                UACC4, UACC5, UACC6, UACC7)> {
-  // The AllocationPriority for the UACC registers is still high and must be at
-  // least 32 as we want to allocate these registers before we allocate other
-  // global ranges. The value must be less than the AllocationPriority of the
-  // ACC registers.
-  let AllocationPriority = 4;
-  let GlobalPriority = true;
-  let Size = 512;
-}
+// The AllocationPriority for the UACC registers is still high and must be at
+// least 32 as we want to allocate these registers before we allocate other
+// global ranges. The value must be less than the AllocationPriority of the
+// ACC registers.
+def UACCRC : PPCAccumulatorRegisterClass<[v512i1], 128,
+               (add UACC0, UACC1, UACC2, UACC3,
+                    UACC4, UACC5, UACC6, UACC7),
+               4, 1, 512>;
 
 // FIXME: This allocation order may increase stack frame size when allocating
 // non-volatile registers.
@@ -89,21 +81,18 @@ def UACCRC : RegisterClass<"PPC", [v512i1], 128,
 // ones, to reduce interference with accumulator registers (lower 32 VSRs).
 // This reduces copies when loading for accumulators, which is common use for
 // paired VSX registers.
-def VSRpRC :
-  RegisterClass<"PPC", [v256i1], 128,
-                (add VSRp17, VSRp18, VSRp16, VSRp19, VSRp20, VSRp21,
-                     VSRp22, VSRp23, VSRp24, VSRp25, VSRp31, VSRp30,
-                     VSRp29, VSRp28, VSRp27, VSRp26,
-                     (sequence "VSRp%u", 0, 6),
-                     (sequence "VSRp%u", 15, 7))> {
-  // Give the VSRp registers a non-zero AllocationPriority. The value is less
-  // than 32 as these registers should not always be allocated before global
-  // ranges and the value should be less than the AllocationPriority - 32 for
-  // the UACC registers. Even global VSRp registers should be allocated after
-  // the UACC registers have been chosen.
-  let AllocationPriority = 2;
-  let Size = 256;
-}
+// Give the VSRp registers a non-zero AllocationPriority. The value is less
+// than 32 as these registers should not always be allocated before global
+// ranges and the value should be less than the AllocationPriority - 32 for
+// the UACC registers. Even global VSRp registers should be allocated after
+// the UACC registers have been chosen.
+def VSRpRC : PPCRegisterClassWithPriority<[v256i1], 128,
+               (add VSRp17, VSRp18, VSRp16, VSRp19, VSRp20, VSRp21,
+                    VSRp22, VSRp23, VSRp24, VSRp25, VSRp31, VSRp30,
+                    VSRp29, VSRp28, VSRp27, VSRp26,
+                    (sequence "VSRp%u", 0, 6),
+                    (sequence "VSRp%u", 15, 7)),
+               2, 0, 256>;
 
 
 

>From 99b1f95f8f697dc49d777b4d7de3e58c954da283 Mon Sep 17 00:00:00 2001
From: Lei Huang <lei at ca.ibm.com>
Date: Fri, 6 Mar 2026 12:04:54 -0500
Subject: [PATCH 2/3] add refactor for register operands

---
 .../Target/PowerPC/AsmParser/PPCAsmParser.cpp |   8 +-
 llvm/lib/Target/PowerPC/PPCInstrInfo.td       |   1 +
 llvm/lib/Target/PowerPC/PPCRegisterClasses.td | 125 ++++-----
 llvm/lib/Target/PowerPC/PPCRegisterInfo.td    | 253 ++++--------------
 llvm/lib/Target/PowerPC/PPCRegisterInfoDMR.td |  12 +-
 llvm/lib/Target/PowerPC/PPCRegisterInfoMMA.td |   4 +-
 6 files changed, 127 insertions(+), 276 deletions(-)

diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index b07f95018ca90..7b07c0881d453 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -458,7 +458,7 @@ struct PPCOperand : public MCParsedAsmOperand {
     Inst.addOperand(MCOperand::createReg(RRegs[getRegNum()]));
   }
 
-  void addRegGPRCNoR0Operands(MCInst &Inst, unsigned N) const {
+  void addRegGPRC_NOR0Operands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
     Inst.addOperand(MCOperand::createReg(RRegsNoR0[getRegNum()]));
   }
@@ -468,7 +468,7 @@ struct PPCOperand : public MCParsedAsmOperand {
     Inst.addOperand(MCOperand::createReg(XRegs[getRegNum()]));
   }
 
-  void addRegG8RCNoX0Operands(MCInst &Inst, unsigned N) const {
+  void addRegG8RC_NOX0Operands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
     Inst.addOperand(MCOperand::createReg(XRegsNoX0[getRegNum()]));
   }
@@ -487,9 +487,9 @@ struct PPCOperand : public MCParsedAsmOperand {
 
   void addRegGxRCNoR0Operands(MCInst &Inst, unsigned N) const {
     if (isPPC64())
-      addRegG8RCNoX0Operands(Inst, N);
+      addRegG8RC_NOX0Operands(Inst, N);
     else
-      addRegGPRCNoR0Operands(Inst, N);
+      addRegGPRC_NOR0Operands(Inst, N);
   }
 
   void addRegF4RCOperands(MCInst &Inst, unsigned N) const {
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
index cc5b7d90fd189..3271e4d279f56 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
@@ -733,6 +733,7 @@ def nzFPImmExactInti5 : PatLeaf<(fpimm), [{
   return IsExact && IntResult <= 15 && IntResult >= -16 && !FloatValue.isZero();
 }]>;
 
+// Floating point zero immediates (positive and negative)
 def fpimm0 : PatLeaf<(fpimm), [{ return N->isExactlyValue(+0.0); }]>;
 def fpimm0neg : PatLeaf<(fpimm), [{return N->isExactlyValue(-0.0);}]>;
 
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterClasses.td b/llvm/lib/Target/PowerPC/PPCRegisterClasses.td
index 4a44b9915e9e2..9da7916de1777 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterClasses.td
+++ b/llvm/lib/Target/PowerPC/PPCRegisterClasses.td
@@ -19,13 +19,52 @@
 class PPCRegisterClass<list<ValueType> regTypes, int alignment, dag regList>
   : RegisterClass<"PPC", regTypes, alignment, regList>;
 
-// Register class with explicit size
-class PPCRegisterClassWithSize<list<ValueType> regTypes, int alignment,
-                               dag regList, int size>
-  : PPCRegisterClass<regTypes, alignment, regList> {
-  let Size = size;
+//===----------------------------------------------------------------------===//
+// Classes for Generating RegisterOperand for Existing RegisterClass
+//===----------------------------------------------------------------------===//
+
+// Base class that creates a RegisterOperand for an already-defined RegisterClass,
+// assuming the AsmOperandClass already exists with the standard naming convention
+// (PPCReg<regClassName>AsmOperand).
+//
+// Usage: def spe4rc : PPCRegOperandOnly<"GPRC">;
+//   Creates: spe4rc RegisterOperand wrapping GPRC, using PPCRegGPRCAsmOperand
+class PPCRegOperandOnly<string regClassName>
+  : RegisterOperand<!cast<RegisterClass>(regClassName)> {
+  let ParserMatchClass = !cast<AsmOperandClass>(!strconcat("PPCReg", regClassName, "AsmOperand"));
 }
 
+// Multiclass that generates both the AsmOperandClass and RegisterOperand for an
+// already-defined RegisterClass. This eliminates the repetitive pattern of
+// manually defining these for each register class.
+//
+// Usage examples:
+//   defm GPRC : PPCRegOperand<"isRegNumber">;
+//     Creates: PPCRegGPRCAsmOperand and gprc (lowercase of GPRC)
+//   defm FpRC : PPCRegOperand<"isEvenRegNumber", "fpairrc">;
+//     Creates: PPCRegFpRCAsmOperand and fpairrc (custom name)
+//
+// The NAME in the defm statement should match the RegisterClass name.
+
+multiclass PPCRegOperand<string predicate, string operandName = ""> {
+  // Define the AsmOperandClass
+  def "PPCReg"#NAME#"AsmOperand" : AsmOperandClass {
+    let Name = "Reg"#NAME;
+    let PredicateMethod = predicate;
+  }
+  
+  // Define the RegisterOperand
+  // Use custom name if provided, otherwise use lowercase of NAME
+  def !if(!eq(operandName, ""), !tolower(NAME), operandName)
+    : RegisterOperand<!cast<RegisterClass>(NAME)> {
+    let ParserMatchClass = !cast<AsmOperandClass>("PPCReg"#NAME#"AsmOperand");
+  }
+}
+
+//===----------------------------------------------------------------------===//
+// Variant Register Class Definitions
+//===----------------------------------------------------------------------===//
+
 // Register class that is not allocatable
 class PPCNonAllocatableRegisterClass<list<ValueType> regTypes, int alignment,
                                      dag regList>
@@ -33,80 +72,37 @@ class PPCNonAllocatableRegisterClass<list<ValueType> regTypes, int alignment,
   let isAllocatable = 0;
 }
 
-// Register class with custom copy cost
-class PPCRegisterClassWithCopyCost<list<ValueType> regTypes, int alignment,
-                                   dag regList, int copyCost>
+// Register class with explicit size
+class PPCRegisterClassWithSize<list<ValueType> regTypes, int alignment,
+                               dag regList, int size>
   : PPCRegisterClass<regTypes, alignment, regList> {
-  let CopyCost = copyCost;
+  let Size = size;
 }
 
-// Register class with allocation priority
+// Register class with allocation priority and size
 class PPCRegisterClassWithPriority<list<ValueType> regTypes, int alignment,
                                    dag regList, int allocPriority,
-                                   bit globalPriority = 0, int size = 0>
+                                   bit globalPriority, int size>
   : PPCRegisterClass<regTypes, alignment, regList> {
   let AllocationPriority = allocPriority;
   let GlobalPriority = globalPriority;
   let Size = size;
 }
 
-// Register class with alternative allocation orders
-class PPCRegisterClassWithAltOrders<list<ValueType> regTypes, int alignment,
-                                    dag regList, list<dag> altOrders,
-                                    code altOrderSelect>
-  : PPCRegisterClass<regTypes, alignment, regList> {
-  let AltOrders = altOrders;
-  let AltOrderSelect = altOrderSelect;
-}
-
-// Register class with alternative orders and size
-class PPCRegisterClassWithAltOrdersAndSize<list<ValueType> regTypes, int alignment,
-                                           dag regList, list<dag> altOrders,
-                                           code altOrderSelect, int size>
-  : PPCRegisterClass<regTypes, alignment, regList> {
-  let AltOrders = altOrders;
-  let AltOrderSelect = altOrderSelect;
-  let Size = size;
-}
-
-// Non-allocatable register class with copy cost
-class PPCNonAllocatableRegisterClassWithCopyCost<list<ValueType> regTypes,
-                                                 int alignment, dag regList,
-                                                 int copyCost>
-  : PPCRegisterClass<regTypes, alignment, regList> {
-  let isAllocatable = 0;
-  let CopyCost = copyCost;
-}
-
 //===----------------------------------------------------------------------===//
 // Specialized Base Classes for Common PPC Patterns
 //===----------------------------------------------------------------------===//
 
 // GPR-style register class with alternative orders for different ABIs
+// Merged PPCRegisterClassWithAltOrders into this class since it was only used here
 class PPCGPRRegisterClass<list<ValueType> regTypes, int alignment, dag regList,
                           dag altOrder1, dag altOrder2>
-  : PPCRegisterClassWithAltOrders<regTypes, alignment, regList,
-      [altOrder1, altOrder2],
-      [{
-        return MF.getSubtarget<PPCSubtarget>().getGPRAllocationOrderIdx();
-      }]>;
-
-// Vector/VSX register class with size
-class PPCVectorRegisterClass<list<ValueType> regTypes, int alignment,
-                             dag regList, int size>
-  : PPCRegisterClassWithSize<regTypes, alignment, regList, size>;
-
-// Accumulator register class with high allocation priority
-class PPCAccumulatorRegisterClass<list<ValueType> regTypes, int alignment,
-                                  dag regList, int allocPriority,
-                                  bit globalPriority, int size>
-  : PPCRegisterClassWithPriority<regTypes, alignment, regList,
-                                 allocPriority, globalPriority, size>;
-
-// DMR-style register class with size
-class PPCDMRRegisterClass<list<ValueType> regTypes, int alignment,
-                          dag regList, int size>
-  : PPCRegisterClassWithSize<regTypes, alignment, regList, size>;
+  : PPCRegisterClass<regTypes, alignment, regList> {
+  let AltOrders = [altOrder1, altOrder2];
+  let AltOrderSelect = [{
+    return MF.getSubtarget<PPCSubtarget>().getGPRAllocationOrderIdx();
+  }];
+}
 
 // Condition register class with alternative orders for ELFv2 ABI
 class PPCCRRegisterClass<list<ValueType> regTypes, int alignment, dag regList,
@@ -120,10 +116,6 @@ class PPCCRRegisterClass<list<ValueType> regTypes, int alignment, dag regList,
   let Size = !if(!ne(size, 0), size, 0);
 }
 
-// Special purpose register class (non-allocatable)
-class PPCSPRegisterClass<list<ValueType> regTypes, int alignment, dag regList>
-  : PPCNonAllocatableRegisterClass<regTypes, alignment, regList>;
-
 // Paired register class with alternative orders for 64-bit ELF ABI
 class PPCPairedRegisterClass<list<ValueType> regTypes, int alignment,
                              dag regList, dag altOrder, int size>
@@ -133,4 +125,5 @@ class PPCPairedRegisterClass<list<ValueType> regTypes, int alignment,
     return MF.getSubtarget<PPCSubtarget>().is64BitELFABI();
   }];
   let Size = size;
-}
\ No newline at end of file
+}
+
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
index eab077fde5266..8969ca79a3ef5 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
@@ -168,10 +168,14 @@ let isArtificial = 1 in {
   }
 }
 
-def VFHRC : PPCNonAllocatableRegisterClassWithCopyCost<[f64], 64,
-              (sequence "VFH%u", 0, 31), -1>;
-def FHRC : PPCNonAllocatableRegisterClassWithCopyCost<[f64], 64,
-             (sequence "FH%u", 0, 31), -1>;
+def VFHRC : PPCNonAllocatableRegisterClass<[f64], 64,
+              (sequence "VFH%u", 0, 31)> {
+  let CopyCost = -1;
+}
+def FHRC : PPCNonAllocatableRegisterClass<[f64], 64,
+             (sequence "FH%u", 0, 31)> {
+  let CopyCost = -1;
+}
 
 // Floating-point pair registers
 foreach Index = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 } in {
@@ -362,6 +366,7 @@ def SPERC : PPCRegisterClass<[f64], 64,
 def F8RC : PPCRegisterClass<[f64], 64,
              (add (sequence "F%u", 0, 13),
                   (sequence "F%u", 31, 14))>;
+
 def F4RC : PPCRegisterClass<[f32], 32, (add F8RC)>;
 
 // Floating point pair registers.
@@ -376,7 +381,7 @@ def FpRC : PPCRegisterClassWithSize<[ppcf128], 128,
                   Fpair14, Fpair16, Fpair18, Fpair20, Fpair22, Fpair24,
                   Fpair26, Fpair28, Fpair30), 128>;
 
-def VRRC : PPCVectorRegisterClass<[v16i8,v8i16,v4i32,v2i64,v1i128,v4f32,v2f64, f128],
+def VRRC : PPCRegisterClassWithSize<[v16i8,v8i16,v4i32,v2i64,v1i128,v4f32,v2f64, f128],
              128,
              (add V2, V3, V4, V5, V0, V1, V6, V7, V8, V9, V10, V11,
                   V12, V13, V14, V15, V16, V17, V18, V19, V31, V30,
@@ -384,10 +389,11 @@ def VRRC : PPCVectorRegisterClass<[v16i8,v8i16,v4i32,v2i64,v1i128,v4f32,v2f64, f
 
 // VSX register classes (the allocation order mirrors that of the corresponding
 // subregister classes).
-def VSLRC : PPCVectorRegisterClass<[v4i32,v4f32,v2f64,v2i64], 128,
+def VSLRC : PPCRegisterClassWithSize<[v4i32,v4f32,v2f64,v2i64], 128,
               (add (sequence "VSL%u", 0, 13),
                    (sequence "VSL%u", 31, 14)), 128>;
-def VSRC  : PPCVectorRegisterClass<[v4i32,v4f32,v2f64,v2i64], 128,
+
+def VSRC  : PPCRegisterClassWithSize<[v4i32,v4f32,v2f64,v2i64], 128,
               (add VSLRC, VRRC), 128>;
 
 // Register classes for the 64-bit "scalar" VSX subregisters.
@@ -397,6 +403,7 @@ def VFRC :  PPCRegisterClass<[f64], 64,
                    VF15, VF16, VF17, VF18, VF19, VF31, VF30,
                    VF29, VF28, VF27, VF26, VF25, VF24, VF23,
                    VF22, VF21, VF20)>;
+
 def VSFRC : PPCRegisterClass<[f64], 64, (add F8RC, VFRC)>;
 
 // Allow spilling GPR's into caller-saved VSR's.
@@ -428,15 +435,16 @@ def CRRC : PPCCRRegisterClass<[i32], 32,
 // The CTR registers are not allocatable because they're used by the
 // decrement-and-branch instructions, and thus need to stay live across
 // multiple basic blocks.
-def CTRRC : PPCSPRegisterClass<[i32], 32, (add CTR)>;
-def CTRRC8 : PPCSPRegisterClass<[i64], 64, (add CTR8)>;
+def CTRRC : PPCNonAllocatableRegisterClass<[i32], 32, (add CTR)>;
+def CTRRC8 : PPCNonAllocatableRegisterClass<[i64], 64, (add CTR8)>;
 
-def LRRC : PPCSPRegisterClass<[i32], 32, (add LR)>;
-def LR8RC : PPCSPRegisterClass<[i64], 64, (add LR8)>;
+def LRRC : PPCNonAllocatableRegisterClass<[i32], 32, (add LR)>;
+def LR8RC : PPCNonAllocatableRegisterClass<[i64], 64, (add LR8)>;
 
 def VRSAVERC : PPCRegisterClass<[i32], 32, (add VRSAVE)>;
-def CARRYRC : PPCNonAllocatableRegisterClassWithCopyCost<[i32], 32,
-                (add CARRY, XER), -1>;
+def CARRYRC : PPCNonAllocatableRegisterClass<[i32], 32, (add CARRY, XER)> {
+  let CopyCost = -1;
+}
 
 // Make AllocationOrder as similar as G8RC's to avoid potential spilling.
 // Similarly, we have an AltOrder for 64-bit ELF ABI which r2 is allocated
@@ -464,89 +472,42 @@ include "PPCRegisterInfoDMR.td"
 // For this purpose, we define one RegisterOperand for each RegisterClass,
 // using the same name as the class, just in lower case.
 
-def PPCRegGPRCAsmOperand : AsmOperandClass {
-  let Name = "RegGPRC"; let PredicateMethod = "isRegNumber";
-}
-def gprc : RegisterOperand<GPRC> {
-  let ParserMatchClass = PPCRegGPRCAsmOperand;
-}
-def PPCRegG8RCAsmOperand : AsmOperandClass {
-  let Name = "RegG8RC"; let PredicateMethod = "isRegNumber";
-}
-def g8rc : RegisterOperand<G8RC> {
-  let ParserMatchClass = PPCRegG8RCAsmOperand;
-}
-def PPCRegG8pRCAsmOperand : AsmOperandClass {
-  let Name = "RegG8pRC"; let PredicateMethod = "isEvenRegNumber";
-}
-def g8prc : RegisterOperand<G8pRC> {
-  let ParserMatchClass = PPCRegG8pRCAsmOperand;
-}
-def PPCRegGPRCNoR0AsmOperand : AsmOperandClass {
-  let Name = "RegGPRCNoR0"; let PredicateMethod = "isRegNumber";
-}
-def gprc_nor0 : RegisterOperand<GPRC_NOR0> {
-  let ParserMatchClass = PPCRegGPRCNoR0AsmOperand;
-}
-def PPCRegG8RCNoX0AsmOperand : AsmOperandClass {
-  let Name = "RegG8RCNoX0"; let PredicateMethod = "isRegNumber";
-}
-def g8rc_nox0 : RegisterOperand<G8RC_NOX0> {
-  let ParserMatchClass = PPCRegG8RCNoX0AsmOperand;
-}
-def PPCRegF8RCAsmOperand : AsmOperandClass {
-  let Name = "RegF8RC"; let PredicateMethod = "isRegNumber";
-}
-def f8rc : RegisterOperand<F8RC> {
-  let ParserMatchClass = PPCRegF8RCAsmOperand;
-}
-def PPCRegF4RCAsmOperand : AsmOperandClass {
-  let Name = "RegF4RC"; let PredicateMethod = "isRegNumber";
-}
-def f4rc : RegisterOperand<F4RC> {
-  let ParserMatchClass = PPCRegF4RCAsmOperand;
-}
-def PPCRegFpRCAsmOperand : AsmOperandClass {
-  let Name = "RegFpRC"; let PredicateMethod = "isEvenRegNumber";
-}
-def fpairrc : RegisterOperand<FpRC> {
-  let ParserMatchClass = PPCRegFpRCAsmOperand;
-}
-def PPCRegVRRCAsmOperand : AsmOperandClass {
-  let Name = "RegVRRC"; let PredicateMethod = "isRegNumber";
-}
-def vrrc : RegisterOperand<VRRC> {
-  let ParserMatchClass = PPCRegVRRCAsmOperand;
-}
-def PPCRegVFRCAsmOperand : AsmOperandClass {
-  let Name = "RegVFRC"; let PredicateMethod = "isRegNumber";
-}
-def vfrc : RegisterOperand<VFRC> {
-  let ParserMatchClass = PPCRegVFRCAsmOperand;
-}
-def PPCRegCRBITRCAsmOperand : AsmOperandClass {
-  let Name = "RegCRBITRC"; let PredicateMethod = "isCRBitNumber";
-}
-def crbitrc : RegisterOperand<CRBITRC> {
-  let ParserMatchClass = PPCRegCRBITRCAsmOperand;
-}
-def PPCRegCRRCAsmOperand : AsmOperandClass {
-  let Name = "RegCRRC"; let PredicateMethod = "isCCRegNumber";
-}
-def crrc : RegisterOperand<CRRC> {
-  let ParserMatchClass = PPCRegCRRCAsmOperand;
-}
-def PPCRegSPERCAsmOperand : AsmOperandClass {
-  let Name = "RegSPERC"; let PredicateMethod = "isRegNumber";
-}
-def sperc : RegisterOperand<SPERC> {
-  let ParserMatchClass = PPCRegSPERCAsmOperand;
+defm GPRC : PPCRegOperand<"isRegNumber">;
+defm G8RC : PPCRegOperand<"isRegNumber">;
+defm GPRC_NOR0 : PPCRegOperand<"isRegNumber">;
+defm G8RC_NOX0 : PPCRegOperand<"isRegNumber">;
+defm SPERC : PPCRegOperand<"isRegNumber">;
+defm F8RC : PPCRegOperand<"isRegNumber">;
+defm F4RC : PPCRegOperand<"isRegNumber">;
+defm FpRC : PPCRegOperand<"isEvenRegNumber", "fpairrc">;
+defm VRRC : PPCRegOperand<"isRegNumber">;
+defm VSRC : PPCRegOperand<"isVSRegNumber">;
+defm VFRC : PPCRegOperand<"isRegNumber">;
+defm VSFRC : PPCRegOperand<"isVSRegNumber">;
+defm SPILLTOVSRRC : PPCRegOperand<"isVSRegNumber">;
+defm VSSRC : PPCRegOperand<"isVSRegNumber">;
+defm CRBITRC : PPCRegOperand<"isCRBitNumber">;
+defm CRRC : PPCRegOperand<"isCCRegNumber">;
+defm G8pRC : PPCRegOperand<"isEvenRegNumber">;
+defm VSRpRC : PPCRegOperand<"isVSRpEvenRegNumber">;
+defm DMRROWRC : PPCRegOperand<"isDMRROWRegNumber", "dmrrow">;
+defm DMRROWpRC : PPCRegOperand<"isDMRROWpRegNumber", "dmrrowp">;
+defm DMRRC : PPCRegOperand<"isDMRRegNumber", "dmr">;
+defm DMRpRC : PPCRegOperand<"isDMRpRegNumber", "dmrp">;
+
+// Special case: spe4rc uses GPRC register class and its AsmOperandClass
+def spe4rc : PPCRegOperandOnly<"GPRC">;
+
+// ACC Register Operands - multiple operands share the same AsmOperandClass
+defm ACCRC : PPCRegOperand<"isACCRegNumber", "acc">;
+def uacc : RegisterOperand<UACCRC> {
+  let ParserMatchClass = PPCRegACCRCAsmOperand;
 }
-def PPCRegSPE4RCAsmOperand : AsmOperandClass {
-  let Name = "RegSPE4RC"; let PredicateMethod = "isRegNumber";
+def wacc : RegisterOperand<WACCRC> {
+  let ParserMatchClass = PPCRegACCRCAsmOperand;
 }
-def spe4rc : RegisterOperand<GPRC> {
-  let ParserMatchClass = PPCRegSPE4RCAsmOperand;
+def wacc_hi : RegisterOperand<WACC_HIRC> {
+  let ParserMatchClass = PPCRegACCRCAsmOperand;
 }
 
 // Address operands
@@ -653,107 +614,3 @@ def pred : Operand<OtherVT> {
   let PrintMethod = "printPredicateOperand";
   let MIOperandInfo = (ops i32imm:$bibo, crrc:$reg);
 }
-
-def PPCRegVSRCAsmOperand : AsmOperandClass {
-  let Name = "RegVSRC"; let PredicateMethod = "isVSRegNumber";
-}
-def vsrc : RegisterOperand<VSRC> {
-  let ParserMatchClass = PPCRegVSRCAsmOperand;
-}
-
-def PPCRegVSFRCAsmOperand : AsmOperandClass {
-  let Name = "RegVSFRC"; let PredicateMethod = "isVSRegNumber";
-}
-def vsfrc : RegisterOperand<VSFRC> {
-  let ParserMatchClass = PPCRegVSFRCAsmOperand;
-}
-
-def PPCRegVSSRCAsmOperand : AsmOperandClass {
-  let Name = "RegVSSRC"; let PredicateMethod = "isVSRegNumber";
-}
-def vssrc : RegisterOperand<VSSRC> {
-  let ParserMatchClass = PPCRegVSSRCAsmOperand;
-}
-
-def PPCRegSPILLTOVSRRCAsmOperand : AsmOperandClass {
-  let Name = "RegSPILLTOVSRRC"; let PredicateMethod = "isVSRegNumber";
-}
-
-def spilltovsrrc : RegisterOperand<SPILLTOVSRRC> {
-  let ParserMatchClass = PPCRegSPILLTOVSRRCAsmOperand;
-}
-
-def PPCRegVSRpRCAsmOperand : AsmOperandClass {
-  let Name = "RegVSRpRC"; let PredicateMethod = "isVSRpEvenRegNumber";
-}
-
-def vsrprc : RegisterOperand<VSRpRC> {
-  let ParserMatchClass = PPCRegVSRpRCAsmOperand;
-}
-
-def PPCRegVSRpEvenRCAsmOperand : AsmOperandClass {
-  let Name = "RegVSRpEvenRC"; let PredicateMethod = "isVSRpEvenRegNumber";
-}
-
-def vsrpevenrc : RegisterOperand<VSRpRC> {
-  let ParserMatchClass = PPCRegVSRpEvenRCAsmOperand;
-  let EncoderMethod = "getVSRpEvenEncoding";
-  let DecoderMethod = "decodeVSRpEvenOperands";
-}
-
-def PPCRegACCRCAsmOperand : AsmOperandClass {
-  let Name = "RegACCRC"; let PredicateMethod = "isACCRegNumber";
-}
-
-def acc : RegisterOperand<ACCRC> {
-  let ParserMatchClass = PPCRegACCRCAsmOperand;
-}
-
-def uacc : RegisterOperand<UACCRC> {
-  let ParserMatchClass = PPCRegACCRCAsmOperand;
-}
-
-// DMR Register Operands
-def PPCRegDMRROWRCAsmOperand : AsmOperandClass {
-  let Name = "RegDMRROWRC";
-  let PredicateMethod = "isDMRROWRegNumber";
-}
-
-def dmrrow : RegisterOperand<DMRROWRC> {
-  let ParserMatchClass = PPCRegDMRROWRCAsmOperand;
-}
-
-def PPCRegDMRROWpRCAsmOperand : AsmOperandClass {
-  let Name = "RegDMRROWpRC";
-  let PredicateMethod = "isDMRROWpRegNumber";
-}
-
-def dmrrowp : RegisterOperand<DMRROWpRC> {
-  let ParserMatchClass = PPCRegDMRROWpRCAsmOperand;
-}
-
-def wacc : RegisterOperand<WACCRC> {
-  let ParserMatchClass = PPCRegACCRCAsmOperand;
-}
-
-def wacc_hi : RegisterOperand<WACC_HIRC> {
-  let ParserMatchClass = PPCRegACCRCAsmOperand;
-}
-
-def PPCRegDMRRCAsmOperand : AsmOperandClass {
-  let Name = "RegDMRRC";
-  let PredicateMethod = "isDMRRegNumber";
-}
-
-def dmr : RegisterOperand<DMRRC> {
-  let ParserMatchClass = PPCRegDMRRCAsmOperand;
-}
-
-def PPCRegDMRpRCAsmOperand : AsmOperandClass {
-  let Name = "RegDMRpRC";
-  let PredicateMethod = "isDMRpRegNumber";
-}
-
-def dmrp : RegisterOperand<DMRpRC> {
-  let ParserMatchClass = PPCRegDMRpRCAsmOperand;
-}
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfoDMR.td b/llvm/lib/Target/PowerPC/PPCRegisterInfoDMR.td
index 145cff5e1c9cb..5c85809b4f023 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfoDMR.td
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfoDMR.td
@@ -133,20 +133,20 @@ let SubRegIndices = [sub_dmr0, sub_dmr1] in {
   def DMRp3 : DMRp<3, "dmrp3", [DMR6, DMR7]>, DwarfRegNum<[-1, -1]>;
 }
 
-def DMRROWRC : PPCDMRRegisterClass<[v128i1], 128,
+def DMRROWRC : PPCRegisterClassWithSize<[v128i1], 128,
                  (add (sequence "DMRROW%u", 0, 63)), 128>;
 
-def DMRROWpRC : PPCDMRRegisterClass<[v256i1], 128,
+def DMRROWpRC : PPCRegisterClassWithSize<[v256i1], 128,
                   (add (sequence "DMRROWp%u", 0, 31)), 256>;
 
-def WACCRC : PPCDMRRegisterClass<[v512i1], 128,
+def WACCRC : PPCRegisterClassWithSize<[v512i1], 128,
                (add (sequence "WACC%u", 0, 7)), 512>;
 
-def WACC_HIRC : PPCDMRRegisterClass<[v512i1], 128,
+def WACC_HIRC : PPCRegisterClassWithSize<[v512i1], 128,
                   (add (sequence "WACC_HI%u", 0, 7)), 512>;
 
-def DMRRC : PPCDMRRegisterClass<[v1024i1], 128,
+def DMRRC : PPCRegisterClassWithSize<[v1024i1], 128,
               (add (sequence "DMR%u", 0, 7)), 1024>;
 
-def DMRpRC : PPCDMRRegisterClass<[v2048i1], 128,
+def DMRpRC : PPCRegisterClassWithSize<[v2048i1], 128,
                (add DMRp0, DMRp1, DMRp2, DMRp3), 2048>;
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfoMMA.td b/llvm/lib/Target/PowerPC/PPCRegisterInfoMMA.td
index 2029a61c9409c..6dffb0b040cc1 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfoMMA.td
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfoMMA.td
@@ -51,7 +51,7 @@ let SubRegIndices = [sub_pair0, sub_pair1] in {
 // must represent 4 advacent vector registers. For example ACC1 must be
 // VS4 - VS7.
 // We want to allocate these registers even before we allocate global ranges.
-def ACCRC : PPCAccumulatorRegisterClass<[v512i1], 128,
+def ACCRC : PPCRegisterClassWithPriority<[v512i1], 128,
               (add ACC0, ACC1, ACC2, ACC3, ACC4, ACC5, ACC6, ACC7),
               31, 1, 512>;
 
@@ -69,7 +69,7 @@ let SubRegIndices = [sub_pair0, sub_pair1] in {
 // least 32 as we want to allocate these registers before we allocate other
 // global ranges. The value must be less than the AllocationPriority of the
 // ACC registers.
-def UACCRC : PPCAccumulatorRegisterClass<[v512i1], 128,
+def UACCRC : PPCRegisterClassWithPriority<[v512i1], 128,
                (add UACC0, UACC1, UACC2, UACC3,
                     UACC4, UACC5, UACC6, UACC7),
                4, 1, 512>;

>From df69c8444a42dca739e1b617f600862b66f2f530 Mon Sep 17 00:00:00 2001
From: Lei Huang <lei at ca.ibm.com>
Date: Fri, 6 Mar 2026 19:26:26 -0500
Subject: [PATCH 3/3] move acc & dmr operand def into the corresponding td
 file.

---
 llvm/lib/Target/PowerPC/PPCRegisterClasses.td | 104 +++++++-----------
 llvm/lib/Target/PowerPC/PPCRegisterInfo.td    |  57 +++++-----
 llvm/lib/Target/PowerPC/PPCRegisterInfoDMR.td |  15 +++
 llvm/lib/Target/PowerPC/PPCRegisterInfoMMA.td |  16 +++
 4 files changed, 96 insertions(+), 96 deletions(-)

diff --git a/llvm/lib/Target/PowerPC/PPCRegisterClasses.td b/llvm/lib/Target/PowerPC/PPCRegisterClasses.td
index 9da7916de1777..53697ac89dd1b 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterClasses.td
+++ b/llvm/lib/Target/PowerPC/PPCRegisterClasses.td
@@ -19,48 +19,6 @@
 class PPCRegisterClass<list<ValueType> regTypes, int alignment, dag regList>
   : RegisterClass<"PPC", regTypes, alignment, regList>;
 
-//===----------------------------------------------------------------------===//
-// Classes for Generating RegisterOperand for Existing RegisterClass
-//===----------------------------------------------------------------------===//
-
-// Base class that creates a RegisterOperand for an already-defined RegisterClass,
-// assuming the AsmOperandClass already exists with the standard naming convention
-// (PPCReg<regClassName>AsmOperand).
-//
-// Usage: def spe4rc : PPCRegOperandOnly<"GPRC">;
-//   Creates: spe4rc RegisterOperand wrapping GPRC, using PPCRegGPRCAsmOperand
-class PPCRegOperandOnly<string regClassName>
-  : RegisterOperand<!cast<RegisterClass>(regClassName)> {
-  let ParserMatchClass = !cast<AsmOperandClass>(!strconcat("PPCReg", regClassName, "AsmOperand"));
-}
-
-// Multiclass that generates both the AsmOperandClass and RegisterOperand for an
-// already-defined RegisterClass. This eliminates the repetitive pattern of
-// manually defining these for each register class.
-//
-// Usage examples:
-//   defm GPRC : PPCRegOperand<"isRegNumber">;
-//     Creates: PPCRegGPRCAsmOperand and gprc (lowercase of GPRC)
-//   defm FpRC : PPCRegOperand<"isEvenRegNumber", "fpairrc">;
-//     Creates: PPCRegFpRCAsmOperand and fpairrc (custom name)
-//
-// The NAME in the defm statement should match the RegisterClass name.
-
-multiclass PPCRegOperand<string predicate, string operandName = ""> {
-  // Define the AsmOperandClass
-  def "PPCReg"#NAME#"AsmOperand" : AsmOperandClass {
-    let Name = "Reg"#NAME;
-    let PredicateMethod = predicate;
-  }
-  
-  // Define the RegisterOperand
-  // Use custom name if provided, otherwise use lowercase of NAME
-  def !if(!eq(operandName, ""), !tolower(NAME), operandName)
-    : RegisterOperand<!cast<RegisterClass>(NAME)> {
-    let ParserMatchClass = !cast<AsmOperandClass>("PPCReg"#NAME#"AsmOperand");
-  }
-}
-
 //===----------------------------------------------------------------------===//
 // Variant Register Class Definitions
 //===----------------------------------------------------------------------===//
@@ -89,10 +47,6 @@ class PPCRegisterClassWithPriority<list<ValueType> regTypes, int alignment,
   let Size = size;
 }
 
-//===----------------------------------------------------------------------===//
-// Specialized Base Classes for Common PPC Patterns
-//===----------------------------------------------------------------------===//
-
 // GPR-style register class with alternative orders for different ABIs
 // Merged PPCRegisterClassWithAltOrders into this class since it was only used here
 class PPCGPRRegisterClass<list<ValueType> regTypes, int alignment, dag regList,
@@ -104,26 +58,44 @@ class PPCGPRRegisterClass<list<ValueType> regTypes, int alignment, dag regList,
   }];
 }
 
-// Condition register class with alternative orders for ELFv2 ABI
-class PPCCRRegisterClass<list<ValueType> regTypes, int alignment, dag regList,
-                         dag altOrder, int size = 0>
-  : PPCRegisterClass<regTypes, alignment, regList> {
-  let AltOrders = [altOrder];
-  let AltOrderSelect = [{
-    return MF.getSubtarget<PPCSubtarget>().isELFv2ABI() &&
-           MF.getInfo<PPCFunctionInfo>()->isNonVolatileCRDisabled();
-  }];
-  let Size = !if(!ne(size, 0), size, 0);
-}
+//===----------------------------------------------------------------------===//
+// Classes for Generating RegisterOperand for Existing RegisterClass
+//===----------------------------------------------------------------------===//
 
-// Paired register class with alternative orders for 64-bit ELF ABI
-class PPCPairedRegisterClass<list<ValueType> regTypes, int alignment,
-                             dag regList, dag altOrder, int size>
-  : PPCRegisterClass<regTypes, alignment, regList> {
-  let AltOrders = [altOrder];
-  let AltOrderSelect = [{
-    return MF.getSubtarget<PPCSubtarget>().is64BitELFABI();
-  }];
-  let Size = size;
+// Base class that creates a RegisterOperand for an already-defined RegisterClass,
+// assuming the AsmOperandClass already exists with the standard naming convention
+// (PPCReg<regClassName>AsmOperand).
+//
+// Usage: def spe4rc : PPCRegOperandOnly<"GPRC">;
+//   Creates: spe4rc RegisterOperand wrapping GPRC, using PPCRegGPRCAsmOperand
+class PPCRegOperandOnly<string regClassName>
+  : RegisterOperand<!cast<RegisterClass>(regClassName)> {
+  let ParserMatchClass = !cast<AsmOperandClass>(!strconcat("PPCReg", regClassName, "AsmOperand"));
 }
 
+// Multiclass that generates both the AsmOperandClass and RegisterOperand for an
+// already-defined RegisterClass. This eliminates the repetitive pattern of
+// manually defining these for each register class.
+//
+// Usage examples:
+//   defm GPRC : PPCRegOperand<"isRegNumber">;
+//     Creates: PPCRegGPRCAsmOperand and gprc (lowercase of GPRC)
+//   defm FpRC : PPCRegOperand<"isEvenRegNumber", "fpairrc">;
+//     Creates: PPCRegFpRCAsmOperand and fpairrc (custom name)
+//
+// The NAME in the defm statement  match the RegisterClass name.
+
+multiclass PPCRegOperand<string predicate, string operandName = ""> {
+  // Define the AsmOperandClass
+  def "PPCReg"#NAME#"AsmOperand" : AsmOperandClass {
+    let Name = "Reg"#NAME;
+    let PredicateMethod = predicate;
+  }
+  
+  // Define the RegisterOperand
+  // Use custom name if provided, otherwise use lowercase of NAME
+  def !if(!eq(operandName, ""), !tolower(NAME), operandName)
+    : RegisterOperand<!cast<RegisterClass>(NAME)> {
+    let ParserMatchClass = !cast<AsmOperandClass>("PPCReg"#NAME#"AsmOperand");
+  }
+}
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
index 8969ca79a3ef5..78352f9f75014 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
@@ -415,7 +415,7 @@ def SPILLTOVSRRC : PPCRegisterClass<[i64, f64], 64,
 // Register class for single precision scalars in VSX registers
 def VSSRC : PPCRegisterClass<[f32], 32, (add VSFRC)>;
 
-def CRBITRC : PPCCRRegisterClass<[i1], 32,
+def CRBITRC : PPCRegisterClassWithSize<[i1], 32,
   (add CR2LT, CR2GT, CR2EQ, CR2UN,
        CR3LT, CR3GT, CR3EQ, CR3UN,
        CR4LT, CR4GT, CR4EQ, CR4UN,
@@ -423,14 +423,24 @@ def CRBITRC : PPCCRRegisterClass<[i1], 32,
        CR6LT, CR6GT, CR6EQ, CR6UN,
        CR7LT, CR7GT, CR7EQ, CR7UN,
        CR1LT, CR1GT, CR1EQ, CR1UN,
-       CR0LT, CR0GT, CR0EQ, CR0UN),
-  (sub CRBITRC, CR2LT, CR2GT, CR2EQ, CR2UN, CR3LT, CR3GT,
-       CR3EQ, CR3UN, CR4LT, CR4GT, CR4EQ, CR4UN), 32>;
+       CR0LT, CR0GT, CR0EQ, CR0UN), 32> {
+  let AltOrders = [(sub CRBITRC, CR2LT, CR2GT, CR2EQ, CR2UN, CR3LT, CR3GT,
+                        CR3EQ, CR3UN, CR4LT, CR4GT, CR4EQ, CR4UN)];
+  let AltOrderSelect = [{
+    return MF.getSubtarget<PPCSubtarget>().isELFv2ABI() &&
+           MF.getInfo<PPCFunctionInfo>()->isNonVolatileCRDisabled();
+  }];
+}
 
-def CRRC : PPCCRRegisterClass<[i32], 32,
+def CRRC : PPCRegisterClass<[i32], 32,
   (add CR0, CR1, CR5, CR6,
-       CR7, CR2, CR3, CR4),
-  (sub CRRC, CR2, CR3, CR4)>;
+       CR7, CR2, CR3, CR4)> {
+  let AltOrders = [(sub CRRC, CR2, CR3, CR4)];
+  let AltOrderSelect = [{
+    return MF.getSubtarget<PPCSubtarget>().isELFv2ABI() &&
+           MF.getInfo<PPCFunctionInfo>()->isNonVolatileCRDisabled();
+  }];
+}
 
 // The CTR registers are not allocatable because they're used by the
 // decrement-and-branch instructions, and thus need to stay live across
@@ -449,14 +459,15 @@ def CARRYRC : PPCNonAllocatableRegisterClass<[i32], 32, (add CARRY, XER)> {
 // Make AllocationOrder as similar as G8RC's to avoid potential spilling.
 // Similarly, we have an AltOrder for 64-bit ELF ABI which r2 is allocated
 // at last.
-def G8pRC : PPCPairedRegisterClass<[untyped], 128,
+def G8pRC : PPCRegisterClassWithSize<[untyped], 128,
               (add (sequence "G8p%u", 1, 5),
                    (sequence "G8p%u", 14, 7),
-                   G8p15, G8p6, G8p0),
-              (add (sub G8pRC, G8p1), G8p1), 128>;
-
-include "PPCRegisterInfoMMA.td"
-include "PPCRegisterInfoDMR.td"
+                   G8p15, G8p6, G8p0), 128> {
+  let AltOrders = [(add (sub G8pRC, G8p1), G8p1)];
+  let AltOrderSelect = [{
+    return MF.getSubtarget<PPCSubtarget>().is64BitELFABI();
+  }];
+}
 
 //===----------------------------------------------------------------------===//
 // PowerPC Register Operand Definitions.
@@ -489,27 +500,10 @@ defm VSSRC : PPCRegOperand<"isVSRegNumber">;
 defm CRBITRC : PPCRegOperand<"isCRBitNumber">;
 defm CRRC : PPCRegOperand<"isCCRegNumber">;
 defm G8pRC : PPCRegOperand<"isEvenRegNumber">;
-defm VSRpRC : PPCRegOperand<"isVSRpEvenRegNumber">;
-defm DMRROWRC : PPCRegOperand<"isDMRROWRegNumber", "dmrrow">;
-defm DMRROWpRC : PPCRegOperand<"isDMRROWpRegNumber", "dmrrowp">;
-defm DMRRC : PPCRegOperand<"isDMRRegNumber", "dmr">;
-defm DMRpRC : PPCRegOperand<"isDMRpRegNumber", "dmrp">;
 
 // Special case: spe4rc uses GPRC register class and its AsmOperandClass
 def spe4rc : PPCRegOperandOnly<"GPRC">;
 
-// ACC Register Operands - multiple operands share the same AsmOperandClass
-defm ACCRC : PPCRegOperand<"isACCRegNumber", "acc">;
-def uacc : RegisterOperand<UACCRC> {
-  let ParserMatchClass = PPCRegACCRCAsmOperand;
-}
-def wacc : RegisterOperand<WACCRC> {
-  let ParserMatchClass = PPCRegACCRCAsmOperand;
-}
-def wacc_hi : RegisterOperand<WACC_HIRC> {
-  let ParserMatchClass = PPCRegACCRCAsmOperand;
-}
-
 // Address operands
 // A version of ptr_rc which excludes R0 (or X0 in 64-bit mode).
 def PPCRegGxRCNoR0Operand : AsmOperandClass {
@@ -540,6 +534,9 @@ def ptr_rc_idx : RegisterOperand<ptr_rc_idx_by_hwmode> {
   let ParserMatchClass = PPCRegGxRCOperand;
 }
 
+include "PPCRegisterInfoMMA.td"
+include "PPCRegisterInfoDMR.td"
+
 //===----------------------------------------------------------------------===//
 // Memory operands (depend on register operands defined above)
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfoDMR.td b/llvm/lib/Target/PowerPC/PPCRegisterInfoDMR.td
index 5c85809b4f023..1b8ecbf043142 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfoDMR.td
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfoDMR.td
@@ -150,3 +150,18 @@ def DMRRC : PPCRegisterClassWithSize<[v1024i1], 128,
 
 def DMRpRC : PPCRegisterClassWithSize<[v2048i1], 128,
                (add DMRp0, DMRp1, DMRp2, DMRp3), 2048>;
+
+// Register Operand Definitions.
+
+defm DMRROWRC : PPCRegOperand<"isDMRROWRegNumber", "dmrrow">;
+defm DMRROWpRC : PPCRegOperand<"isDMRROWpRegNumber", "dmrrowp">;
+defm DMRRC : PPCRegOperand<"isDMRRegNumber", "dmr">;
+defm DMRpRC : PPCRegOperand<"isDMRpRegNumber", "dmrp">;               
+
+// ACC Register Operands share the same AsmOperandClass.
+def wacc : RegisterOperand<WACCRC> {
+  let ParserMatchClass = PPCRegACCRCAsmOperand;
+}
+def wacc_hi : RegisterOperand<WACC_HIRC> {
+  let ParserMatchClass = PPCRegACCRCAsmOperand;
+}
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfoMMA.td b/llvm/lib/Target/PowerPC/PPCRegisterInfoMMA.td
index 6dffb0b040cc1..e4d773e92051b 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfoMMA.td
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfoMMA.td
@@ -95,5 +95,21 @@ def VSRpRC : PPCRegisterClassWithPriority<[v256i1], 128,
                2, 0, 256>;
 
 
+// Register Operand Definitions.
 
+// ACC Register Operands share the same AsmOperandClass.
+defm ACCRC : PPCRegOperand<"isACCRegNumber", "acc">;
+def uacc : RegisterOperand<UACCRC> {
+  let ParserMatchClass = PPCRegACCRCAsmOperand;
+}
 
+defm VSRpRC : PPCRegOperand<"isVSRpEvenRegNumber">;
+// VSRpRC with encoder/decoder methods (uses VSRpRC class but different operand name)
+def PPCRegVSRpEvenRCAsmOperand : AsmOperandClass {
+  let Name = "RegVSRpEvenRC"; let PredicateMethod = "isVSRpEvenRegNumber";
+}
+def vsrpevenrc : RegisterOperand<VSRpRC> {
+  let ParserMatchClass = PPCRegVSRpEvenRCAsmOperand;
+  let EncoderMethod = "getVSRpEvenEncoding";
+  let DecoderMethod = "decodeVSRpEvenOperands";
+}



More information about the llvm-commits mailing list