[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