Switch ARM to using AltOrders instead of MethodBodies.

This slightly changes the GPR allocation order on Darwin where R9 is not
a callee-saved register:

Before: %R0 %R1 %R2 %R3 %R12 %R9 %LR %R4 %R5 %R6 %R8 %R10 %R11
After:  %R0 %R1 %R2 %R3 %R9 %R12 %LR %R4 %R5 %R6 %R8 %R10 %R11
llvm-svn: 133326
This commit is contained in:
Jakob Stoklund Olesen 2011-06-18 01:14:46 +00:00
parent 3337f7d50a
commit 831ae0105a
2 changed files with 27 additions and 224 deletions

View File

@ -202,42 +202,14 @@ def FPEXC : ARMReg<8, "fpexc">;
//
def GPR : RegisterClass<"ARM", [i32], 32, (add (sequence "R%u", 0, 12),
SP, LR, PC)> {
let MethodProtos = [{
iterator allocation_order_begin(const MachineFunction &MF) const;
iterator allocation_order_end(const MachineFunction &MF) const;
}];
let MethodBodies = [{
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::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_GPR_AO[] = {
ARM::R0, ARM::R1, ARM::R2, ARM::R3,
ARM::R4, ARM::R5, ARM::R6, ARM::R7 };
GPRClass::iterator
GPRClass::allocation_order_begin(const MachineFunction &MF) const {
const TargetMachine &TM = MF.getTarget();
const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
if (Subtarget.isThumb1Only())
return THUMB_GPR_AO;
return ARM_GPR_AO;
}
GPRClass::iterator
GPRClass::allocation_order_end(const MachineFunction &MF) const {
const TargetMachine &TM = MF.getTarget();
const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
if (Subtarget.isThumb1Only())
return THUMB_GPR_AO + (sizeof(THUMB_GPR_AO)/sizeof(unsigned));
return ARM_GPR_AO + (sizeof(ARM_GPR_AO)/sizeof(unsigned));
}
// Allocate LR as the first CSR since it is always saved anyway.
// 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.
let AltOrders = [(add LR, GPR), (trunc GPR, 8)];
let AltOrderSelect = [{
return 1 + MF.getTarget().getSubtarget<ARMSubtarget>().isThumb1Only();
}];
}
@ -246,44 +218,9 @@ def GPR : RegisterClass<"ARM", [i32], 32, (add (sequence "R%u", 0, 12),
// or SP (R13 or R15) are used. The ARM ISA refers to these operands
// via the BadReg() pseudo-code description.
def rGPR : RegisterClass<"ARM", [i32], 32, (sub GPR, SP, PC)> {
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<ARMSubtarget>();
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<ARMSubtarget>();
if (Subtarget.isThumb1Only())
return THUMB_rGPR_AO + (sizeof(THUMB_rGPR_AO)/sizeof(unsigned));
return ARM_rGPR_AO + (sizeof(ARM_rGPR_AO)/sizeof(unsigned));
}
let AltOrders = [(add LR, rGPR), (trunc rGPR, 8)];
let AltOrderSelect = [{
return 1 + MF.getTarget().getSubtarget<ARMSubtarget>().isThumb1Only();
}];
}
@ -296,52 +233,12 @@ def tGPR : RegisterClass<"ARM", [i32], 32, (trunc GPR, 8)>;
// 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, (add 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 = [{
// R9 is available.
static const unsigned ARM_GPR_R9_TC[] = {
ARM::R0, ARM::R1, ARM::R2, ARM::R3,
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 };
// 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<ARMSubtarget>();
if (Subtarget.isThumb1Only())
return THUMB_GPR_AO_TC;
return Subtarget.isTargetDarwin() ? ARM_GPR_R9_TC : ARM_GPR_NOR9_TC;
}
tcGPRClass::iterator
tcGPRClass::allocation_order_end(const MachineFunction &MF) const {
const TargetMachine &TM = MF.getTarget();
const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
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));
}
let AltOrders = [(and tcGPR, tGPR)];
let AltOrderSelect = [{
return MF.getTarget().getSubtarget<ARMSubtarget>().isThumb1Only();
}];
}
// Scalar single precision floating point register class..
def SPR : RegisterClass<"ARM", [f32], 32, (sequence "S%u", 0, 31)>;
@ -355,48 +252,9 @@ def SPR_8 : RegisterClass<"ARM", [f32], 32, (trunc SPR, 16)>;
// is double-word alignment though.
def DPR : RegisterClass<"ARM", [f64, v8i8, v4i16, v2i32, v1i64, v2f32], 64,
(sequence "D%u", 0, 31)> {
let MethodProtos = [{
iterator allocation_order_begin(const MachineFunction &MF) const;
iterator allocation_order_end(const MachineFunction &MF) const;
}];
let MethodBodies = [{
// 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: 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::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::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<ARMSubtarget>();
if (Subtarget.hasVFP3() && !Subtarget.hasD16())
return ARM_DPR_VFP3;
return ARM_DPR_VFP2;
}
DPRClass::iterator
DPRClass::allocation_order_end(const MachineFunction &MF) const {
const TargetMachine &TM = MF.getTarget();
const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
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));
}
}];
// Allocate non-VFP2 registers D16-D31 first.
let AltOrders = [(rotl DPR, 16)];
let AltOrderSelect = [{ return 1; }];
}
// Subset of DPR that are accessible with VFP2 (and so that also have
@ -417,29 +275,9 @@ def DPR_8 : RegisterClass<"ARM", [f64, v8i8, v4i16, v2i32, v1i64, v2f32], 64,
def QPR : RegisterClass<"ARM", [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64], 128,
(sequence "Q%u", 0, 15)> {
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));
}
}];
// Allocate non-VFP2 aliases Q8-Q15 first.
let AltOrders = [(rotl QPR, 8)];
let AltOrderSelect = [{ return 1; }];
}
// Subset of QPR that have 32-bit SPR subregs.
@ -461,27 +299,9 @@ def QPR_8 : RegisterClass<"ARM", [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64],
def QQPR : RegisterClass<"ARM", [v4i64], 256, (sequence "QQ%u", 0, 7)> {
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));
}
}];
// Allocate non-VFP2 aliases first.
let AltOrders = [(rotl QQPR, 4)];
let AltOrderSelect = [{ return 1; }];
}
// Subset of QQPR that have 32-bit SPR subregs.
@ -498,26 +318,9 @@ def QQQQPR : RegisterClass<"ARM", [v8i64], 256, (sequence "QQQQ%u", 0, 3)> {
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));
}
}];
// Allocate non-VFP2 aliases first.
let AltOrders = [(rotl QQQQPR, 2)];
let AltOrderSelect = [{ return 1; }];
}
// Condition code registers.

View File

@ -22,7 +22,7 @@
define %union.rec* @Manifest(%union.rec* %x, %union.rec* %env, %struct.STYLE* %style, %union.rec** %bthr, %union.rec** %fthr, %union.rec** %target, %union.rec** %crs, i32 %ok, i32 %need_expand, %union.rec** %enclose, i32 %fcr) nounwind {
entry:
; CHECK: ldr.w {{(r[0-9]+)|(lr)}}, [r7, #28]
; CHECK: ldr{{(.w)?}} {{(r[0-9]+)|(lr)}}, [r7, #28]
%xgaps.i = alloca [32 x %union.rec*], align 4 ; <[32 x %union.rec*]*> [#uses=0]
%ycomp.i = alloca [32 x %union.rec*], align 4 ; <[32 x %union.rec*]*> [#uses=0]
br label %bb20