From: Nate Begeman Date: Thu, 1 Dec 2005 04:51:06 +0000 (+0000) Subject: Support multiple ValueTypes per RegisterClass, needed for upcoming vector X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;ds=sidebyside;h=6510b22cec7de4f0acc9965ec24c3668a6a8a87e;p=oota-llvm.git Support multiple ValueTypes per RegisterClass, needed for upcoming vector work. This change has no effect on generated code. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24563 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Target/MRegisterInfo.h b/include/llvm/Target/MRegisterInfo.h index f7baba2ce60..d17636d9a4d 100644 --- a/include/llvm/Target/MRegisterInfo.h +++ b/include/llvm/Target/MRegisterInfo.h @@ -45,18 +45,15 @@ public: typedef const unsigned* const_iterator; private: - const MVT::ValueType VT; + const MVT::ValueType* VTs; const unsigned RegSize, Alignment; // Size & Alignment of register in bytes const iterator RegsBegin, RegsEnd; public: - TargetRegisterClass(MVT::ValueType vt, unsigned RS, unsigned Al, iterator RB, iterator RE) - : VT(vt), RegSize(RS), Alignment(Al), RegsBegin(RB), RegsEnd(RE) {} + TargetRegisterClass(const MVT::ValueType *vts, unsigned RS, unsigned Al, + iterator RB, iterator RE) + : VTs(vts), RegSize(RS), Alignment(Al), RegsBegin(RB), RegsEnd(RE) {} virtual ~TargetRegisterClass() {} // Allow subclasses - /// getType - Return the declared value type for this register class. - /// - MVT::ValueType getType() const { return VT; } - // begin/end - Return all of the registers in this class. iterator begin() const { return RegsBegin; } iterator end() const { return RegsEnd; } @@ -78,6 +75,15 @@ public: return false; } + /// hasType - return true if this TargetRegisterClass has the ValueType vt. + /// + bool hasType(MVT::ValueType vt) const { + for(int i = 0; VTs[i] != MVT::Other; ++i) + if (VTs[i] == vt) + return true; + return false; + } + /// allocation_order_begin/end - These methods define a range of registers /// which specify the registers in this class that are valid to register /// allocate, and the preferred order to allocate them in. For example, diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp index f250a7bc050..c1a7f47bbc3 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp @@ -1208,7 +1208,7 @@ void SimpleSched::EmitNode(NodeInfo *NI) { // Pick the register class of the right type that contains this physreg. for (MRegisterInfo::regclass_iterator I = MRI.regclass_begin(), E = MRI.regclass_end(); I != E; ++I) - if ((*I)->getType() == Node->getValueType(0) && + if ((*I)->hasType(Node->getValueType(0)) && (*I)->contains(SrcReg)) { TRC = *I; break; diff --git a/lib/Target/Alpha/AlphaRegisterInfo.td b/lib/Target/Alpha/AlphaRegisterInfo.td index b0884360861..febf6fe2ff5 100644 --- a/lib/Target/Alpha/AlphaRegisterInfo.td +++ b/lib/Target/Alpha/AlphaRegisterInfo.td @@ -78,7 +78,7 @@ def F30 : FPR<30, "$f30">; def F31 : FPR<31, "$f31">; // $28 is undefined after any and all calls /// Register classes -def GPRC : RegisterClass<"Alpha", i64, 64, +def GPRC : RegisterClass<"Alpha", [i64], 64, // Volatile [R0, R1, R2, R3, R4, R5, R6, R7, R8, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R28, @@ -102,7 +102,7 @@ def GPRC : RegisterClass<"Alpha", i64, 64, }]; } -def F4RC : RegisterClass<"Alpha", f32, 64, [F0, F1, +def F4RC : RegisterClass<"Alpha", [f32], 64, [F0, F1, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, // Saved: @@ -120,7 +120,7 @@ def F4RC : RegisterClass<"Alpha", f32, 64, [F0, F1, }]; } -def F8RC : RegisterClass<"Alpha", f64, 64, [F0, F1, +def F8RC : RegisterClass<"Alpha", [f64], 64, [F0, F1, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, // Saved: diff --git a/lib/Target/IA64/IA64RegisterInfo.td b/lib/Target/IA64/IA64RegisterInfo.td index 60cdf991a23..03aba454635 100644 --- a/lib/Target/IA64/IA64RegisterInfo.td +++ b/lib/Target/IA64/IA64RegisterInfo.td @@ -232,7 +232,7 @@ def B6 : GR<0, "b6">; // FIXME/XXX we also reserve r22 for calculating addresses // in IA64RegisterInfo.cpp -def GR : RegisterClass<"IA64", i64, 64, +def GR : RegisterClass<"IA64", [i64], 64, [ //FIXME!: for readability, we don't want the out registers to be the first @@ -282,7 +282,7 @@ def GR : RegisterClass<"IA64", i64, 64, // these are the scratch (+stacked) FP registers -def FP : RegisterClass<"IA64", f64, 64, +def FP : RegisterClass<"IA64", [f64], 64, [F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F32, F33, F34, F35, F36, F37, F38, F39, @@ -317,7 +317,7 @@ def FP : RegisterClass<"IA64", f64, 64, } // these are the predicate registers, p0 (1/TRUE) is not here -def PR : RegisterClass<"IA64", i1, 64, +def PR : RegisterClass<"IA64", [i1], 64, // for now, let's be wimps and only have the scratch predicate regs [p6, p7, p8, p9, p10, p11, p12, p13, p14, p15]> { diff --git a/lib/Target/PowerPC/PPCRegisterInfo.td b/lib/Target/PowerPC/PPCRegisterInfo.td index d62045d8103..99813fdd2d1 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.td +++ b/lib/Target/PowerPC/PPCRegisterInfo.td @@ -135,7 +135,7 @@ def VRSAVE: SPR<256, "VRsave">; /// Register classes // Allocate volatiles first // then nonvolatiles in reverse order since stmw/lmw save from rN to r31 -def GPRC : RegisterClass<"PPC", i32, 32, +def GPRC : RegisterClass<"PPC", [i32], 32, [R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R30, R29, R28, R27, R26, R25, R24, R23, R22, R21, R20, R19, R18, R17, R16, R15, R14, R13, R31, R0, R1, LR]> @@ -158,7 +158,7 @@ def GPRC : RegisterClass<"PPC", i32, 32, } }]; } -def G8RC : RegisterClass<"PPC", i64, 64, +def G8RC : RegisterClass<"PPC", [i64], 64, [X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X30, X29, X28, X27, X26, X25, X24, X23, X22, X21, X20, X19, X18, X17, X16, X15, X14, X13, X31, X0, X1]> @@ -184,15 +184,16 @@ def G8RC : RegisterClass<"PPC", i64, 64, -def F8RC : RegisterClass<"PPC", f64, 64, [F0, F1, F2, F3, F4, F5, F6, F7, +def F8RC : RegisterClass<"PPC", [f64], 64, [F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31]>; -def F4RC : RegisterClass<"PPC", f32, 32, [F0, F1, F2, F3, F4, F5, F6, F7, +def F4RC : RegisterClass<"PPC", [f32], 32, [F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31]>; -def VRRC : RegisterClass<"PPC", v4f32, 128, [V0, V1, V2, V3, V4, V5, V6, V7, V8, - V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, +def VRRC : RegisterClass<"PPC", [v4f32], 128, [V0, V1, V2, V3, V4, V5, V6, V7, + V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30, V31]>; -def CRRC : RegisterClass<"PPC", i32, 32, [CR0, CR1, CR5, CR6, CR7, CR2, CR3, CR4]>; +def CRRC : RegisterClass<"PPC", [i32], 32, [CR0, CR1, CR5, CR6, CR7, CR2, + CR3, CR4]>; diff --git a/lib/Target/Skeleton/SkeletonRegisterInfo.td b/lib/Target/Skeleton/SkeletonRegisterInfo.td index 5313001ae55..41cef244c4f 100644 --- a/lib/Target/Skeleton/SkeletonRegisterInfo.td +++ b/lib/Target/Skeleton/SkeletonRegisterInfo.td @@ -89,10 +89,10 @@ def TBU : SPR<5, "TBU">; /// Register classes: one for floats and another for non-floats. /// -def GPRC : RegisterClass<"Skeleton", i32, 32, [R0, R1, R2, R3, R4, R5, R6, R7, +def GPRC : RegisterClass<"Skeleton", [i32], 32, [R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31]>; -def FPRC : RegisterClass<"Skeleton", f64, 64, [F0, F1, F2, F3, F4, F5, F6, F7, +def FPRC : RegisterClass<"Skeleton", [f64], 64, [F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31]>; diff --git a/lib/Target/Sparc/SparcRegisterInfo.td b/lib/Target/Sparc/SparcRegisterInfo.td index b3285469593..40eb185b71f 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.td +++ b/lib/Target/Sparc/SparcRegisterInfo.td @@ -84,7 +84,7 @@ def Y : Rs<0, "Y">; // FIXME: the register order should be defined in terms of the preferred // allocation order... // -def IntRegs : RegisterClass<"V8", i32, 32, [L0, L1, L2, L3, L4, L5, L6, L7, +def IntRegs : RegisterClass<"V8", [i32], 32, [L0, L1, L2, L3, L4, L5, L6, L7, I0, I1, I2, I3, I4, I5, G1, O0, O1, O2, O3, O4, O5, O7, @@ -109,9 +109,9 @@ def IntRegs : RegisterClass<"V8", i32, 32, [L0, L1, L2, L3, L4, L5, L6, L7, }]; } -def FPRegs : RegisterClass<"V8", f32, 32, [F0, F1, F2, F3, F4, F5, F6, F7, F8, +def FPRegs : RegisterClass<"V8", [f32], 32, [F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31]>; -def DFPRegs : RegisterClass<"V8", f64, 64, [D0, D1, D2, D3, D4, D5, D6, D7, +def DFPRegs : RegisterClass<"V8", [f64], 64, [D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15]>; diff --git a/lib/Target/SparcV8/SparcV8RegisterInfo.td b/lib/Target/SparcV8/SparcV8RegisterInfo.td index b3285469593..40eb185b71f 100644 --- a/lib/Target/SparcV8/SparcV8RegisterInfo.td +++ b/lib/Target/SparcV8/SparcV8RegisterInfo.td @@ -84,7 +84,7 @@ def Y : Rs<0, "Y">; // FIXME: the register order should be defined in terms of the preferred // allocation order... // -def IntRegs : RegisterClass<"V8", i32, 32, [L0, L1, L2, L3, L4, L5, L6, L7, +def IntRegs : RegisterClass<"V8", [i32], 32, [L0, L1, L2, L3, L4, L5, L6, L7, I0, I1, I2, I3, I4, I5, G1, O0, O1, O2, O3, O4, O5, O7, @@ -109,9 +109,9 @@ def IntRegs : RegisterClass<"V8", i32, 32, [L0, L1, L2, L3, L4, L5, L6, L7, }]; } -def FPRegs : RegisterClass<"V8", f32, 32, [F0, F1, F2, F3, F4, F5, F6, F7, F8, +def FPRegs : RegisterClass<"V8", [f32], 32, [F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31]>; -def DFPRegs : RegisterClass<"V8", f64, 64, [D0, D1, D2, D3, D4, D5, D6, D7, +def DFPRegs : RegisterClass<"V8", [f64], 64, [D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15]>; diff --git a/lib/Target/SparcV9/SparcV9RegisterInfo.cpp b/lib/Target/SparcV9/SparcV9RegisterInfo.cpp index d2d0946053f..0ef9d34365f 100644 --- a/lib/Target/SparcV9/SparcV9RegisterInfo.cpp +++ b/lib/Target/SparcV9/SparcV9RegisterInfo.cpp @@ -27,6 +27,7 @@ #include "SparcV9RegisterInfo.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/ValueTypes.h" using namespace llvm; namespace llvm { @@ -42,8 +43,9 @@ namespace { SparcV9::g2, SparcV9::g3, SparcV9::g4, SparcV9::g5, SparcV9::g6, SparcV9::g7, SparcV9::o6 }; + const MVT::ValueType IRVTs[] = { MVT::i64, MVT::Other }; struct IRClass : public TargetRegisterClass { - IRClass() : TargetRegisterClass(MVT::i64, 8, 8, IR, IR + 32) {} + IRClass() : TargetRegisterClass(IRVTs, 8, 8, IR, IR + 32) {} } IRInstance; @@ -66,12 +68,13 @@ namespace { SparcV9::f58, SparcV9::f59, SparcV9::f60, SparcV9::f61, SparcV9::f62, SparcV9::f63 }; + const MVT::ValueType FRVTs[] = { MVT::f32, MVT::Other }; // FIXME: The size is correct for the first 32 registers. The // latter 32 do not all really exist; you can only access every other // one (32, 34, ...), and they must contain double-fp or quad-fp // values... see below about the aliasing problems. struct FRClass : public TargetRegisterClass { - FRClass() : TargetRegisterClass(MVT::f32, 4, 8, FR, FR + 64) {} + FRClass() : TargetRegisterClass(FRVTs, 4, 8, FR, FR + 64) {} } FRInstance; @@ -79,8 +82,9 @@ namespace { const unsigned ICCR[] = { SparcV9::xcc, SparcV9::icc, SparcV9::ccr }; + const MVT::ValueType ICCRVTs[] = { MVT::i1, MVT::Other }; struct ICCRClass : public TargetRegisterClass { - ICCRClass() : TargetRegisterClass(MVT::i1, 1, 8, ICCR, ICCR + 3) {} + ICCRClass() : TargetRegisterClass(ICCRVTs, 1, 8, ICCR, ICCR + 3) {} } ICCRInstance; @@ -88,8 +92,9 @@ namespace { const unsigned FCCR[] = { SparcV9::fcc0, SparcV9::fcc1, SparcV9::fcc2, SparcV9::fcc3 }; + const MVT::ValueType FCCRVTs[] = { MVT::i1, MVT::Other }; struct FCCRClass : public TargetRegisterClass { - FCCRClass() : TargetRegisterClass(MVT::i1, 1, 8, FCCR, FCCR + 4) {} + FCCRClass() : TargetRegisterClass(FCCRVTs, 1, 8, FCCR, FCCR + 4) {} } FCCRInstance; @@ -97,8 +102,9 @@ namespace { const unsigned SR[] = { SparcV9::fsr }; + const MVT::ValueType SRVTs[] = { MVT::i64, MVT::Other }; struct SRClass : public TargetRegisterClass { - SRClass() : TargetRegisterClass(MVT::i64, 8, 8, SR, SR + 1) {} + SRClass() : TargetRegisterClass(SRVTs, 8, 8, SR, SR + 1) {} } SRInstance; diff --git a/lib/Target/SparcV9/SparcV9RegisterInfo.td b/lib/Target/SparcV9/SparcV9RegisterInfo.td index a248bc5a2cd..c2266511c02 100644 --- a/lib/Target/SparcV9/SparcV9RegisterInfo.td +++ b/lib/Target/SparcV9/SparcV9RegisterInfo.td @@ -43,7 +43,7 @@ let Namespace = "SparcV9" in { // FIXME: the register order should be defined in terms of the preferred // allocation order... // -def IntRegs : RegisterClass<"V9", i64, 64, [G0, G1, G2, G3, G4, G5, G6, G7, +def IntRegs : RegisterClass<"V9", [i64], 64, [G0, G1, G2, G3, G4, G5, G6, G7, O0, O1, O2, O3, O4, O5, O6, O7, L0, L1, L2, L3, L4, L5, L6, L7, I0, I1, I2, I3, I4, I5, I6, I7]>; diff --git a/lib/Target/Target.td b/lib/Target/Target.td index eeda4f9fe06..46a1b470c49 100644 --- a/lib/Target/Target.td +++ b/lib/Target/Target.td @@ -90,19 +90,22 @@ class RegisterGroup aliases> : Register { // register classes. This also defines the default allocation order of // registers by register allocators. // -class RegisterClass regTypes, int alignment, list regList> { string Namespace = namespace; // RegType - Specify the ValueType of the registers in this register class. // Note that all registers in a register class must have the same ValueType. // - ValueType RegType = regType; + list RegTypes = regTypes; + + // Size - Specify the spill size in bits of the registers. A default value of + // zero lets tablgen pick an appropriate size. + int Size = 0; // Alignment - Specify the alignment required of the registers when they are // stored or loaded to memory. // - int Size = RegType.Size; int Alignment = alignment; // MemberList - Specify which registers are in this class. If the diff --git a/lib/Target/X86/X86RegisterInfo.td b/lib/Target/X86/X86RegisterInfo.td index 64571525cd4..139ebd7fd71 100644 --- a/lib/Target/X86/X86RegisterInfo.td +++ b/lib/Target/X86/X86RegisterInfo.td @@ -72,9 +72,9 @@ let Namespace = "X86" in { // dependences between upper and lower parts of the register. BL and BH are // last because they are call clobbered. Both Athlon and P4 chips suffer this // issue. -def R8 : RegisterClass<"X86", i8, 8, [AL, CL, DL, AH, CH, DH, BL, BH]>; +def R8 : RegisterClass<"X86", [i8], 8, [AL, CL, DL, AH, CH, DH, BL, BH]>; -def R16 : RegisterClass<"X86", i16, 16, [AX, CX, DX, SI, DI, BX, BP, SP]> { +def R16 : RegisterClass<"X86", [i16], 16, [AX, CX, DX, SI, DI, BX, BP, SP]> { let MethodProtos = [{ iterator allocation_order_end(MachineFunction &MF) const; }]; @@ -89,7 +89,8 @@ def R16 : RegisterClass<"X86", i16, 16, [AX, CX, DX, SI, DI, BX, BP, SP]> { }]; } -def R32 : RegisterClass<"X86", i32, 32, [EAX, ECX, EDX, ESI, EDI, EBX, EBP, ESP]> { +def R32 : RegisterClass<"X86", [i32], 32, + [EAX, ECX, EDX, ESI, EDI, EBX, EBP, ESP]> { let MethodProtos = [{ iterator allocation_order_end(MachineFunction &MF) const; }]; @@ -106,9 +107,9 @@ def R32 : RegisterClass<"X86", i32, 32, [EAX, ECX, EDX, ESI, EDI, EBX, EBP, ESP] // V4F4, the 4 x f32 class, and V2F8, the 2 x f64 class, which we will use for // Scalar SSE2 floating point support. -def V4F4 : RegisterClass<"X86", f32, 32, +def V4F4 : RegisterClass<"X86", [f32], 32, [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7]>; -def V2F8 : RegisterClass<"X86", f64, 64, +def V2F8 : RegisterClass<"X86", [f64], 64, [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7]>; // FIXME: This sets up the floating point register files as though they are f64 @@ -117,12 +118,12 @@ def V2F8 : RegisterClass<"X86", f64, 64, // faster on common hardware. In reality, this should be controlled by a // command line option or something. -def RFP : RegisterClass<"X86", f64, 32, [FP0, FP1, FP2, FP3, FP4, FP5, FP6]>; +def RFP : RegisterClass<"X86", [f64], 32, [FP0, FP1, FP2, FP3, FP4, FP5, FP6]>; // Floating point stack registers (these are not allocatable by the // register allocator - the floating point stackifier is responsible // for transforming FPn allocations to STn registers) -def RST : RegisterClass<"X86", f64, 32, +def RST : RegisterClass<"X86", [f64], 32, [ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7]> { let MethodProtos = [{ iterator allocation_order_end(MachineFunction &MF) const; diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h index 6a9b7907bd8..d719d89d625 100644 --- a/utils/TableGen/CodeGenRegisters.h +++ b/utils/TableGen/CodeGenRegisters.h @@ -35,13 +35,20 @@ namespace llvm { Record *TheDef; std::string Namespace; std::vector Elements; + std::vector VTs; unsigned SpillSize; unsigned SpillAlignment; - MVT::ValueType VT; std::string MethodProtos, MethodBodies; const std::string &getName() const; + const MVT::ValueType getValueTypeNum(unsigned VTNum) const { + if (VTNum < VTs.size()) + return VTs[VTNum]; + assert(0 && "VTNum greater than number of ValueTypes in RegClass!"); + abort(); + } + CodeGenRegisterClass(Record *R); }; } diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index 73730d18a80..51aad4fd3bb 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -154,13 +154,15 @@ CodeGenRegisterClass::CodeGenRegisterClass(Record *R) : TheDef(R) { R->setName("AnonRegClass_"+utostr(AnonCounter++)); } - Namespace = R->getValueAsString("Namespace"); - SpillSize = R->getValueAsInt("Size"); - SpillAlignment = R->getValueAsInt("Alignment"); - VT = getValueType(R->getValueAsDef("RegType")); - - MethodBodies = R->getValueAsCode("MethodBodies"); - MethodProtos = R->getValueAsCode("MethodProtos"); + std::vector TypeList = R->getValueAsListOfDefs("RegTypes"); + for (unsigned i = 0, e = TypeList.size(); i != e; ++i) { + Record *Type = TypeList[i]; + if (!Type->isSubClassOf("ValueType")) + throw "RegTypes list member '" + Type->getName() + + "' does not derive from the ValueType class!"; + VTs.push_back(getValueType(Type)); + } + assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!"); std::vector RegList = R->getValueAsListOfDefs("MemberList"); for (unsigned i = 0, e = RegList.size(); i != e; ++i) { @@ -170,6 +172,15 @@ CodeGenRegisterClass::CodeGenRegisterClass(Record *R) : TheDef(R) { "' does not derive from the Register class!"; Elements.push_back(Reg); } + + // Allow targets to override the size in bits of the RegisterClass. + unsigned Size = R->getValueAsInt("Size"); + + Namespace = R->getValueAsString("Namespace"); + SpillSize = Size ? Size : MVT::getSizeInBits(VTs[0]); + SpillAlignment = R->getValueAsInt("Alignment"); + MethodBodies = R->getValueAsCode("MethodBodies"); + MethodProtos = R->getValueAsCode("MethodProtos"); } const std::string &CodeGenRegisterClass::getName() const { @@ -179,7 +190,8 @@ const std::string &CodeGenRegisterClass::getName() const { void CodeGenTarget::ReadLegalValueTypes() const { const std::vector &RCs = getRegisterClasses(); for (unsigned i = 0, e = RCs.size(); i != e; ++i) - LegalValueTypes.push_back(RCs[i].VT); + for (unsigned ri = 0, re = RCs[i].VTs.size(); ri != re; ++ri) + LegalValueTypes.push_back(RCs[i].VTs[ri]); // Remove duplicates. std::sort(LegalValueTypes.begin(), LegalValueTypes.end()); diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index 4b40561b268..8e6095c1063 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -455,7 +455,9 @@ static unsigned char getIntrinsicType(Record *R, bool NotRegisters, // Check to see if this is a register or a register class... if (R->isSubClassOf("RegisterClass")) { if (NotRegisters) return MVT::isUnknown; - return getValueType(R->getValueAsDef("RegType")); + const CodeGenRegisterClass &RC = + TP.getDAGISelEmitter().getTargetInfo().getRegisterClass(R); + return RC.getValueTypeNum(0); } else if (R->isSubClassOf("PatFrag")) { // Pattern fragment types will be resolved when they are inlined. return MVT::isUnknown; @@ -537,8 +539,9 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { const CodeGenRegisterClass &RC = TP.getDAGISelEmitter().getTargetInfo().getRegisterClass(ResultNode); - - bool MadeChange = UpdateNodeType(RC.VT, TP); + + // Get the first ValueType in the RegClass, it's as good as any. + bool MadeChange = UpdateNodeType(RC.getValueTypeNum(0), TP); if (getNumChildren() != Inst.getNumOperands()) TP.error("Instruction '" + getOperator()->getName() + " expects " + @@ -550,7 +553,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { if (OperandNode->isSubClassOf("RegisterClass")) { const CodeGenRegisterClass &RC = TP.getDAGISelEmitter().getTargetInfo().getRegisterClass(OperandNode); - VT = RC.VT; + VT = RC.getValueTypeNum(0); } else if (OperandNode->isSubClassOf("Operand")) { VT = getValueType(OperandNode->getValueAsDef("Type")); } else { @@ -1672,7 +1675,8 @@ void DAGISelEmitter::EmitMatchForPattern(TreePatternNode *N, << ".Val)) goto P" << PatternNo << "Fail;\n"; } -/// getRegisterValueType - Look up and return ValueType of specified record +/// getRegisterValueType - Look up and return the first ValueType of specified +/// RegisterClass record static MVT::ValueType getRegisterValueType(Record *R, const CodeGenTarget &T) { const std::vector &RegisterClasses = T.getRegisterClasses(); @@ -1681,7 +1685,7 @@ static MVT::ValueType getRegisterValueType(Record *R, const CodeGenTarget &T) { const CodeGenRegisterClass &RC = RegisterClasses[i]; for (unsigned ei = 0, ee = RC.Elements.size(); ei != ee; ++ei) { if (R == RC.Elements[ei]) { - return RC.VT; + return RC.getValueTypeNum(0); } } } diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 5c3cb8db808..13a85f784fa 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -109,6 +109,7 @@ void RegisterInfoEmitter::run(std::ostream &OS) { // belongs to. std::multimap RegClassesBelongedTo; + // Emit the register enum value arrays for each RegisterClass for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = RegisterClasses[rc]; @@ -127,6 +128,22 @@ void RegisterInfoEmitter::run(std::ostream &OS) { } OS << "\n };\n\n"; } + + // Emit the ValueType arrays for each RegisterClass + for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { + const CodeGenRegisterClass &RC = RegisterClasses[rc]; + + // Give the register class a legal C name if it's anonymous. + std::string Name = RC.TheDef->getName() + "VTs"; + + // Emit the register list now. + OS << " // " << Name + << " Register Class Value Types...\n const MVT::ValueType " << Name + << "[] = {\n "; + for (unsigned i = 0, e = RC.VTs.size(); i != e; ++i) + OS << "MVT::" << RC.VTs[i] << ", "; + OS << "MVT::Other\n };\n\n"; + } OS << "} // end anonymous namespace\n\n"; // Now that all of the structs have been emitted, emit the instances. @@ -140,8 +157,8 @@ void RegisterInfoEmitter::run(std::ostream &OS) { for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { const CodeGenRegisterClass &RC = RegisterClasses[i]; OS << RC.MethodBodies << "\n"; - OS << RC.getName() << "Class::" << RC.getName() - << "Class() : TargetRegisterClass(MVT::" << getEnumName(RC.VT) << "," + OS << RC.getName() << "Class::" << RC.getName() + << "Class() : TargetRegisterClass(" << RC.getName() + "VTs" << ", " << RC.SpillSize/8 << ", " << RC.SpillAlignment/8 << ", " << RC.getName() << ", " << RC.getName() << " + " << RC.Elements.size() << ") {}\n";