Fix ARM hasFP() semantics. It should return true whenever FP register is

reserved, not available for general allocation. This eliminates all the
extra checks for Darwin.

This change also fixes the use of FP to access frame indices in leaf
functions and cleaned up some confusing code in epilogue emission.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@110655 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2010-08-10 06:26:49 +00:00
parent 94f7950e4d
commit c9aed19747
6 changed files with 90 additions and 70 deletions

View File

@ -177,7 +177,7 @@ getReservedRegs(const MachineFunction &MF) const {
Reserved.set(ARM::SP); Reserved.set(ARM::SP);
Reserved.set(ARM::PC); Reserved.set(ARM::PC);
Reserved.set(ARM::FPSCR); Reserved.set(ARM::FPSCR);
if (STI.isTargetDarwin() || hasFP(MF)) if (hasFP(MF))
Reserved.set(FramePtr); Reserved.set(FramePtr);
// Some targets reserve R9. // Some targets reserve R9.
if (STI.isR9Reserved()) if (STI.isR9Reserved())
@ -194,7 +194,7 @@ bool ARMBaseRegisterInfo::isReservedReg(const MachineFunction &MF,
return true; return true;
case ARM::R7: case ARM::R7:
case ARM::R11: case ARM::R11:
if (FramePtr == Reg && (STI.isTargetDarwin() || hasFP(MF))) if (FramePtr == Reg && hasFP(MF))
return true; return true;
break; break;
case ARM::R9: case ARM::R9:
@ -511,7 +511,7 @@ ARMBaseRegisterInfo::getAllocationOrder(const TargetRegisterClass *RC,
return std::make_pair(RC->allocation_order_begin(MF), return std::make_pair(RC->allocation_order_begin(MF),
RC->allocation_order_end(MF)); RC->allocation_order_end(MF));
if (!STI.isTargetDarwin() && !hasFP(MF)) { if (!hasFP(MF)) {
if (!STI.isR9Reserved()) if (!STI.isR9Reserved())
return std::make_pair(GPREven1, return std::make_pair(GPREven1,
GPREven1 + (sizeof(GPREven1)/sizeof(unsigned))); GPREven1 + (sizeof(GPREven1)/sizeof(unsigned)));
@ -540,7 +540,7 @@ ARMBaseRegisterInfo::getAllocationOrder(const TargetRegisterClass *RC,
return std::make_pair(RC->allocation_order_begin(MF), return std::make_pair(RC->allocation_order_begin(MF),
RC->allocation_order_end(MF)); RC->allocation_order_end(MF));
if (!STI.isTargetDarwin() && !hasFP(MF)) { if (!hasFP(MF)) {
if (!STI.isR9Reserved()) if (!STI.isR9Reserved())
return std::make_pair(GPROdd1, return std::make_pair(GPROdd1,
GPROdd1 + (sizeof(GPROdd1)/sizeof(unsigned))); GPROdd1 + (sizeof(GPROdd1)/sizeof(unsigned)));
@ -610,6 +610,10 @@ ARMBaseRegisterInfo::UpdateRegAllocHint(unsigned Reg, unsigned NewReg,
/// or if frame pointer elimination is disabled. /// or if frame pointer elimination is disabled.
/// ///
bool ARMBaseRegisterInfo::hasFP(const MachineFunction &MF) const { bool ARMBaseRegisterInfo::hasFP(const MachineFunction &MF) const {
// Mac OS X requires FP not to be clobbered for backtracing purpose.
if (STI.isTargetDarwin())
return true;
const MachineFrameInfo *MFI = MF.getFrameInfo(); const MachineFrameInfo *MFI = MF.getFrameInfo();
// Always eliminate non-leaf frame pointers. // Always eliminate non-leaf frame pointers.
return ((DisableFramePointerElim(MF) && MFI->hasCalls()) || return ((DisableFramePointerElim(MF) && MFI->hasCalls()) ||
@ -683,6 +687,7 @@ static unsigned estimateStackSize(MachineFunction &MF) {
/// instructions will require a scratch register during their expansion later. /// instructions will require a scratch register during their expansion later.
unsigned unsigned
ARMBaseRegisterInfo::estimateRSStackSizeLimit(MachineFunction &MF) const { ARMBaseRegisterInfo::estimateRSStackSizeLimit(MachineFunction &MF) const {
const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
unsigned Limit = (1 << 12) - 1; unsigned Limit = (1 << 12) - 1;
for (MachineFunction::iterator BB = MF.begin(),E = MF.end(); BB != E; ++BB) { for (MachineFunction::iterator BB = MF.begin(),E = MF.end(); BB != E; ++BB) {
for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end(); for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end();
@ -708,7 +713,10 @@ ARMBaseRegisterInfo::estimateRSStackSizeLimit(MachineFunction &MF) const {
Limit = std::min(Limit, ((1U << 8) - 1) * 4); Limit = std::min(Limit, ((1U << 8) - 1) * 4);
break; break;
case ARMII::AddrModeT2_i12: case ARMII::AddrModeT2_i12:
if (hasFP(MF)) Limit = std::min(Limit, (1U << 8) - 1); // i12 supports only positive offset so these will be converted to
// i8 opcodes. See llvm::rewriteT2FrameIndex.
if (hasFP(MF) && AFI->hasStackFrame())
Limit = std::min(Limit, (1U << 8) - 1);
break; break;
case ARMII::AddrMode6: case ARMII::AddrMode6:
// Addressing mode 6 (load/store) instructions can't encode an // Addressing mode 6 (load/store) instructions can't encode an
@ -860,8 +868,9 @@ ARMBaseRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
// and which instructions will need a scratch register for them. Is it // and which instructions will need a scratch register for them. Is it
// worth the effort and added fragility? // worth the effort and added fragility?
bool BigStack = bool BigStack =
(RS && (estimateStackSize(MF) + (hasFP(MF) ? 4:0) >= (RS &&
estimateRSStackSizeLimit(MF))) (estimateStackSize(MF) + ((hasFP(MF) && AFI->hasStackFrame()) ? 4:0) >=
estimateRSStackSizeLimit(MF)))
|| MFI->hasVarSizedObjects() || MFI->hasVarSizedObjects()
|| (MFI->adjustsStack() && !canSimplifyCallFramePseudos(MF)); || (MFI->adjustsStack() && !canSimplifyCallFramePseudos(MF));
@ -881,9 +890,7 @@ ARMBaseRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
ExtraCSSpill = true; ExtraCSSpill = true;
} }
// Darwin ABI requires FP to point to the stack slot that contains the if (hasFP(MF)) {
// previous FP.
if (STI.isTargetDarwin() || hasFP(MF)) {
MF.getRegInfo().setPhysRegUsed(FramePtr); MF.getRegInfo().setPhysRegUsed(FramePtr);
NumGPRSpills++; NumGPRSpills++;
} }
@ -976,7 +983,7 @@ unsigned ARMBaseRegisterInfo::getRARegister() const {
unsigned unsigned
ARMBaseRegisterInfo::getFrameRegister(const MachineFunction &MF) const { ARMBaseRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
if (STI.isTargetDarwin() || hasFP(MF)) if (hasFP(MF))
return FramePtr; return FramePtr;
return ARM::SP; return ARM::SP;
} }
@ -1546,7 +1553,8 @@ emitPrologue(MachineFunction &MF) const {
// Otherwise, if this is not Darwin, all the callee-saved registers go // Otherwise, if this is not Darwin, all the callee-saved registers go
// into spill area 1, including the FP in R11. In either case, it is // into spill area 1, including the FP in R11. In either case, it is
// now safe to emit this assignment. // now safe to emit this assignment.
if (STI.isTargetDarwin() || hasFP(MF)) { bool HasFP = hasFP(MF);
if (HasFP) {
unsigned ADDriOpc = !AFI->isThumbFunction() ? ARM::ADDri : ARM::t2ADDri; unsigned ADDriOpc = !AFI->isThumbFunction() ? ARM::ADDri : ARM::t2ADDri;
MachineInstrBuilder MIB = MachineInstrBuilder MIB =
BuildMI(MBB, MBBI, dl, TII.get(ADDriOpc), FramePtr) BuildMI(MBB, MBBI, dl, TII.get(ADDriOpc), FramePtr)
@ -1565,7 +1573,7 @@ emitPrologue(MachineFunction &MF) const {
unsigned DPRCSOffset = NumBytes - (GPRCS1Size + GPRCS2Size + DPRCSSize); unsigned DPRCSOffset = NumBytes - (GPRCS1Size + GPRCS2Size + DPRCSSize);
unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize; unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize;
unsigned GPRCS1Offset = GPRCS2Offset + GPRCS2Size; unsigned GPRCS1Offset = GPRCS2Offset + GPRCS2Size;
if (STI.isTargetDarwin() || hasFP(MF)) if (HasFP)
AFI->setFramePtrSpillOffset(MFI->getObjectOffset(FramePtrSpillFI) + AFI->setFramePtrSpillOffset(MFI->getObjectOffset(FramePtrSpillFI) +
NumBytes); NumBytes);
AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset); AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset);
@ -1577,11 +1585,14 @@ emitPrologue(MachineFunction &MF) const {
if (NumBytes) { if (NumBytes) {
// Adjust SP after all the callee-save spills. // Adjust SP after all the callee-save spills.
emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes); emitSPUpdate(isARM, MBB, MBBI, dl, TII, -NumBytes);
if (HasFP)
AFI->setShouldRestoreSPFromFP(true);
} }
if (STI.isTargetELF() && hasFP(MF)) { if (STI.isTargetELF() && hasFP(MF)) {
MFI->setOffsetAdjustment(MFI->getOffsetAdjustment() - MFI->setOffsetAdjustment(MFI->getOffsetAdjustment() -
AFI->getFramePtrSpillOffset()); AFI->getFramePtrSpillOffset());
AFI->setShouldRestoreSPFromFP(true);
} }
AFI->setGPRCalleeSavedArea1Size(GPRCS1Size); AFI->setGPRCalleeSavedArea1Size(GPRCS1Size);
@ -1614,6 +1625,8 @@ emitPrologue(MachineFunction &MF) const {
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), ARM::SP) BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVtgpr2gpr), ARM::SP)
.addReg(ARM::R4, RegState::Kill); .addReg(ARM::R4, RegState::Kill);
} }
AFI->setShouldRestoreSPFromFP(true);
} }
} }
@ -1669,34 +1682,25 @@ emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {
AFI->getGPRCalleeSavedArea2Size() + AFI->getGPRCalleeSavedArea2Size() +
AFI->getDPRCalleeSavedAreaSize()); AFI->getDPRCalleeSavedAreaSize());
// Darwin ABI requires FP to point to the stack slot that contains the // Reset SP based on frame pointer only if the stack frame extends beyond
// previous FP. // frame pointer stack slot or target is ELF and the function has FP.
bool HasFP = hasFP(MF); if (AFI->shouldRestoreSPFromFP()) {
if ((STI.isTargetDarwin() && NumBytes) || HasFP) {
NumBytes = AFI->getFramePtrSpillOffset() - NumBytes; NumBytes = AFI->getFramePtrSpillOffset() - NumBytes;
// Reset SP based on frame pointer only if the stack frame extends beyond if (NumBytes) {
// frame pointer stack slot or target is ELF and the function has FP. if (isARM)
if (HasFP || emitARMRegPlusImmediate(MBB, MBBI, dl, ARM::SP, FramePtr, -NumBytes,
AFI->getGPRCalleeSavedArea2Size() || ARMCC::AL, 0, TII);
AFI->getDPRCalleeSavedAreaSize() || else
AFI->getDPRCalleeSavedAreaOffset()) { emitT2RegPlusImmediate(MBB, MBBI, dl, ARM::SP, FramePtr, -NumBytes,
if (NumBytes) { ARMCC::AL, 0, TII);
if (isARM) } else {
emitARMRegPlusImmediate(MBB, MBBI, dl, ARM::SP, FramePtr, -NumBytes, // Thumb2 or ARM.
ARMCC::AL, 0, TII); if (isARM)
else BuildMI(MBB, MBBI, dl, TII.get(ARM::MOVr), ARM::SP)
emitT2RegPlusImmediate(MBB, MBBI, dl, ARM::SP, FramePtr, -NumBytes, .addReg(FramePtr).addImm((unsigned)ARMCC::AL).addReg(0).addReg(0);
ARMCC::AL, 0, TII); else
} else { BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), ARM::SP)
// Thumb2 or ARM. .addReg(FramePtr);
if (isARM)
BuildMI(MBB, MBBI, dl, TII.get(ARM::MOVr), ARM::SP)
.addReg(FramePtr)
.addImm((unsigned)ARMCC::AL).addReg(0).addReg(0);
else
BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVgpr2gpr), ARM::SP)
.addReg(FramePtr);
}
} }
} else if (NumBytes) } else if (NumBytes)
emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes); emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes);

View File

@ -742,14 +742,15 @@ Sched::Preference ARMTargetLowering::getSchedulingPreference(SDNode *N) const {
unsigned unsigned
ARMTargetLowering::getRegPressureLimit(const TargetRegisterClass *RC, ARMTargetLowering::getRegPressureLimit(const TargetRegisterClass *RC,
MachineFunction &MF) const { MachineFunction &MF) const {
unsigned FPDiff = RegInfo->hasFP(MF) ? 1 : 0;
switch (RC->getID()) { switch (RC->getID()) {
default: default:
return 0; return 0;
case ARM::tGPRRegClassID: case ARM::tGPRRegClassID:
return 5 - FPDiff; return RegInfo->hasFP(MF) ? 4 : 5;
case ARM::GPRRegClassID: case ARM::GPRRegClassID: {
return 10 - FPDiff - (Subtarget->isR9Reserved() ? 1 : 0); unsigned FP = RegInfo->hasFP(MF) ? 1 : 0;
return 10 - FP - (Subtarget->isR9Reserved() ? 1 : 0);
}
case ARM::SPRRegClassID: // Currently not used as 'rep' register class. case ARM::SPRRegClassID: // Currently not used as 'rep' register class.
case ARM::DPRRegClassID: case ARM::DPRRegClassID:
return 32 - 10; return 32 - 10;

View File

@ -43,6 +43,10 @@ class ARMFunctionInfo : public MachineFunctionInfo {
/// processFunctionBeforeCalleeSavedScan(). /// processFunctionBeforeCalleeSavedScan().
bool HasStackFrame; bool HasStackFrame;
/// RestoreSPFromFP - True if epilogue should restore SP from FP. Set by
/// emitPrologue.
bool RestoreSPFromFP;
/// LRSpilledForFarJump - True if the LR register has been for spilled to /// LRSpilledForFarJump - True if the LR register has been for spilled to
/// enable far jump. /// enable far jump.
bool LRSpilledForFarJump; bool LRSpilledForFarJump;
@ -95,7 +99,7 @@ public:
ARMFunctionInfo() : ARMFunctionInfo() :
isThumb(false), isThumb(false),
hasThumb2(false), hasThumb2(false),
VarArgsRegSaveSize(0), HasStackFrame(false), VarArgsRegSaveSize(0), HasStackFrame(false), RestoreSPFromFP(false),
LRSpilledForFarJump(false), LRSpilledForFarJump(false),
FramePtrSpillOffset(0), GPRCS1Offset(0), GPRCS2Offset(0), DPRCSOffset(0), FramePtrSpillOffset(0), GPRCS1Offset(0), GPRCS2Offset(0), DPRCSOffset(0),
GPRCS1Size(0), GPRCS2Size(0), DPRCSSize(0), GPRCS1Size(0), GPRCS2Size(0), DPRCSSize(0),
@ -106,7 +110,7 @@ public:
explicit ARMFunctionInfo(MachineFunction &MF) : explicit ARMFunctionInfo(MachineFunction &MF) :
isThumb(MF.getTarget().getSubtarget<ARMSubtarget>().isThumb()), isThumb(MF.getTarget().getSubtarget<ARMSubtarget>().isThumb()),
hasThumb2(MF.getTarget().getSubtarget<ARMSubtarget>().hasThumb2()), hasThumb2(MF.getTarget().getSubtarget<ARMSubtarget>().hasThumb2()),
VarArgsRegSaveSize(0), HasStackFrame(false), VarArgsRegSaveSize(0), HasStackFrame(false), RestoreSPFromFP(false),
LRSpilledForFarJump(false), LRSpilledForFarJump(false),
FramePtrSpillOffset(0), GPRCS1Offset(0), GPRCS2Offset(0), DPRCSOffset(0), FramePtrSpillOffset(0), GPRCS1Offset(0), GPRCS2Offset(0), DPRCSOffset(0),
GPRCS1Size(0), GPRCS2Size(0), DPRCSSize(0), GPRCS1Size(0), GPRCS2Size(0), DPRCSSize(0),
@ -125,6 +129,9 @@ public:
bool hasStackFrame() const { return HasStackFrame; } bool hasStackFrame() const { return HasStackFrame; }
void setHasStackFrame(bool s) { HasStackFrame = s; } void setHasStackFrame(bool s) { HasStackFrame = s; }
bool shouldRestoreSPFromFP() const { return RestoreSPFromFP; }
void setShouldRestoreSPFromFP(bool s) { RestoreSPFromFP = s; }
bool isLRSpilledForFarJump() const { return LRSpilledForFarJump; } bool isLRSpilledForFarJump() const { return LRSpilledForFarJump; }
void setLRIsSpilledForFarJump(bool s) { LRSpilledForFarJump = s; } void setLRIsSpilledForFarJump(bool s) { LRSpilledForFarJump = s; }

View File

@ -294,8 +294,7 @@ def GPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6,
if (Subtarget.isThumb1Only()) { if (Subtarget.isThumb1Only()) {
I = THUMB_GPR_AO + (sizeof(THUMB_GPR_AO)/sizeof(unsigned)); I = THUMB_GPR_AO + (sizeof(THUMB_GPR_AO)/sizeof(unsigned));
// Mac OS X requires FP not to be clobbered for backtracing purpose. return RI->hasFP(MF) ? I-1 : I;
return (Subtarget.isTargetDarwin() || RI->hasFP(MF)) ? I-1 : I;
} }
if (Subtarget.isTargetDarwin()) { if (Subtarget.isTargetDarwin()) {
@ -312,8 +311,7 @@ def GPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6,
I = ARM_GPR_AO_1 + (sizeof(ARM_GPR_AO_1)/sizeof(unsigned)); 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 RI->hasFP(MF) ? I-1 : I;
return (Subtarget.isTargetDarwin() || RI->hasFP(MF)) ? I-1 : I;
} }
}]; }];
} }
@ -403,8 +401,7 @@ def rGPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6,
if (Subtarget.isThumb1Only()) { if (Subtarget.isThumb1Only()) {
I = THUMB_rGPRAO + (sizeof(THUMB_rGPRAO)/sizeof(unsigned)); I = THUMB_rGPRAO + (sizeof(THUMB_rGPRAO)/sizeof(unsigned));
// Mac OS X requires FP not to be clobbered for backtracing purpose. return RI->hasFP(MF) ? I-1 : I;
return (Subtarget.isTargetDarwin() || RI->hasFP(MF)) ? I-1 : I;
} }
if (Subtarget.isTargetDarwin()) { if (Subtarget.isTargetDarwin()) {
@ -421,8 +418,7 @@ def rGPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6,
I = ARM_rGPRAO_1 + (sizeof(ARM_rGPRAO_1)/sizeof(unsigned)); I = ARM_rGPRAO_1 + (sizeof(ARM_rGPRAO_1)/sizeof(unsigned));
} }
// Mac OS X requires FP not to be clobbered for backtracing purpose. return RI->hasFP(MF) ? I-1 : I;
return (Subtarget.isTargetDarwin() || RI->hasFP(MF)) ? I-1 : I;
} }
}]; }];
} }
@ -449,11 +445,9 @@ def tGPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6, R7]> {
tGPRClass::allocation_order_end(const MachineFunction &MF) const { tGPRClass::allocation_order_end(const MachineFunction &MF) const {
const TargetMachine &TM = MF.getTarget(); const TargetMachine &TM = MF.getTarget();
const TargetRegisterInfo *RI = TM.getRegisterInfo(); const TargetRegisterInfo *RI = TM.getRegisterInfo();
const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
tGPRClass::iterator I = tGPRClass::iterator I =
THUMB_tGPR_AO + (sizeof(THUMB_tGPR_AO)/sizeof(unsigned)); THUMB_tGPR_AO + (sizeof(THUMB_tGPR_AO)/sizeof(unsigned));
// Mac OS X requires FP not to be clobbered for backtracing purpose. return RI->hasFP(MF) ? I-1 : I;
return (Subtarget.isTargetDarwin() || RI->hasFP(MF)) ? I-1 : I;
} }
}]; }];
} }

View File

@ -742,11 +742,11 @@ void Thumb1RegisterInfo::emitPrologue(MachineFunction &MF) const {
dl = MBBI->getDebugLoc(); dl = MBBI->getDebugLoc();
} }
// Darwin ABI requires FP to point to the stack slot that contains the // Adjust FP so it point to the stack slot that contains the previous FP.
// previous FP. if (hasFP(MF)) {
if (STI.isTargetDarwin() || hasFP(MF)) {
BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), FramePtr) BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), FramePtr)
.addFrameIndex(FramePtrSpillFI).addImm(0); .addFrameIndex(FramePtrSpillFI).addImm(0);
AFI->setShouldRestoreSPFromFP(true);
} }
// Determine starting offsets of spill areas. // Determine starting offsets of spill areas.
@ -764,10 +764,9 @@ void Thumb1RegisterInfo::emitPrologue(MachineFunction &MF) const {
emitSPUpdate(MBB, MBBI, TII, dl, *this, -NumBytes); emitSPUpdate(MBB, MBBI, TII, dl, *this, -NumBytes);
} }
if (STI.isTargetELF() && hasFP(MF)) { if (STI.isTargetELF() && hasFP(MF))
MFI->setOffsetAdjustment(MFI->getOffsetAdjustment() - MFI->setOffsetAdjustment(MFI->getOffsetAdjustment() -
AFI->getFramePtrSpillOffset()); AFI->getFramePtrSpillOffset());
}
AFI->setGPRCalleeSavedArea1Size(GPRCS1Size); AFI->setGPRCalleeSavedArea1Size(GPRCS1Size);
AFI->setGPRCalleeSavedArea2Size(GPRCS2Size); AFI->setGPRCalleeSavedArea2Size(GPRCS2Size);
@ -828,7 +827,7 @@ void Thumb1RegisterInfo::emitEpilogue(MachineFunction &MF,
AFI->getGPRCalleeSavedArea2Size() + AFI->getGPRCalleeSavedArea2Size() +
AFI->getDPRCalleeSavedAreaSize()); AFI->getDPRCalleeSavedAreaSize());
if (hasFP(MF)) { if (AFI->shouldRestoreSPFromFP()) {
NumBytes = AFI->getFramePtrSpillOffset() - NumBytes; NumBytes = AFI->getFramePtrSpillOffset() - NumBytes;
// Reset SP based on frame pointer only if the stack frame extends beyond // Reset SP based on frame pointer only if the stack frame extends beyond
// frame pointer stack slot or target is ELF and the function has FP. // frame pointer stack slot or target is ELF and the function has FP.

View File

@ -1,20 +1,35 @@
; RUN: llc < %s -march=thumb | grep {ldr.*LCP} | count 5 ; RUN: llc < %s -mtriple=thumb-apple-darwin | FileCheck %s
define void @test1() { define void @test1() {
; CHECK: test1:
; CHECK: sub sp, #256
; CHECK: add sp, #256
%tmp = alloca [ 64 x i32 ] , align 4 %tmp = alloca [ 64 x i32 ] , align 4
ret void ret void
} }
define void @test2() { define void @test2() {
; CHECK: test2:
; CHECK: ldr r0, LCPI
; CHECK: add sp, r0
; CHECK: mov sp, r7
; CHECK: sub sp, #4
%tmp = alloca [ 4168 x i8 ] , align 4 %tmp = alloca [ 4168 x i8 ] , align 4
ret void ret void
} }
define i32 @test3() { define i32 @test3() {
%retval = alloca i32, align 4 ; CHECK: test3:
%tmp = alloca i32, align 4 ; CHECK: ldr r1, LCPI
%a = alloca [805306369 x i8], align 16 ; CHECK: add sp, r1
store i32 0, i32* %tmp ; CHECK: ldr r1, LCPI
%tmp1 = load i32* %tmp ; CHECK: add r1, sp
ret i32 %tmp1 ; CHECK: mov sp, r7
; CHECK: sub sp, #4
%retval = alloca i32, align 4
%tmp = alloca i32, align 4
%a = alloca [805306369 x i8], align 16
store i32 0, i32* %tmp
%tmp1 = load i32* %tmp
ret i32 %tmp1
} }