aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/ARM/ARMRegisterInfo.cpp
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2009-06-15 08:28:29 +0000
committerEvan Cheng <evan.cheng@apple.com>2009-06-15 08:28:29 +0000
commit358dec51804ee52e47ea3a47c9248086e458ad7c (patch)
tree55cae00b3830a7107f21212681aec06a9a79dc4f /lib/Target/ARM/ARMRegisterInfo.cpp
parentd3b295c23fe945c992e7ffc29962248a0e573ea2 (diff)
Part 1.
- Change register allocation hint to a pair of unsigned integers. The hint type is zero (which means prefer the register specified as second part of the pair) or entirely target dependent. - Allow targets to specify alternative register allocation orders based on allocation hint. Part 2. - Use the register allocation hint system to implement more aggressive load / store multiple formation. - Aggressively form LDRD / STRD. These are formed *before* register allocation. It has to be done this way to shorten live interval of base and offset registers. e.g. v1025 = LDR v1024, 0 v1026 = LDR v1024, 0 => v1025,v1026 = LDRD v1024, 0 If this transformation isn't done before allocation, v1024 will overlap v1025 which means it more difficult to allocate a register pair. - Even with the register allocation hint, it may not be possible to get the desired allocation. In that case, the post-allocation load / store multiple pass must fix the ldrd / strd instructions. They can either become ldm / stm instructions or back to a pair of ldr / str instructions. This is work in progress, not yet enabled. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@73381 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/ARM/ARMRegisterInfo.cpp')
-rw-r--r--lib/Target/ARM/ARMRegisterInfo.cpp305
1 files changed, 301 insertions, 4 deletions
diff --git a/lib/Target/ARM/ARMRegisterInfo.cpp b/lib/Target/ARM/ARMRegisterInfo.cpp
index 199858f525..d06da67a5f 100644
--- a/lib/Target/ARM/ARMRegisterInfo.cpp
+++ b/lib/Target/ARM/ARMRegisterInfo.cpp
@@ -194,10 +194,6 @@ void ARMRegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB,
.addReg(0).addImm(0).addImm(Pred).addReg(PredReg);
}
-const TargetRegisterClass *ARMRegisterInfo::getPointerRegClass() const {
- return &ARM::GPRRegClass;
-}
-
/// isLowRegister - Returns true if the register is low register r0-r7.
///
bool ARMRegisterInfo::isLowRegister(unsigned Reg) const {
@@ -304,6 +300,159 @@ ARMRegisterInfo::isReservedReg(const MachineFunction &MF, unsigned Reg) const {
return false;
}
+const TargetRegisterClass *ARMRegisterInfo::getPointerRegClass() const {
+ return &ARM::GPRRegClass;
+}
+
+/// getAllocationOrder - Returns the register allocation order for a specified
+/// register class in the form of a pair of TargetRegisterClass iterators.
+std::pair<TargetRegisterClass::iterator,TargetRegisterClass::iterator>
+ARMRegisterInfo::getAllocationOrder(const TargetRegisterClass *RC,
+ std::pair<unsigned, unsigned> Hint,
+ const MachineFunction &MF) const {
+ // Alternative register allocation orders when favoring even / odd registers
+ // of register pairs.
+
+ // No FP, R9 is available.
+ static const unsigned GPREven1[] = {
+ ARM::R0, ARM::R2, ARM::R4, ARM::R6, ARM::R8, ARM::R10,
+ ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R7,
+ ARM::R9, ARM::R11
+ };
+ static const unsigned GPROdd1[] = {
+ ARM::R1, ARM::R3, ARM::R5, ARM::R7, ARM::R9, ARM::R11,
+ ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6,
+ ARM::R8, ARM::R10
+ };
+
+ // FP is R7, R9 is available.
+ static const unsigned GPREven2[] = {
+ ARM::R0, ARM::R2, ARM::R4, ARM::R8, ARM::R10,
+ ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R6,
+ ARM::R9, ARM::R11
+ };
+ static const unsigned GPROdd2[] = {
+ ARM::R1, ARM::R3, ARM::R5, ARM::R9, ARM::R11,
+ ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6,
+ ARM::R8, ARM::R10
+ };
+
+ // FP is R11, R9 is available.
+ static const unsigned GPREven3[] = {
+ ARM::R0, ARM::R2, ARM::R4, ARM::R6, ARM::R8,
+ ARM::R1, ARM::R3, ARM::R10,ARM::R12,ARM::LR, ARM::R5, ARM::R7,
+ ARM::R9
+ };
+ static const unsigned GPROdd3[] = {
+ ARM::R1, ARM::R3, ARM::R5, ARM::R6, ARM::R9,
+ ARM::R0, ARM::R2, ARM::R10,ARM::R12,ARM::LR, ARM::R4, ARM::R7,
+ ARM::R8
+ };
+
+ // No FP, R9 is not available.
+ static const unsigned GPREven4[] = {
+ ARM::R0, ARM::R2, ARM::R4, ARM::R6, ARM::R10,
+ ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R7, ARM::R8,
+ ARM::R11
+ };
+ static const unsigned GPROdd4[] = {
+ ARM::R1, ARM::R3, ARM::R5, ARM::R7, ARM::R11,
+ ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6, ARM::R8,
+ ARM::R10
+ };
+
+ // FP is R7, R9 is not available.
+ static const unsigned GPREven5[] = {
+ ARM::R0, ARM::R2, ARM::R4, ARM::R10,
+ ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R6, ARM::R8,
+ ARM::R11
+ };
+ static const unsigned GPROdd5[] = {
+ ARM::R1, ARM::R3, ARM::R5, ARM::R11,
+ ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6, ARM::R8,
+ ARM::R10
+ };
+
+ // FP is R11, R9 is not available.
+ static const unsigned GPREven6[] = {
+ ARM::R0, ARM::R2, ARM::R4, ARM::R6,
+ ARM::R1, ARM::R3, ARM::R10,ARM::R12,ARM::LR, ARM::R5, ARM::R7, ARM::R8
+ };
+ static const unsigned GPROdd6[] = {
+ ARM::R1, ARM::R3, ARM::R5, ARM::R7,
+ ARM::R0, ARM::R2, ARM::R10,ARM::R12,ARM::LR, ARM::R4, ARM::R6, ARM::R8
+ };
+
+
+ if (Hint.first == ARMRI::RegPairEven) {
+ if (!hasFP(MF)) {
+ if (!STI.isR9Reserved())
+ return std::make_pair(GPREven1,
+ GPREven1 + (sizeof(GPREven1)/sizeof(unsigned)));
+ else
+ return std::make_pair(GPREven4,
+ GPREven4 + (sizeof(GPREven4)/sizeof(unsigned)));
+ } else if (FramePtr == ARM::R7) {
+ if (!STI.isR9Reserved())
+ return std::make_pair(GPREven2,
+ GPREven2 + (sizeof(GPREven2)/sizeof(unsigned)));
+ else
+ return std::make_pair(GPREven5,
+ GPREven5 + (sizeof(GPREven5)/sizeof(unsigned)));
+ } else { // FramePtr == ARM::R11
+ if (!STI.isR9Reserved())
+ return std::make_pair(GPREven3,
+ GPREven3 + (sizeof(GPREven3)/sizeof(unsigned)));
+ else
+ return std::make_pair(GPREven6,
+ GPREven6 + (sizeof(GPREven6)/sizeof(unsigned)));
+ }
+ } else if (Hint.first == ARMRI::RegPairOdd) {
+ if (!hasFP(MF)) {
+ if (!STI.isR9Reserved())
+ return std::make_pair(GPROdd1,
+ GPROdd1 + (sizeof(GPROdd1)/sizeof(unsigned)));
+ else
+ return std::make_pair(GPROdd4,
+ GPROdd4 + (sizeof(GPROdd4)/sizeof(unsigned)));
+ } else if (FramePtr == ARM::R7) {
+ if (!STI.isR9Reserved())
+ return std::make_pair(GPROdd2,
+ GPROdd2 + (sizeof(GPROdd2)/sizeof(unsigned)));
+ else
+ return std::make_pair(GPROdd5,
+ GPROdd5 + (sizeof(GPROdd5)/sizeof(unsigned)));
+ } else { // FramePtr == ARM::R11
+ if (!STI.isR9Reserved())
+ return std::make_pair(GPROdd3,
+ GPROdd3 + (sizeof(GPROdd3)/sizeof(unsigned)));
+ else
+ return std::make_pair(GPROdd6,
+ GPROdd6 + (sizeof(GPROdd6)/sizeof(unsigned)));
+ }
+ }
+ return std::make_pair(RC->allocation_order_begin(MF),
+ RC->allocation_order_end(MF));
+}
+
+/// ResolveRegAllocHint - Resolves the specified register allocation hint
+/// to a physical register. Returns the physical register if it is successful.
+unsigned
+ARMRegisterInfo::ResolveRegAllocHint(unsigned Type, unsigned Reg,
+ const MachineFunction &MF) const {
+ if (Reg == 0 || !isPhysicalRegister(Reg))
+ return 0;
+ if (Type == 0)
+ return Reg;
+ else if (Type == (unsigned)ARMRI::RegPairOdd)
+ // Odd register.
+ return getRegisterPairOdd(Reg, MF);
+ else if (Type == (unsigned)ARMRI::RegPairEven)
+ // Even register.
+ return getRegisterPairEven(Reg, MF);
+ return 0;
+}
+
bool
ARMRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const {
const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
@@ -1525,4 +1674,152 @@ int ARMRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
return ARMGenRegisterInfo::getDwarfRegNumFull(RegNum, 0);
}
+unsigned ARMRegisterInfo::getRegisterPairEven(unsigned Reg,
+ const MachineFunction &MF) const {
+ switch (Reg) {
+ default: break;
+ // Return 0 if either register of the pair is a special register.
+ // So no R12, etc.
+ case ARM::R0: case ARM::R1:
+ return ARM::R0;
+ case ARM::R2: case ARM::R3:
+ // FIXME!
+ return STI.isThumb() ? 0 : ARM::R2;
+ case ARM::R4: case ARM::R5:
+ return ARM::R4;
+ case ARM::R6: case ARM::R7:
+ return isReservedReg(MF, ARM::R7) ? 0 : ARM::R6;
+ case ARM::R8: case ARM::R9:
+ return isReservedReg(MF, ARM::R9) ? 0 :ARM::R8;
+ case ARM::R10: case ARM::R11:
+ return isReservedReg(MF, ARM::R11) ? 0 : ARM::R10;
+
+ case ARM::S0: case ARM::S1:
+ return ARM::S0;
+ case ARM::S2: case ARM::S3:
+ return ARM::S2;
+ case ARM::S4: case ARM::S5:
+ return ARM::S4;
+ case ARM::S6: case ARM::S7:
+ return ARM::S6;
+ case ARM::S8: case ARM::S9:
+ return ARM::S8;
+ case ARM::S10: case ARM::S11:
+ return ARM::S10;
+ case ARM::S12: case ARM::S13:
+ return ARM::S12;
+ case ARM::S14: case ARM::S15:
+ return ARM::S14;
+ case ARM::S16: case ARM::S17:
+ return ARM::S16;
+ case ARM::S18: case ARM::S19:
+ return ARM::S18;
+ case ARM::S20: case ARM::S21:
+ return ARM::S20;
+ case ARM::S22: case ARM::S23:
+ return ARM::S22;
+ case ARM::S24: case ARM::S25:
+ return ARM::S24;
+ case ARM::S26: case ARM::S27:
+ return ARM::S26;
+ case ARM::S28: case ARM::S29:
+ return ARM::S28;
+ case ARM::S30: case ARM::S31:
+ return ARM::S30;
+
+ case ARM::D0: case ARM::D1:
+ return ARM::D0;
+ case ARM::D2: case ARM::D3:
+ return ARM::D2;
+ case ARM::D4: case ARM::D5:
+ return ARM::D4;
+ case ARM::D6: case ARM::D7:
+ return ARM::D6;
+ case ARM::D8: case ARM::D9:
+ return ARM::D8;
+ case ARM::D10: case ARM::D11:
+ return ARM::D10;
+ case ARM::D12: case ARM::D13:
+ return ARM::D12;
+ case ARM::D14: case ARM::D15:
+ return ARM::D14;
+ }
+
+ return 0;
+}
+
+unsigned ARMRegisterInfo::getRegisterPairOdd(unsigned Reg,
+ const MachineFunction &MF) const {
+ switch (Reg) {
+ default: break;
+ // Return 0 if either register of the pair is a special register.
+ // So no R12, etc.
+ case ARM::R0: case ARM::R1:
+ return ARM::R1;
+ case ARM::R2: case ARM::R3:
+ // FIXME!
+ return STI.isThumb() ? 0 : ARM::R3;
+ case ARM::R4: case ARM::R5:
+ return ARM::R5;
+ case ARM::R6: case ARM::R7:
+ return isReservedReg(MF, ARM::R7) ? 0 : ARM::R7;
+ case ARM::R8: case ARM::R9:
+ return isReservedReg(MF, ARM::R9) ? 0 :ARM::R9;
+ case ARM::R10: case ARM::R11:
+ return isReservedReg(MF, ARM::R11) ? 0 : ARM::R11;
+
+ case ARM::S0: case ARM::S1:
+ return ARM::S1;
+ case ARM::S2: case ARM::S3:
+ return ARM::S3;
+ case ARM::S4: case ARM::S5:
+ return ARM::S5;
+ case ARM::S6: case ARM::S7:
+ return ARM::S7;
+ case ARM::S8: case ARM::S9:
+ return ARM::S9;
+ case ARM::S10: case ARM::S11:
+ return ARM::S11;
+ case ARM::S12: case ARM::S13:
+ return ARM::S13;
+ case ARM::S14: case ARM::S15:
+ return ARM::S15;
+ case ARM::S16: case ARM::S17:
+ return ARM::S17;
+ case ARM::S18: case ARM::S19:
+ return ARM::S19;
+ case ARM::S20: case ARM::S21:
+ return ARM::S21;
+ case ARM::S22: case ARM::S23:
+ return ARM::S23;
+ case ARM::S24: case ARM::S25:
+ return ARM::S25;
+ case ARM::S26: case ARM::S27:
+ return ARM::S27;
+ case ARM::S28: case ARM::S29:
+ return ARM::S29;
+ case ARM::S30: case ARM::S31:
+ return ARM::S31;
+
+ case ARM::D0: case ARM::D1:
+ return ARM::D1;
+ case ARM::D2: case ARM::D3:
+ return ARM::D3;
+ case ARM::D4: case ARM::D5:
+ return ARM::D5;
+ case ARM::D6: case ARM::D7:
+ return ARM::D7;
+ case ARM::D8: case ARM::D9:
+ return ARM::D9;
+ case ARM::D10: case ARM::D11:
+ return ARM::D11;
+ case ARM::D12: case ARM::D13:
+ return ARM::D13;
+ case ARM::D14: case ARM::D15:
+ return ARM::D15;
+ }
+
+ return 0;
+}
+
#include "ARMGenRegisterInfo.inc"