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 new file mode 100644 index 0000000000000..dac74eb352d8c --- /dev/null +++ b/llvm/lib/Target/PowerPC/PPCRegisterClasses.td @@ -0,0 +1,101 @@ +//===-- PPCRegisterClasses.td - 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 regTypes, int alignment, dag regList> + : RegisterClass<"PPC", regTypes, alignment, regList>; + +//===----------------------------------------------------------------------===// +// Variant Register Class Definitions +//===----------------------------------------------------------------------===// + +// Register class that is not allocatable +class PPCNonAllocatableRegisterClass regTypes, int alignment, + dag regList> + : PPCRegisterClass { + let isAllocatable = 0; +} + +// Register class with explicit size +class PPCRegisterClassWithSize regTypes, int alignment, + dag regList, int size> + : PPCRegisterClass { + let Size = size; +} + +// Register class with allocation priority and size +class PPCRegisterClassWithPriority regTypes, int alignment, + dag regList, int allocPriority, + bit globalPriority, int size> + : PPCRegisterClass { + let AllocationPriority = allocPriority; + let GlobalPriority = globalPriority; + let Size = size; +} + +// GPR-style register class with alternative orders for different ABIs +// Merged PPCRegisterClassWithAltOrders into this class since it was only used +// here. +class PPCGPRRegisterClass regTypes, int alignment, dag regList, + dag altOrder1, dag altOrder2> + : PPCRegisterClass { + let AltOrders = [altOrder1, altOrder2]; + let AltOrderSelect = [{ + return MF.getSubtarget().getGPRAllocationOrderIdx(); + }]; +} + +//===----------------------------------------------------------------------===// +// Classes for Generating RegisterOperand for Existing RegisterClass +//===----------------------------------------------------------------------===// + +// Creates a RegisterOperand for an already-defined RegisterClass, assuming the +// AsmOperandClass already exists with the standard naming convention: +// (PPCRegAsmOperand). +// Usage: def spe4rc : PPCRegOperandOnly<"GPRC">; +// Creates: spe4rc RegisterOperand wrapping GPRC, using PPCRegGPRCAsmOperand. +class PPCRegOperandOnly + : RegisterOperand(regClassName)> { + let ParserMatchClass = + !cast(!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 { + // Define the AsmOperandClass. + def "PPCReg"#NAME#"AsmOperand" : AsmOperandClass { + let Name = "Reg"#NAME; + let PredicateMethod = predicate; + } + + // Define the RegisterOperand with custom name if provided, + // otherwise use lowercase of NAME. + def !if(!eq(operandName, ""), !tolower(NAME), operandName) + : RegisterOperand(NAME)> { + let ParserMatchClass = !cast("PPCReg"#NAME#"AsmOperand"); + } +} diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td index 28cfbc9991c3c..90c7be4297935 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,9 +168,9 @@ 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)>; +let CopyCost = -1 in { + def VFHRC : PPCNonAllocatableRegisterClass<[f64], 64, (sequence "VFH%u", 0, 31)>; + def FHRC : PPCNonAllocatableRegisterClass<[f64], 64, (sequence "FH%u", 0, 31)>; } // Floating-point pair registers @@ -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().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().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().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().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,9 @@ 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 +370,45 @@ 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 : 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, + 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 : PPCRegisterClassWithSize<[v4i32,v4f32,v2f64,v2i64], 128, + (add (sequence "VSL%u", 0, 13), + (sequence "VSL%u", 31, 14)), 128>; + +def VSRC : PPCRegisterClassWithSize<[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 : PPCRegisterClassWithSize<[i1], 32, (add CR2LT, CR2GT, CR2EQ, CR2UN, CR3LT, CR3GT, CR3EQ, CR3UN, CR4LT, CR4GT, CR4EQ, CR4UN, @@ -428,8 +416,7 @@ 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; + CR0LT, CR0GT, CR0EQ, CR0UN), 32> { let AltOrders = [(sub CRBITRC, CR2LT, CR2GT, CR2EQ, CR2UN, CR3LT, CR3GT, CR3EQ, CR3UN, CR4LT, CR4GT, CR4EQ, CR4UN)]; let AltOrderSelect = [{ @@ -438,7 +425,7 @@ def CRBITRC : RegisterClass<"PPC", [i1], 32, }]; } -def CRRC : RegisterClass<"PPC", [i32], 32, +def CRRC : PPCRegisterClass<[i32], 32, (add CR0, CR1, CR5, CR6, CR7, CR2, CR3, CR4)> { let AltOrders = [(sub CRRC, CR2, CR3, CR4)]; @@ -447,47 +434,34 @@ def CRRC : RegisterClass<"PPC", [i32], 32, MF.getInfo()->isNonVolatileCRDisabled(); }]; } + // 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 : PPCNonAllocatableRegisterClass<[i32], 32, (add CTR)>; +def CTRRC8 : PPCNonAllocatableRegisterClass<[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 : PPCNonAllocatableRegisterClass<[i32], 32, (add LR)>; +def LR8RC : PPCNonAllocatableRegisterClass<[i64], 64, (add LR8)>; -def VRSAVERC : RegisterClass<"PPC", [i32], 32, (add VRSAVE)>; -def CARRYRC : RegisterClass<"PPC", [i32], 32, (add CARRY, XER)> { +def VRSAVERC : PPCRegisterClass<[i32], 32, (add VRSAVE)>; +def CARRYRC : PPCNonAllocatableRegisterClass<[i32], 32, (add CARRY, XER)> { let CopyCost = -1; - let isAllocatable = 0; } // 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)> { +def G8pRC : PPCRegisterClassWithSize<[untyped], 128, + (add (sequence "G8p%u", 1, 5), + (sequence "G8p%u", 14, 7), + G8p15, G8p6, G8p0), 128> { let AltOrders = [(add (sub G8pRC, G8p1), G8p1)]; let AltOrderSelect = [{ return MF.getSubtarget().is64BitELFABI(); }]; - let Size = 128; } -include "PPCRegisterInfoMMA.td" -include "PPCRegisterInfoDMR.td" - //===----------------------------------------------------------------------===// // PowerPC Register Operand Definitions. @@ -502,90 +476,26 @@ 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 { - let ParserMatchClass = PPCRegGPRCAsmOperand; -} -def PPCRegG8RCAsmOperand : AsmOperandClass { - let Name = "RegG8RC"; let PredicateMethod = "isRegNumber"; -} -def g8rc : RegisterOperand { - let ParserMatchClass = PPCRegG8RCAsmOperand; -} -def PPCRegG8pRCAsmOperand : AsmOperandClass { - let Name = "RegG8pRC"; let PredicateMethod = "isEvenRegNumber"; -} -def g8prc : RegisterOperand { - let ParserMatchClass = PPCRegG8pRCAsmOperand; -} -def PPCRegGPRCNoR0AsmOperand : AsmOperandClass { - let Name = "RegGPRCNoR0"; let PredicateMethod = "isRegNumber"; -} -def gprc_nor0 : RegisterOperand { - let ParserMatchClass = PPCRegGPRCNoR0AsmOperand; -} -def PPCRegG8RCNoX0AsmOperand : AsmOperandClass { - let Name = "RegG8RCNoX0"; let PredicateMethod = "isRegNumber"; -} -def g8rc_nox0 : RegisterOperand { - let ParserMatchClass = PPCRegG8RCNoX0AsmOperand; -} -def PPCRegF8RCAsmOperand : AsmOperandClass { - let Name = "RegF8RC"; let PredicateMethod = "isRegNumber"; -} -def f8rc : RegisterOperand { - let ParserMatchClass = PPCRegF8RCAsmOperand; -} -def PPCRegF4RCAsmOperand : AsmOperandClass { - let Name = "RegF4RC"; let PredicateMethod = "isRegNumber"; -} -def f4rc : RegisterOperand { - let ParserMatchClass = PPCRegF4RCAsmOperand; -} -def PPCRegFpRCAsmOperand : AsmOperandClass { - let Name = "RegFpRC"; let PredicateMethod = "isEvenRegNumber"; -} -def fpairrc : RegisterOperand { - let ParserMatchClass = PPCRegFpRCAsmOperand; -} -def PPCRegVRRCAsmOperand : AsmOperandClass { - let Name = "RegVRRC"; let PredicateMethod = "isRegNumber"; -} -def vrrc : RegisterOperand { - let ParserMatchClass = PPCRegVRRCAsmOperand; -} -def PPCRegVFRCAsmOperand : AsmOperandClass { - let Name = "RegVFRC"; let PredicateMethod = "isRegNumber"; -} -def vfrc : RegisterOperand { - let ParserMatchClass = PPCRegVFRCAsmOperand; -} -def PPCRegCRBITRCAsmOperand : AsmOperandClass { - let Name = "RegCRBITRC"; let PredicateMethod = "isCRBitNumber"; -} -def crbitrc : RegisterOperand { - let ParserMatchClass = PPCRegCRBITRCAsmOperand; -} -def PPCRegCRRCAsmOperand : AsmOperandClass { - let Name = "RegCRRC"; let PredicateMethod = "isCCRegNumber"; -} -def crrc : RegisterOperand { - let ParserMatchClass = PPCRegCRRCAsmOperand; -} -def PPCRegSPERCAsmOperand : AsmOperandClass { - let Name = "RegSPERC"; let PredicateMethod = "isRegNumber"; -} -def sperc : RegisterOperand { - let ParserMatchClass = PPCRegSPERCAsmOperand; -} -def PPCRegSPE4RCAsmOperand : AsmOperandClass { - let Name = "RegSPE4RC"; let PredicateMethod = "isRegNumber"; -} -def spe4rc : RegisterOperand { - let ParserMatchClass = PPCRegSPE4RCAsmOperand; -} +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">; + +// Special case: spe4rc uses GPRC register class and its AsmOperandClass +def spe4rc : PPCRegOperandOnly<"GPRC">; // Address operands // A version of ptr_rc which excludes R0 (or X0 in 64-bit mode). @@ -617,6 +527,9 @@ def ptr_rc_idx : RegisterOperand { let ParserMatchClass = PPCRegGxRCOperand; } +include "PPCRegisterInfoMMA.td" +include "PPCRegisterInfoDMR.td" + //===----------------------------------------------------------------------===// // Memory operands (depend on register operands defined above) //===----------------------------------------------------------------------===// @@ -691,107 +604,3 @@ def pred : Operand { let PrintMethod = "printPredicateOperand"; let MIOperandInfo = (ops i32imm:$bibo, crrc:$reg); } - -def PPCRegVSRCAsmOperand : AsmOperandClass { - let Name = "RegVSRC"; let PredicateMethod = "isVSRegNumber"; -} -def vsrc : RegisterOperand { - let ParserMatchClass = PPCRegVSRCAsmOperand; -} - -def PPCRegVSFRCAsmOperand : AsmOperandClass { - let Name = "RegVSFRC"; let PredicateMethod = "isVSRegNumber"; -} -def vsfrc : RegisterOperand { - let ParserMatchClass = PPCRegVSFRCAsmOperand; -} - -def PPCRegVSSRCAsmOperand : AsmOperandClass { - let Name = "RegVSSRC"; let PredicateMethod = "isVSRegNumber"; -} -def vssrc : RegisterOperand { - let ParserMatchClass = PPCRegVSSRCAsmOperand; -} - -def PPCRegSPILLTOVSRRCAsmOperand : AsmOperandClass { - let Name = "RegSPILLTOVSRRC"; let PredicateMethod = "isVSRegNumber"; -} - -def spilltovsrrc : RegisterOperand { - let ParserMatchClass = PPCRegSPILLTOVSRRCAsmOperand; -} - -def PPCRegVSRpRCAsmOperand : AsmOperandClass { - let Name = "RegVSRpRC"; let PredicateMethod = "isVSRpEvenRegNumber"; -} - -def vsrprc : RegisterOperand { - let ParserMatchClass = PPCRegVSRpRCAsmOperand; -} - -def PPCRegVSRpEvenRCAsmOperand : AsmOperandClass { - let Name = "RegVSRpEvenRC"; let PredicateMethod = "isVSRpEvenRegNumber"; -} - -def vsrpevenrc : RegisterOperand { - let ParserMatchClass = PPCRegVSRpEvenRCAsmOperand; - let EncoderMethod = "getVSRpEvenEncoding"; - let DecoderMethod = "decodeVSRpEvenOperands"; -} - -def PPCRegACCRCAsmOperand : AsmOperandClass { - let Name = "RegACCRC"; let PredicateMethod = "isACCRegNumber"; -} - -def acc : RegisterOperand { - let ParserMatchClass = PPCRegACCRCAsmOperand; -} - -def uacc : RegisterOperand { - let ParserMatchClass = PPCRegACCRCAsmOperand; -} - -// DMR Register Operands -def PPCRegDMRROWRCAsmOperand : AsmOperandClass { - let Name = "RegDMRROWRC"; - let PredicateMethod = "isDMRROWRegNumber"; -} - -def dmrrow : RegisterOperand { - let ParserMatchClass = PPCRegDMRROWRCAsmOperand; -} - -def PPCRegDMRROWpRCAsmOperand : AsmOperandClass { - let Name = "RegDMRROWpRC"; - let PredicateMethod = "isDMRROWpRegNumber"; -} - -def dmrrowp : RegisterOperand { - let ParserMatchClass = PPCRegDMRROWpRCAsmOperand; -} - -def wacc : RegisterOperand { - let ParserMatchClass = PPCRegACCRCAsmOperand; -} - -def wacc_hi : RegisterOperand { - let ParserMatchClass = PPCRegACCRCAsmOperand; -} - -def PPCRegDMRRCAsmOperand : AsmOperandClass { - let Name = "RegDMRRC"; - let PredicateMethod = "isDMRRegNumber"; -} - -def dmr : RegisterOperand { - let ParserMatchClass = PPCRegDMRRCAsmOperand; -} - -def PPCRegDMRpRCAsmOperand : AsmOperandClass { - let Name = "RegDMRpRC"; - let PredicateMethod = "isDMRpRegNumber"; -} - -def dmrp : RegisterOperand { - let ParserMatchClass = PPCRegDMRpRCAsmOperand; -} diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfoDMR.td b/llvm/lib/Target/PowerPC/PPCRegisterInfoDMR.td index 1c3e7621825bd..1b8ecbf043142 100644 --- a/llvm/lib/Target/PowerPC/PPCRegisterInfoDMR.td +++ b/llvm/lib/Target/PowerPC/PPCRegisterInfoDMR.td @@ -133,32 +133,35 @@ 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 : PPCRegisterClassWithSize<[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 : PPCRegisterClassWithSize<[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 : PPCRegisterClassWithSize<[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 : PPCRegisterClassWithSize<[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 : PPCRegisterClassWithSize<[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 : 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 { + let ParserMatchClass = PPCRegACCRCAsmOperand; +} +def wacc_hi : RegisterOperand { + let ParserMatchClass = PPCRegACCRCAsmOperand; } diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfoMMA.td b/llvm/lib/Target/PowerPC/PPCRegisterInfoMMA.td index 57f4545516a00..e4d773e92051b 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 : PPCRegisterClassWithPriority<[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 : PPCRegisterClassWithPriority<[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,22 +81,35 @@ 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>; +// Register Operand Definitions. +// ACC Register Operands share the same AsmOperandClass. +defm ACCRC : PPCRegOperand<"isACCRegNumber", "acc">; +def uacc : RegisterOperand { + 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 { + let ParserMatchClass = PPCRegVSRpEvenRCAsmOperand; + let EncoderMethod = "getVSRpEvenEncoding"; + let DecoderMethod = "decodeVSRpEvenOperands"; +}