From fcb25e60f514e4dbceecef73ac229c61d6202ed2 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 2 Apr 2013 04:08:54 +0000 Subject: [PATCH] Add an I64Regs register class for 64-bit registers. We are going to use the same registers for 32-bit and 64-bit values, but in two different register classes. The I64Regs register class has a larger spill size and alignment. The addition of an i64 register class confuses TableGen's type inference, so it is necessary to clarify the type of some immediates and the G0 register. In 64-bit mode, pointers are i64 and should use the I64Regs register class. Implement getPointerRegClass() to dynamically provide the pointer register class depending on the subtarget. Use ptr_rc and iPTR for memory operands. Finally, add the i64 type to the IntRegs register class. This register class is not used to hold i64 values, I64Regs is for that. The type is required to appease TableGen's type checking in output patterns like this: def : Pat<(add i64:$a, i64:$b), (ADDrr $a, $b)>; SPARC v9 uses the same ADDrr instruction for i32 and i64 additions, and TableGen doesn't know to check the type of register sub-classes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178522 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Sparc/SparcISelLowering.cpp | 3 +++ lib/Target/Sparc/SparcISelLowering.h | 3 +++ lib/Target/Sparc/SparcInstrInfo.td | 20 ++++++++++---------- lib/Target/Sparc/SparcRegisterInfo.cpp | 6 ++++++ lib/Target/Sparc/SparcRegisterInfo.h | 3 +++ lib/Target/Sparc/SparcRegisterInfo.td | 12 +++++++++++- 6 files changed, 36 insertions(+), 11 deletions(-) diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp index 28ac02a613e..b345d5f13f3 100644 --- a/lib/Target/Sparc/SparcISelLowering.cpp +++ b/lib/Target/Sparc/SparcISelLowering.cpp @@ -689,11 +689,14 @@ static SPCC::CondCodes FPCondCCodeToFCC(ISD::CondCode CC) { SparcTargetLowering::SparcTargetLowering(TargetMachine &TM) : TargetLowering(TM, new TargetLoweringObjectFileELF()) { + Subtarget = &TM.getSubtarget(); // Set up the register classes. addRegisterClass(MVT::i32, &SP::IntRegsRegClass); addRegisterClass(MVT::f32, &SP::FPRegsRegClass); addRegisterClass(MVT::f64, &SP::DFPRegsRegClass); + if (Subtarget->is64Bit()) + addRegisterClass(MVT::i64, &SP::I64RegsRegClass); // Turn FP extload into load/fextend setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); diff --git a/lib/Target/Sparc/SparcISelLowering.h b/lib/Target/Sparc/SparcISelLowering.h index 09148ea5402..b9937c84606 100644 --- a/lib/Target/Sparc/SparcISelLowering.h +++ b/lib/Target/Sparc/SparcISelLowering.h @@ -19,6 +19,8 @@ #include "llvm/Target/TargetLowering.h" namespace llvm { + class SparcSubtarget; + namespace SPISD { enum { FIRST_NUMBER = ISD::BUILTIN_OP_END, @@ -42,6 +44,7 @@ namespace llvm { } class SparcTargetLowering : public TargetLowering { + const SparcSubtarget *Subtarget; public: SparcTargetLowering(TargetMachine &TM); virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const; diff --git a/lib/Target/Sparc/SparcInstrInfo.td b/lib/Target/Sparc/SparcInstrInfo.td index c3810b2a4d6..3a5200d48d3 100644 --- a/lib/Target/Sparc/SparcInstrInfo.td +++ b/lib/Target/Sparc/SparcInstrInfo.td @@ -63,17 +63,17 @@ def SETHIimm : PatLeaf<(imm), [{ }], HI22>; // Addressing modes. -def ADDRrr : ComplexPattern; -def ADDRri : ComplexPattern; +def ADDRrr : ComplexPattern; +def ADDRri : ComplexPattern; // Address operands -def MEMrr : Operand { +def MEMrr : Operand { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops IntRegs, IntRegs); + let MIOperandInfo = (ops ptr_rc, ptr_rc); } -def MEMri : Operand { +def MEMri : Operand { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops IntRegs, i32imm); + let MIOperandInfo = (ops ptr_rc, i32imm); } // Branch targets have OtherVT type. @@ -186,7 +186,7 @@ multiclass F3_12 Op3Val, SDNode OpNode> { def ri : F3_2<2, Op3Val, (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c), !strconcat(OpcStr, " $b, $c, $dst"), - [(set i32:$dst, (OpNode i32:$b, simm13:$c))]>; + [(set i32:$dst, (OpNode i32:$b, (i32 simm13:$c)))]>; } /// F3_12np multiclass - Define a normal F3_1/F3_2 pattern in one shot, with no @@ -770,7 +770,7 @@ def : Pat<(ctpop i32:$src), // Small immediates. def : Pat<(i32 simm13:$val), - (ORri G0, imm:$val)>; + (ORri (i32 G0), imm:$val)>; // Arbitrary immediates. def : Pat<(i32 imm:$val), (ORri (SETHIi (HI22 imm:$val)), (LO10 imm:$val))>; @@ -783,9 +783,9 @@ def : Pat<(subc i32:$b, simm13:$val), // Global addresses, constant pool entries def : Pat<(SPhi tglobaladdr:$in), (SETHIi tglobaladdr:$in)>; -def : Pat<(SPlo tglobaladdr:$in), (ORri G0, tglobaladdr:$in)>; +def : Pat<(SPlo tglobaladdr:$in), (ORri (i32 G0), tglobaladdr:$in)>; def : Pat<(SPhi tconstpool:$in), (SETHIi tconstpool:$in)>; -def : Pat<(SPlo tconstpool:$in), (ORri G0, tconstpool:$in)>; +def : Pat<(SPlo tconstpool:$in), (ORri (i32 G0), tconstpool:$in)>; // Add reg, lo. This is used when taking the addr of a global/constpool entry. def : Pat<(add i32:$r, (SPlo tglobaladdr:$in)), diff --git a/lib/Target/Sparc/SparcRegisterInfo.cpp b/lib/Target/Sparc/SparcRegisterInfo.cpp index 25e90b7af57..db9b30eb433 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.cpp +++ b/lib/Target/Sparc/SparcRegisterInfo.cpp @@ -56,6 +56,12 @@ BitVector SparcRegisterInfo::getReservedRegs(const MachineFunction &MF) const { return Reserved; } +const TargetRegisterClass* +SparcRegisterInfo::getPointerRegClass(const MachineFunction &MF, + unsigned Kind) const { + return Subtarget.is64Bit() ? &SP::I64RegsRegClass : &SP::IntRegsRegClass; +} + void SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, diff --git a/lib/Target/Sparc/SparcRegisterInfo.h b/lib/Target/Sparc/SparcRegisterInfo.h index b53a1ed095a..f91df539895 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.h +++ b/lib/Target/Sparc/SparcRegisterInfo.h @@ -36,6 +36,9 @@ struct SparcRegisterInfo : public SparcGenRegisterInfo { BitVector getReservedRegs(const MachineFunction &MF) const; + const TargetRegisterClass *getPointerRegClass(const MachineFunction &MF, + unsigned Kind) const; + void eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, RegScavenger *RS = NULL) const; diff --git a/lib/Target/Sparc/SparcRegisterInfo.td b/lib/Target/Sparc/SparcRegisterInfo.td index 81bff6c51c9..e8ccd20af8b 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.td +++ b/lib/Target/Sparc/SparcRegisterInfo.td @@ -140,7 +140,10 @@ def D15 : Rd<30, "F30", [F30, F31]>, DwarfRegNum<[87]>; // FIXME: the register order should be defined in terms of the preferred // allocation order... // -def IntRegs : RegisterClass<"SP", [i32], 32, +// This register class should not be used to hold i64 values, use the I64Regs +// register class for that. The i64 type is included here to allow i64 patterns +// using the integer instructions. +def IntRegs : RegisterClass<"SP", [i32, i64], 32, (add L0, L1, L2, L3, L4, L5, L6, L7, I0, I1, I2, I3, I4, I5, O0, O1, O2, O3, O4, O5, O7, @@ -155,6 +158,13 @@ def IntRegs : RegisterClass<"SP", [i32], 32, G5, G6, G7 // reserved for kernel )>; +// Register class for 64-bit mode, with a 64-bit spill slot size. +// These are the same as the 32-bit registers, so TableGen will consider this +// to be a sub-class of IntRegs. That works out because requiring a 64-bit +// spill slot is a stricter constraint than only requiring a 32-bit spill slot. +def I64Regs : RegisterClass<"SP", [i64], 64, (add IntRegs)>; + +// Floating point register classes. def FPRegs : RegisterClass<"SP", [f32], 32, (sequence "F%u", 0, 31)>; def DFPRegs : RegisterClass<"SP", [f64], 64, (sequence "D%u", 0, 15)>; -- 2.34.1