X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FARM%2FARMRegisterInfo.td;h=462b158b38f2fd3faca7e1de135fe192305df2ba;hb=0b951ceb02c43c157022f284881da7d2f7daf58d;hp=80325ae54e70c20f07c1dedd3606f609af106e52;hpb=b990a2f249196ad3e0cc451d40a45fc2f9278eaf;p=oota-llvm.git diff --git a/lib/Target/ARM/ARMRegisterInfo.td b/lib/Target/ARM/ARMRegisterInfo.td index 80325ae54e7..462b158b38f 100644 --- a/lib/Target/ARM/ARMRegisterInfo.td +++ b/lib/Target/ARM/ARMRegisterInfo.td @@ -1,4 +1,4 @@ -//===- ARMRegisterInfo.td - ARM Register defs -------------------*- C++ -*-===// +//===- ARMRegisterInfo.td - ARM Register defs --------------*- tablegen -*-===// // // The LLVM Compiler Infrastructure // @@ -23,6 +23,44 @@ class ARMFReg num, string n> : Register { let Namespace = "ARM"; } +// Subregister indices. +let Namespace = "ARM" in { +// Note: Code depends on these having consecutive numbers. +def ssub_0 : SubRegIndex; +def ssub_1 : SubRegIndex; +def ssub_2 : SubRegIndex; // In a Q reg. +def ssub_3 : SubRegIndex; +def ssub_4 : SubRegIndex; // In a QQ reg. +def ssub_5 : SubRegIndex; +def ssub_6 : SubRegIndex; +def ssub_7 : SubRegIndex; +def ssub_8 : SubRegIndex; // In a QQQQ reg. +def ssub_9 : SubRegIndex; +def ssub_10 : SubRegIndex; +def ssub_11 : SubRegIndex; +def ssub_12 : SubRegIndex; +def ssub_13 : SubRegIndex; +def ssub_14 : SubRegIndex; +def ssub_15 : SubRegIndex; + +def dsub_0 : SubRegIndex; +def dsub_1 : SubRegIndex; +def dsub_2 : SubRegIndex; +def dsub_3 : SubRegIndex; +def dsub_4 : SubRegIndex; +def dsub_5 : SubRegIndex; +def dsub_6 : SubRegIndex; +def dsub_7 : SubRegIndex; + +def qsub_0 : SubRegIndex; +def qsub_1 : SubRegIndex; +def qsub_2 : SubRegIndex; +def qsub_3 : SubRegIndex; + +def qqsub_0 : SubRegIndex; +def qqsub_1 : SubRegIndex; +} + // Integer registers def R0 : ARMReg< 0, "r0">, DwarfRegNum<[0]>; def R1 : ARMReg< 1, "r1">, DwarfRegNum<[1]>; @@ -58,9 +96,9 @@ def S24 : ARMFReg<24, "s24">; def S25 : ARMFReg<25, "s25">; def S26 : ARMFReg<26, "s26">; def S27 : ARMFReg<27, "s27">; def S28 : ARMFReg<28, "s28">; def S29 : ARMFReg<29, "s29">; def S30 : ARMFReg<30, "s30">; def S31 : ARMFReg<31, "s31">; -def SDummy : ARMFReg<63, "sINVALID">; // Aliases of the F* registers used to hold 64-bit fp values (doubles) +let SubRegIndices = [ssub_0, ssub_1] in { def D0 : ARMReg< 0, "d0", [S0, S1]>; def D1 : ARMReg< 1, "d1", [S2, S3]>; def D2 : ARMReg< 2, "d2", [S4, S5]>; @@ -77,6 +115,7 @@ def D12 : ARMReg<12, "d12", [S24, S25]>; def D13 : ARMReg<13, "d13", [S26, S27]>; def D14 : ARMReg<14, "d14", [S28, S29]>; def D15 : ARMReg<15, "d15", [S30, S31]>; +} // VFP3 defines 16 additional double registers def D16 : ARMFReg<16, "d16">; def D17 : ARMFReg<17, "d17">; @@ -87,9 +126,11 @@ def D24 : ARMFReg<24, "d24">; def D25 : ARMFReg<25, "d25">; def D26 : ARMFReg<26, "d26">; def D27 : ARMFReg<27, "d27">; def D28 : ARMFReg<28, "d28">; def D29 : ARMFReg<29, "d29">; def D30 : ARMFReg<30, "d30">; def D31 : ARMFReg<31, "d31">; -def DDummy : ARMFReg<31, "dINVALID">; // Advanced SIMD (NEON) defines 16 quad-word aliases +let SubRegIndices = [dsub_0, dsub_1], + CompositeIndices = [(ssub_2 dsub_1, ssub_0), + (ssub_3 dsub_1, ssub_1)] in { def Q0 : ARMReg< 0, "q0", [D0, D1]>; def Q1 : ARMReg< 1, "q1", [D2, D3]>; def Q2 : ARMReg< 2, "q2", [D4, D5]>; @@ -98,6 +139,8 @@ def Q4 : ARMReg< 4, "q4", [D8, D9]>; def Q5 : ARMReg< 5, "q5", [D10, D11]>; def Q6 : ARMReg< 6, "q6", [D12, D13]>; def Q7 : ARMReg< 7, "q7", [D14, D15]>; +} +let SubRegIndices = [dsub_0, dsub_1] in { def Q8 : ARMReg< 8, "q8", [D16, D17]>; def Q9 : ARMReg< 9, "q9", [D18, D19]>; def Q10 : ARMReg<10, "q10", [D20, D21]>; @@ -106,34 +149,57 @@ def Q12 : ARMReg<12, "q12", [D24, D25]>; def Q13 : ARMReg<13, "q13", [D26, D27]>; def Q14 : ARMReg<14, "q14", [D28, D29]>; def Q15 : ARMReg<15, "q15", [D30, D31]>; -def QDummy : ARMFReg<16, "qINVALID">; +} // Pseudo 256-bit registers to represent pairs of Q registers. These should // never be present in the emitted code. -// These are used for NEON load / store instructions, e.g. vld4, vst3. -// NOTE: It's possible to define more QQ registers since technical the -// starting D register number doesn't have to be multiple of 4. e.g. -// D1, D2, D3, D4 would be a legal quad. But that would make the sub-register -// stuffs very messy. +// These are used for NEON load / store instructions, e.g., vld4, vst3. +// NOTE: It's possible to define more QQ registers since technically the +// starting D register number doesn't have to be multiple of 4, e.g., +// D1, D2, D3, D4 would be a legal quad, but that would make the subregister +// stuff very messy. +let SubRegIndices = [qsub_0, qsub_1] in { +let CompositeIndices = [(dsub_2 qsub_1, dsub_0), (dsub_3 qsub_1, dsub_1), + (ssub_4 qsub_1, ssub_0), (ssub_5 qsub_1, ssub_1), + (ssub_6 qsub_1, ssub_2), (ssub_7 qsub_1, ssub_3)] in { def QQ0 : ARMReg<0, "qq0", [Q0, Q1]>; def QQ1 : ARMReg<1, "qq1", [Q2, Q3]>; def QQ2 : ARMReg<2, "qq2", [Q4, Q5]>; def QQ3 : ARMReg<3, "qq3", [Q6, Q7]>; +} +let CompositeIndices = [(dsub_2 qsub_1, dsub_0), (dsub_3 qsub_1, dsub_1)] in { def QQ4 : ARMReg<4, "qq4", [Q8, Q9]>; def QQ5 : ARMReg<5, "qq5", [Q10, Q11]>; def QQ6 : ARMReg<6, "qq6", [Q12, Q13]>; def QQ7 : ARMReg<7, "qq7", [Q14, Q15]>; +} +} // Pseudo 512-bit registers to represent four consecutive Q registers. +let SubRegIndices = [qqsub_0, qqsub_1] in { +let CompositeIndices = [(qsub_2 qqsub_1, qsub_0), (qsub_3 qqsub_1, qsub_1), + (dsub_4 qqsub_1, dsub_0), (dsub_5 qqsub_1, dsub_1), + (dsub_6 qqsub_1, dsub_2), (dsub_7 qqsub_1, dsub_3), + (ssub_8 qqsub_1, ssub_0), (ssub_9 qqsub_1, ssub_1), + (ssub_10 qqsub_1, ssub_2), (ssub_11 qqsub_1, ssub_3), + (ssub_12 qqsub_1, ssub_4), (ssub_13 qqsub_1, ssub_5), + (ssub_14 qqsub_1, ssub_6), (ssub_15 qqsub_1, ssub_7)] in +{ def QQQQ0 : ARMReg<0, "qqqq0", [QQ0, QQ1]>; def QQQQ1 : ARMReg<1, "qqqq1", [QQ2, QQ3]>; +} +let CompositeIndices = [(qsub_2 qqsub_1, qsub_0), (qsub_3 qqsub_1, qsub_1), + (dsub_4 qqsub_1, dsub_0), (dsub_5 qqsub_1, dsub_1), + (dsub_6 qqsub_1, dsub_2), (dsub_7 qqsub_1, dsub_3)] in { def QQQQ2 : ARMReg<2, "qqqq2", [QQ4, QQ5]>; def QQQQ3 : ARMReg<3, "qqqq3", [QQ6, QQ7]>; +} +} // Current Program Status Register. -def CPSR : ARMReg<0, "cpsr">; - -def FPSCR : ARMReg<1, "fpscr">; +def CPSR : ARMReg<0, "cpsr">; +def FPSCR : ARMReg<1, "fpscr">; +def ITSTATE : ARMReg<2, "itstate">; // Register classes. // @@ -154,41 +220,11 @@ def GPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6, iterator allocation_order_end(const MachineFunction &MF) const; }]; let MethodBodies = [{ - // FP is R11, R9 is available. - static const unsigned ARM_GPR_AO_1[] = { - ARM::R0, ARM::R1, ARM::R2, ARM::R3, - ARM::R12,ARM::LR, - ARM::R4, ARM::R5, ARM::R6, ARM::R7, - ARM::R8, ARM::R9, ARM::R10, - ARM::R11 }; - // FP is R11, R9 is not available. - static const unsigned ARM_GPR_AO_2[] = { + static const unsigned ARM_GPR_AO[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3, ARM::R12,ARM::LR, ARM::R4, ARM::R5, ARM::R6, ARM::R7, - ARM::R8, ARM::R10, - ARM::R11 }; - // FP is R7, R9 is available as non-callee-saved register. - // This is used by Darwin. - static const unsigned ARM_GPR_AO_3[] = { - ARM::R0, ARM::R1, ARM::R2, ARM::R3, - ARM::R9, ARM::R12,ARM::LR, - ARM::R4, ARM::R5, ARM::R6, - ARM::R8, ARM::R10,ARM::R11,ARM::R7 }; - // FP is R7, R9 is not available. - static const unsigned ARM_GPR_AO_4[] = { - ARM::R0, ARM::R1, ARM::R2, ARM::R3, - ARM::R12,ARM::LR, - ARM::R4, ARM::R5, ARM::R6, - ARM::R8, ARM::R10,ARM::R11, - ARM::R7 }; - // FP is R7, R9 is available as callee-saved register. - // This is used by non-Darwin platform in Thumb mode. - static const unsigned ARM_GPR_AO_5[] = { - ARM::R0, ARM::R1, ARM::R2, ARM::R3, - ARM::R12,ARM::LR, - ARM::R4, ARM::R5, ARM::R6, - ARM::R8, ARM::R9, ARM::R10,ARM::R11,ARM::R7 }; + ARM::R8, ARM::R9, ARM::R10, ARM::R11 }; // For Thumb1 mode, we don't want to allocate hi regs at all, as we // don't know how to spill them. If we make our prologue/epilogue code @@ -204,85 +240,122 @@ def GPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6, const ARMSubtarget &Subtarget = TM.getSubtarget(); if (Subtarget.isThumb1Only()) return THUMB_GPR_AO; - if (Subtarget.isTargetDarwin()) { - if (Subtarget.isR9Reserved()) - return ARM_GPR_AO_4; - else - return ARM_GPR_AO_3; - } else { - if (Subtarget.isR9Reserved()) - return ARM_GPR_AO_2; - else if (Subtarget.isThumb()) - return ARM_GPR_AO_5; - else - return ARM_GPR_AO_1; - } + return ARM_GPR_AO; } GPRClass::iterator GPRClass::allocation_order_end(const MachineFunction &MF) const { const TargetMachine &TM = MF.getTarget(); - const TargetRegisterInfo *RI = TM.getRegisterInfo(); const ARMSubtarget &Subtarget = TM.getSubtarget(); - GPRClass::iterator I; - - if (Subtarget.isThumb1Only()) { - I = THUMB_GPR_AO + (sizeof(THUMB_GPR_AO)/sizeof(unsigned)); - // Mac OS X requires FP not to be clobbered for backtracing purpose. - return (Subtarget.isTargetDarwin() || RI->hasFP(MF)) ? I-1 : I; - } - - if (Subtarget.isTargetDarwin()) { - if (Subtarget.isR9Reserved()) - I = ARM_GPR_AO_4 + (sizeof(ARM_GPR_AO_4)/sizeof(unsigned)); - else - I = ARM_GPR_AO_3 + (sizeof(ARM_GPR_AO_3)/sizeof(unsigned)); - } else { - if (Subtarget.isR9Reserved()) - I = ARM_GPR_AO_2 + (sizeof(ARM_GPR_AO_2)/sizeof(unsigned)); - else if (Subtarget.isThumb()) - I = ARM_GPR_AO_5 + (sizeof(ARM_GPR_AO_5)/sizeof(unsigned)); - else - I = ARM_GPR_AO_1 + (sizeof(ARM_GPR_AO_1)/sizeof(unsigned)); - } - - // Mac OS X requires FP not to be clobbered for backtracing purpose. - return (Subtarget.isTargetDarwin() || RI->hasFP(MF)) ? I-1 : I; + if (Subtarget.isThumb1Only()) + return THUMB_GPR_AO + (sizeof(THUMB_GPR_AO)/sizeof(unsigned)); + return ARM_GPR_AO + (sizeof(ARM_GPR_AO)/sizeof(unsigned)); + } + }]; +} + +// restricted GPR register class. Many Thumb2 instructions allow the full +// register range for operands, but have undefined behaviours when PC +// or SP (R13 or R15) are used. The ARM ARM refers to these operands +// via the BadReg() pseudo-code description. +def rGPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6, + R7, R8, R9, R10, R11, R12, LR]> { + let MethodProtos = [{ + iterator allocation_order_begin(const MachineFunction &MF) const; + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + static const unsigned ARM_rGPR_AO[] = { + ARM::R0, ARM::R1, ARM::R2, ARM::R3, + ARM::R12,ARM::LR, + ARM::R4, ARM::R5, ARM::R6, ARM::R7, + ARM::R8, ARM::R9, ARM::R10, + ARM::R11 }; + + // For Thumb1 mode, we don't want to allocate hi regs at all, as we + // don't know how to spill them. If we make our prologue/epilogue code + // smarter at some point, we can go back to using the above allocation + // orders for the Thumb1 instructions that know how to use hi regs. + static const unsigned THUMB_rGPR_AO[] = { + ARM::R0, ARM::R1, ARM::R2, ARM::R3, + ARM::R4, ARM::R5, ARM::R6, ARM::R7 }; + + rGPRClass::iterator + rGPRClass::allocation_order_begin(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const ARMSubtarget &Subtarget = TM.getSubtarget(); + if (Subtarget.isThumb1Only()) + return THUMB_rGPR_AO; + return ARM_rGPR_AO; + } + + rGPRClass::iterator + rGPRClass::allocation_order_end(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const ARMSubtarget &Subtarget = TM.getSubtarget(); + + if (Subtarget.isThumb1Only()) + return THUMB_rGPR_AO + (sizeof(THUMB_rGPR_AO)/sizeof(unsigned)); + return ARM_rGPR_AO + (sizeof(ARM_rGPR_AO)/sizeof(unsigned)); } }]; } // Thumb registers are R0-R7 normally. Some instructions can still use // the general GPR register class above (MOV, e.g.) -def tGPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6, R7]> { +def tGPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6, R7]> {} + +// For tail calls, we can't use callee-saved registers, as they are restored +// to the saved value before the tail call, which would clobber a call address. +// Note, getMinimalPhysRegClass(R0) returns tGPR because of the names of +// this class and the preceding one(!) This is what we want. +def tcGPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R9, R12]> { let MethodProtos = [{ iterator allocation_order_begin(const MachineFunction &MF) const; iterator allocation_order_end(const MachineFunction &MF) const; }]; let MethodBodies = [{ - static const unsigned THUMB_tGPR_AO[] = { + // R9 is available. + static const unsigned ARM_GPR_R9_TC[] = { ARM::R0, ARM::R1, ARM::R2, ARM::R3, - ARM::R4, ARM::R5, ARM::R6, ARM::R7 }; + ARM::R9, ARM::R12 }; + // R9 is not available. + static const unsigned ARM_GPR_NOR9_TC[] = { + ARM::R0, ARM::R1, ARM::R2, ARM::R3, + ARM::R12 }; - // FP is R7, only low registers available. - tGPRClass::iterator - tGPRClass::allocation_order_begin(const MachineFunction &MF) const { - return THUMB_tGPR_AO; + // For Thumb1 mode, we don't want to allocate hi regs at all, as we + // don't know how to spill them. If we make our prologue/epilogue code + // smarter at some point, we can go back to using the above allocation + // orders for the Thumb1 instructions that know how to use hi regs. + static const unsigned THUMB_GPR_AO_TC[] = { + ARM::R0, ARM::R1, ARM::R2, ARM::R3 }; + + tcGPRClass::iterator + tcGPRClass::allocation_order_begin(const MachineFunction &MF) const { + const TargetMachine &TM = MF.getTarget(); + const ARMSubtarget &Subtarget = TM.getSubtarget(); + if (Subtarget.isThumb1Only()) + return THUMB_GPR_AO_TC; + return Subtarget.isTargetDarwin() ? ARM_GPR_R9_TC : ARM_GPR_NOR9_TC; } - tGPRClass::iterator - tGPRClass::allocation_order_end(const MachineFunction &MF) const { + tcGPRClass::iterator + tcGPRClass::allocation_order_end(const MachineFunction &MF) const { const TargetMachine &TM = MF.getTarget(); - const TargetRegisterInfo *RI = TM.getRegisterInfo(); const ARMSubtarget &Subtarget = TM.getSubtarget(); - tGPRClass::iterator I = - THUMB_tGPR_AO + (sizeof(THUMB_tGPR_AO)/sizeof(unsigned)); - // Mac OS X requires FP not to be clobbered for backtracing purpose. - return (Subtarget.isTargetDarwin() || RI->hasFP(MF)) ? I-1 : I; + + if (Subtarget.isThumb1Only()) + return THUMB_GPR_AO_TC + (sizeof(THUMB_GPR_AO_TC)/sizeof(unsigned)); + + return Subtarget.isTargetDarwin() ? + ARM_GPR_R9_TC + (sizeof(ARM_GPR_R9_TC)/sizeof(unsigned)) : + ARM_GPR_NOR9_TC + (sizeof(ARM_GPR_NOR9_TC)/sizeof(unsigned)); } }]; } + // Scalar single precision floating point register class.. def SPR : RegisterClass<"ARM", [f32], 32, [S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13, S14, S15, S16, S17, S18, S19, S20, S21, S22, @@ -294,11 +367,6 @@ def SPR_8 : RegisterClass<"ARM", [f32], 32, [S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13, S14, S15]>; -// Dummy f32 regclass to represent impossible subreg indices. -def SPR_INVALID : RegisterClass<"ARM", [f32], 32, [SDummy]> { - let CopyCost = -1; -} - // Scalar double precision floating point / generic 64-bit vector register // class. // ARM requires only word alignment for double. It's more performant if it @@ -308,33 +376,34 @@ def DPR : RegisterClass<"ARM", [f64, v8i8, v4i16, v2i32, v1i64, v2f32], 64, D8, D9, D10, D11, D12, D13, D14, D15, D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, D31]> { - let SubRegClassList = [SPR_INVALID, SPR_INVALID]; let MethodProtos = [{ iterator allocation_order_begin(const MachineFunction &MF) const; iterator allocation_order_end(const MachineFunction &MF) const; }]; let MethodBodies = [{ - // VFP2 + // VFP2 / VFPv3-D16 static const unsigned ARM_DPR_VFP2[] = { ARM::D0, ARM::D1, ARM::D2, ARM::D3, ARM::D4, ARM::D5, ARM::D6, ARM::D7, ARM::D8, ARM::D9, ARM::D10, ARM::D11, ARM::D12, ARM::D13, ARM::D14, ARM::D15 }; - // VFP3 + // VFP3: D8-D15 are callee saved and should be allocated last. + // Save other low registers for use as DPR_VFP2 and DPR_8 classes. static const unsigned ARM_DPR_VFP3[] = { - ARM::D0, ARM::D1, ARM::D2, ARM::D3, - ARM::D4, ARM::D5, ARM::D6, ARM::D7, - ARM::D8, ARM::D9, ARM::D10, ARM::D11, - ARM::D12, ARM::D13, ARM::D14, ARM::D15, ARM::D16, ARM::D17, ARM::D18, ARM::D19, ARM::D20, ARM::D21, ARM::D22, ARM::D23, ARM::D24, ARM::D25, ARM::D26, ARM::D27, - ARM::D28, ARM::D29, ARM::D30, ARM::D31 }; + ARM::D28, ARM::D29, ARM::D30, ARM::D31, + ARM::D0, ARM::D1, ARM::D2, ARM::D3, + ARM::D4, ARM::D5, ARM::D6, ARM::D7, + ARM::D8, ARM::D9, ARM::D10, ARM::D11, + ARM::D12, ARM::D13, ARM::D14, ARM::D15 }; + DPRClass::iterator DPRClass::allocation_order_begin(const MachineFunction &MF) const { const TargetMachine &TM = MF.getTarget(); const ARMSubtarget &Subtarget = TM.getSubtarget(); - if (Subtarget.hasVFP3()) + if (Subtarget.hasVFP3() && !Subtarget.hasD16()) return ARM_DPR_VFP3; return ARM_DPR_VFP2; } @@ -343,7 +412,7 @@ def DPR : RegisterClass<"ARM", [f64, v8i8, v4i16, v2i32, v1i64, v2f32], 64, DPRClass::allocation_order_end(const MachineFunction &MF) const { const TargetMachine &TM = MF.getTarget(); const ARMSubtarget &Subtarget = TM.getSubtarget(); - if (Subtarget.hasVFP3()) + if (Subtarget.hasVFP3() && !Subtarget.hasD16()) return ARM_DPR_VFP3 + (sizeof(ARM_DPR_VFP3)/sizeof(unsigned)); else return ARM_DPR_VFP2 + (sizeof(ARM_DPR_VFP2)/sizeof(unsigned)); @@ -356,55 +425,60 @@ def DPR : RegisterClass<"ARM", [f64, v8i8, v4i16, v2i32, v1i64, v2f32], 64, def DPR_VFP2 : RegisterClass<"ARM", [f64, v8i8, v4i16, v2i32, v1i64, v2f32], 64, [D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15]> { - let SubRegClassList = [SPR, SPR]; + let SubRegClasses = [(SPR ssub_0, ssub_1)]; } // Subset of DPR which can be used as a source of NEON scalars for 16-bit // operations def DPR_8 : RegisterClass<"ARM", [f64, v8i8, v4i16, v2i32, v1i64, v2f32], 64, [D0, D1, D2, D3, D4, D5, D6, D7]> { - let SubRegClassList = [SPR_8, SPR_8]; -} - -// Dummy 64-bit regclass to represent impossible subreg indices. -def DPR_INVALID : RegisterClass<"ARM", - [f64, v8i8, v4i16, v2i32, v1i64, v2f32], 64, - [DDummy]> { - let CopyCost = -1; + let SubRegClasses = [(SPR_8 ssub_0, ssub_1)]; } // Generic 128-bit vector register class. def QPR : RegisterClass<"ARM", [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], 128, [Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15]> { - let SubRegClassList = [SPR_INVALID, SPR_INVALID, SPR_INVALID, SPR_INVALID, - DPR, DPR, DPR_INVALID, DPR_INVALID, - DPR_INVALID, DPR_INVALID, DPR_INVALID, DPR_INVALID]; + let SubRegClasses = [(DPR dsub_0, dsub_1)]; + let MethodProtos = [{ + iterator allocation_order_begin(const MachineFunction &MF) const; + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + // Q4-Q7 are callee saved and should be allocated last. + // Save other low registers for use as QPR_VFP2 and QPR_8 classes. + static const unsigned ARM_QPR[] = { + ARM::Q8, ARM::Q9, ARM::Q10, ARM::Q11, + ARM::Q12, ARM::Q13, ARM::Q14, ARM::Q15, + ARM::Q0, ARM::Q1, ARM::Q2, ARM::Q3, + ARM::Q4, ARM::Q5, ARM::Q6, ARM::Q7 }; + + QPRClass::iterator + QPRClass::allocation_order_begin(const MachineFunction &MF) const { + return ARM_QPR; + } + + QPRClass::iterator + QPRClass::allocation_order_end(const MachineFunction &MF) const { + return ARM_QPR + (sizeof(ARM_QPR)/sizeof(unsigned)); + } + }]; } // Subset of QPR that have 32-bit SPR subregs. def QPR_VFP2 : RegisterClass<"ARM", [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], 128, [Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7]> { - let SubRegClassList = [SPR, SPR, SPR, SPR, - DPR_VFP2, DPR_VFP2, DPR_INVALID, DPR_INVALID, - DPR_INVALID, DPR_INVALID, DPR_INVALID, DPR_INVALID]; + let SubRegClasses = [(SPR ssub_0, ssub_1, ssub_2, ssub_3), + (DPR_VFP2 dsub_0, dsub_1)]; } // Subset of QPR that have DPR_8 and SPR_8 subregs. def QPR_8 : RegisterClass<"ARM", [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], 128, [Q0, Q1, Q2, Q3]> { - let SubRegClassList = [SPR_8, SPR_8, SPR_8, SPR_8, - DPR_8, DPR_8, DPR_INVALID, DPR_INVALID, - DPR_INVALID, DPR_INVALID, DPR_INVALID, DPR_INVALID]; -} - -// Dummy 128-bit regclass to represent impossible subreg indices. -def QPR_INVALID : RegisterClass<"ARM", - [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], 128, - [QDummy]> { - let CopyCost = -1; + let SubRegClasses = [(SPR_8 ssub_0, ssub_1, ssub_2, ssub_3), + (DPR_8 dsub_0, dsub_1)]; } // Pseudo 256-bit vector register class to model pairs of Q registers @@ -412,20 +486,39 @@ def QPR_INVALID : RegisterClass<"ARM", def QQPR : RegisterClass<"ARM", [v4i64], 256, [QQ0, QQ1, QQ2, QQ3, QQ4, QQ5, QQ6, QQ7]> { - let SubRegClassList = [SPR_INVALID, SPR_INVALID, SPR_INVALID, SPR_INVALID, - DPR, DPR, DPR, DPR, - DPR_INVALID, DPR_INVALID, DPR_INVALID, DPR_INVALID, - QPR, QPR, QPR_INVALID, QPR_INVALID]; + let SubRegClasses = [(DPR dsub_0, dsub_1, dsub_2, dsub_3), + (QPR qsub_0, qsub_1)]; + let MethodProtos = [{ + iterator allocation_order_begin(const MachineFunction &MF) const; + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + // QQ2-QQ3 are callee saved and should be allocated last. + // Save other low registers for use as QPR_VFP2 and QPR_8 classes. + static const unsigned ARM_QQPR[] = { + ARM::QQ4, ARM::QQ5, ARM::QQ6, ARM::QQ7, + ARM::QQ0, ARM::QQ1, ARM::QQ2, ARM::QQ3 }; + + QQPRClass::iterator + QQPRClass::allocation_order_begin(const MachineFunction &MF) const { + return ARM_QQPR; + } + + QQPRClass::iterator + QQPRClass::allocation_order_end(const MachineFunction &MF) const { + return ARM_QQPR + (sizeof(ARM_QQPR)/sizeof(unsigned)); + } + }]; } // Subset of QQPR that have 32-bit SPR subregs. def QQPR_VFP2 : RegisterClass<"ARM", [v4i64], 256, [QQ0, QQ1, QQ2, QQ3]> { - let SubRegClassList = [SPR, SPR, SPR, SPR, - DPR_VFP2, DPR_VFP2, DPR_VFP2, DPR_VFP2, - DPR_INVALID, DPR_INVALID, DPR_INVALID, DPR_INVALID, - QPR_VFP2, QPR_VFP2, QPR_INVALID, QPR_INVALID]; + let SubRegClasses = [(SPR ssub_0, ssub_1, ssub_2, ssub_3), + (DPR_VFP2 dsub_0, dsub_1, dsub_2, dsub_3), + (QPR_VFP2 qsub_0, qsub_1)]; + } // Pseudo 512-bit vector register class to model 4 consecutive Q registers @@ -433,133 +526,30 @@ def QQPR_VFP2 : RegisterClass<"ARM", [v4i64], def QQQQPR : RegisterClass<"ARM", [v8i64], 256, [QQQQ0, QQQQ1, QQQQ2, QQQQ3]> { - let SubRegClassList = [SPR_INVALID, SPR_INVALID, SPR_INVALID, SPR_INVALID, - DPR, DPR, DPR, DPR, DPR, DPR, DPR, DPR, - QPR, QPR, QPR, QPR]; + let SubRegClasses = [(DPR dsub_0, dsub_1, dsub_2, dsub_3, + dsub_4, dsub_5, dsub_6, dsub_7), + (QPR qsub_0, qsub_1, qsub_2, qsub_3)]; + let MethodProtos = [{ + iterator allocation_order_begin(const MachineFunction &MF) const; + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + // QQQQ1 is callee saved and should be allocated last. + // Save QQQQ0 for use as QPR_VFP2 and QPR_8 classes. + static const unsigned ARM_QQQQPR[] = { + ARM::QQQQ2, ARM::QQQQ3, ARM::QQQQ0, ARM::QQQQ1 }; + + QQQQPRClass::iterator + QQQQPRClass::allocation_order_begin(const MachineFunction &MF) const { + return ARM_QQQQPR; + } + + QQQQPRClass::iterator + QQQQPRClass::allocation_order_end(const MachineFunction &MF) const { + return ARM_QQQQPR + (sizeof(ARM_QQQQPR)/sizeof(unsigned)); + } + }]; } // Condition code registers. def CCR : RegisterClass<"ARM", [i32], 32, [CPSR]>; - -//===----------------------------------------------------------------------===// -// Subregister Set Definitions... now that we have all of the pieces, define the -// sub registers for each register. -// - -def arm_ssubreg_0 : PatLeaf<(i32 1)>; -def arm_ssubreg_1 : PatLeaf<(i32 2)>; -def arm_ssubreg_2 : PatLeaf<(i32 3)>; -def arm_ssubreg_3 : PatLeaf<(i32 4)>; - -def arm_dsubreg_0 : PatLeaf<(i32 5)>; -def arm_dsubreg_1 : PatLeaf<(i32 6)>; -def arm_dsubreg_2 : PatLeaf<(i32 7)>; -def arm_dsubreg_3 : PatLeaf<(i32 8)>; -def arm_dsubreg_4 : PatLeaf<(i32 9)>; -def arm_dsubreg_5 : PatLeaf<(i32 10)>; -def arm_dsubreg_6 : PatLeaf<(i32 11)>; -def arm_dsubreg_7 : PatLeaf<(i32 12)>; - -def arm_qsubreg_0 : PatLeaf<(i32 13)>; -def arm_qsubreg_1 : PatLeaf<(i32 14)>; -def arm_qsubreg_2 : PatLeaf<(i32 15)>; -def arm_qsubreg_3 : PatLeaf<(i32 16)>; - -def arm_qqsubreg_0 : PatLeaf<(i32 17)>; -def arm_qqsubreg_1 : PatLeaf<(i32 18)>; - - -// S sub-registers of D registers. -def : SubRegSet<1, [D0, D1, D2, D3, D4, D5, D6, D7, - D8, D9, D10, D11, D12, D13, D14, D15], - [S0, S2, S4, S6, S8, S10, S12, S14, - S16, S18, S20, S22, S24, S26, S28, S30]>; -def : SubRegSet<2, [D0, D1, D2, D3, D4, D5, D6, D7, - D8, D9, D10, D11, D12, D13, D14, D15], - [S1, S3, S5, S7, S9, S11, S13, S15, - S17, S19, S21, S23, S25, S27, S29, S31]>; - -// S sub-registers of Q registers. -def : SubRegSet<1, [Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7], - [S0, S4, S8, S12, S16, S20, S24, S28]>; -def : SubRegSet<2, [Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7], - [S1, S5, S9, S13, S17, S21, S25, S29]>; -def : SubRegSet<3, [Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7], - [S2, S6, S10, S14, S18, S22, S26, S30]>; -def : SubRegSet<4, [Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7], - [S3, S7, S11, S15, S19, S23, S27, S31]>; - -// D sub-registers of Q registers. -def : SubRegSet<5, [Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, - Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15], - [D0, D2, D4, D6, D8, D10, D12, D14, - D16, D18, D20, D22, D24, D26, D28, D30]>; -def : SubRegSet<6, [Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, - Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15], - [D1, D3, D5, D7, D9, D11, D13, D15, - D17, D19, D21, D23, D25, D27, D29, D31]>; - -// S sub-registers of QQ registers. Note there are no sub-indices -// for referencing S4 - S7, S12 - S15, and S20 - S23. It doesn't -// look like we need them. -def : SubRegSet<1, [QQ0, QQ1, QQ2, QQ3], - [S0, S8, S16, S24]>; -def : SubRegSet<2, [QQ0, QQ1, QQ2, QQ3], - [S1, S9, S17, S25]>; -def : SubRegSet<3, [QQ0, QQ1, QQ2, QQ3], - [S2, S10, S18, S26]>; -def : SubRegSet<4, [QQ0, QQ1, QQ2, QQ3], - [S3, S11, S19, S27]>; - -// D sub-registers of QQ registers. -def : SubRegSet<5, [QQ0, QQ1, QQ2, QQ3, QQ4, QQ5, QQ6, QQ7], - [D0, D4, D8, D12, D16, D20, D24, D28]>; -def : SubRegSet<6, [QQ0, QQ1, QQ2, QQ3, QQ4, QQ5, QQ6, QQ7], - [D1, D5, D9, D13, D17, D21, D25, D29]>; -def : SubRegSet<7, [QQ0, QQ1, QQ2, QQ3, QQ4, QQ5, QQ6, QQ7], - [D2, D6, D10, D14, D18, D22, D26, D30]>; -def : SubRegSet<8, [QQ0, QQ1, QQ2, QQ3, QQ4, QQ5, QQ6, QQ7], - [D3, D7, D11, D15, D19, D23, D27, D31]>; - -// Q sub-registers of QQ registers. -def : SubRegSet<13, [QQ0, QQ1, QQ2, QQ3, QQ4, QQ5, QQ6, QQ7], - [Q0, Q2, Q4, Q6, Q8, Q10, Q12, Q14]>; -def : SubRegSet<14,[QQ0, QQ1, QQ2, QQ3, QQ4, QQ5, QQ6, QQ7], - [Q1, Q3, Q5, Q7, Q9, Q11, Q13, Q15]>; - - -// D sub-registers of QQQQ registers. -def : SubRegSet<5, [QQQQ0, QQQQ1, QQQQ2, QQQQ3], - [D0, D8, D16, D24]>; -def : SubRegSet<6, [QQQQ0, QQQQ1, QQQQ2, QQQQ3], - [D1, D9, D17, D25]>; -def : SubRegSet<7, [QQQQ0, QQQQ1, QQQQ2, QQQQ3], - [D2, D10, D18, D26]>; -def : SubRegSet<8, [QQQQ0, QQQQ1, QQQQ2, QQQQ3], - [D3, D11, D19, D27]>; - -def : SubRegSet<9, [QQQQ0, QQQQ1, QQQQ2, QQQQ3], - [D4, D12, D20, D28]>; -def : SubRegSet<10, [QQQQ0, QQQQ1, QQQQ2, QQQQ3], - [D5, D13, D21, D29]>; -def : SubRegSet<11, [QQQQ0, QQQQ1, QQQQ2, QQQQ3], - [D6, D14, D22, D30]>; -def : SubRegSet<12, [QQQQ0, QQQQ1, QQQQ2, QQQQ3], - [D7, D15, D23, D31]>; - -// Q sub-registers of QQQQQQQQ registers. -def : SubRegSet<13, [QQQQ0, QQQQ1, QQQQ2, QQQQ3], - [Q0, Q4, Q8, Q12]>; -def : SubRegSet<14, [QQQQ0, QQQQ1, QQQQ2, QQQQ3], - [Q1, Q5, Q9, Q13]>; -def : SubRegSet<15, [QQQQ0, QQQQ1, QQQQ2, QQQQ3], - [Q2, Q6, Q10, Q14]>; -def : SubRegSet<16, [QQQQ0, QQQQ1, QQQQ2, QQQQ3], - [Q3, Q7, Q11, Q15]>; - -// QQ sub-registers of QQQQQQQQ registers. -def : SubRegSet<17, [QQQQ0, QQQQ1, QQQQ2, QQQQ3], - [QQ0, QQ2, QQ4, QQ6]>; -def : SubRegSet<18, [QQQQ0, QQQQ1, QQQQ2, QQQQ3], - [QQ1, QQ3, QQ5, QQ7]>; -