From 657baec0af38d84e24e4738b0696bb99d1517179 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Wed, 24 Feb 2010 22:43:17 +0000 Subject: [PATCH] Create a stack frame on ARM when - Function uses all scratch registers AND - Function does not use any callee saved registers AND - Stack size is too big to address with immediate offsets. In this case a register must be scavenged to calculate the address of a stack object, and the scavenger needs a spare register or emergency spill slot. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97071 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMBaseRegisterInfo.cpp | 82 +++++++++++----------- test/CodeGen/Thumb2/2010-02-24-BigStack.ll | 15 ++++ 2 files changed, 56 insertions(+), 41 deletions(-) create mode 100644 test/CodeGen/Thumb2/2010-02-24-BigStack.ll diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index c0c95fea131..80449668caf 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -513,7 +513,7 @@ cannotEliminateFrame(const MachineFunction &MF) const { } /// estimateStackSize - Estimate and return the size of the frame. -static unsigned estimateStackSize(MachineFunction &MF, MachineFrameInfo *MFI) { +static unsigned estimateStackSize(MachineFunction &MF) { const MachineFrameInfo *FFI = MF.getFrameInfo(); int Offset = 0; for (int i = FFI->getObjectIndexBegin(); i != 0; ++i) { @@ -671,8 +671,16 @@ ARMBaseRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, } } + // If any of the stack slot references may be out of range of an immediate + // offset, make sure a register (or a spill slot) is available for the + // register scavenger. Note that if we're indexing off the frame pointer, the + // effective stack size is 4 bytes larger since the FP points to the stack + // slot of the previous FP. + bool BigStack = RS && + estimateStackSize(MF) + (hasFP(MF) ? 4 : 0) >= estimateRSStackSizeLimit(MF); + bool ExtraCSSpill = false; - if (!CanEliminateFrame || cannotEliminateFrame(MF)) { + if (BigStack || !CanEliminateFrame || cannotEliminateFrame(MF)) { AFI->setHasStackFrame(true); // If LR is not spilled, but at least one of R4, R5, R6, and R7 is spilled. @@ -727,51 +735,43 @@ ARMBaseRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, // callee-saved register or reserve a special spill slot to facilitate // register scavenging. Thumb1 needs a spill slot for stack pointer // adjustments also, even when the frame itself is small. - if (RS && !ExtraCSSpill) { - MachineFrameInfo *MFI = MF.getFrameInfo(); - // If any of the stack slot references may be out of range of an - // immediate offset, make sure a register (or a spill slot) is - // available for the register scavenger. Note that if we're indexing - // off the frame pointer, the effective stack size is 4 bytes larger - // since the FP points to the stack slot of the previous FP. - if (estimateStackSize(MF, MFI) + (hasFP(MF) ? 4 : 0) - >= estimateRSStackSizeLimit(MF)) { - // If any non-reserved CS register isn't spilled, just spill one or two - // extra. That should take care of it! - unsigned NumExtras = TargetAlign / 4; - SmallVector Extras; - while (NumExtras && !UnspilledCS1GPRs.empty()) { - unsigned Reg = UnspilledCS1GPRs.back(); - UnspilledCS1GPRs.pop_back(); + if (BigStack && !ExtraCSSpill) { + // If any non-reserved CS register isn't spilled, just spill one or two + // extra. That should take care of it! + unsigned NumExtras = TargetAlign / 4; + SmallVector Extras; + while (NumExtras && !UnspilledCS1GPRs.empty()) { + unsigned Reg = UnspilledCS1GPRs.back(); + UnspilledCS1GPRs.pop_back(); + if (!isReservedReg(MF, Reg)) { + Extras.push_back(Reg); + NumExtras--; + } + } + // For non-Thumb1 functions, also check for hi-reg CS registers + if (!AFI->isThumb1OnlyFunction()) { + while (NumExtras && !UnspilledCS2GPRs.empty()) { + unsigned Reg = UnspilledCS2GPRs.back(); + UnspilledCS2GPRs.pop_back(); if (!isReservedReg(MF, Reg)) { Extras.push_back(Reg); NumExtras--; } } - // For non-Thumb1 functions, also check for hi-reg CS registers - if (!AFI->isThumb1OnlyFunction()) { - while (NumExtras && !UnspilledCS2GPRs.empty()) { - unsigned Reg = UnspilledCS2GPRs.back(); - UnspilledCS2GPRs.pop_back(); - if (!isReservedReg(MF, Reg)) { - Extras.push_back(Reg); - NumExtras--; - } - } - } - if (Extras.size() && NumExtras == 0) { - for (unsigned i = 0, e = Extras.size(); i != e; ++i) { - MF.getRegInfo().setPhysRegUsed(Extras[i]); - AFI->setCSRegisterIsSpilled(Extras[i]); - } - } else if (!AFI->isThumb1OnlyFunction()) { - // note: Thumb1 functions spill to R12, not the stack. - // Reserve a slot closest to SP or frame pointer. - const TargetRegisterClass *RC = ARM::GPRRegisterClass; - RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(), - RC->getAlignment(), - false)); + } + if (Extras.size() && NumExtras == 0) { + for (unsigned i = 0, e = Extras.size(); i != e; ++i) { + MF.getRegInfo().setPhysRegUsed(Extras[i]); + AFI->setCSRegisterIsSpilled(Extras[i]); } + } else if (!AFI->isThumb1OnlyFunction()) { + // note: Thumb1 functions spill to R12, not the stack. Reserve a slot + // closest to SP or frame pointer. + const TargetRegisterClass *RC = ARM::GPRRegisterClass; + MachineFrameInfo *MFI = MF.getFrameInfo(); + RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(), + RC->getAlignment(), + false)); } } } diff --git a/test/CodeGen/Thumb2/2010-02-24-BigStack.ll b/test/CodeGen/Thumb2/2010-02-24-BigStack.ll new file mode 100644 index 00000000000..533546bb191 --- /dev/null +++ b/test/CodeGen/Thumb2/2010-02-24-BigStack.ll @@ -0,0 +1,15 @@ +; RUN: llc < %s -O0 -relocation-model=pic -disable-fp-elim -mcpu=cortex-a8 -mattr=+vfp2 +; This test creates a big stack frame without spilling any callee-saved registers. +; Make sure the whole stack frame is addrerssable wiothout scavenger crashes. +target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:32-n32" +target triple = "thumbv7-apple-darwin3.0.0-iphoneos" + +define arm_apcscc void @FindMin(double* %panelTDEL, i8* %dclOfRow, i32 %numRows, i32 %numCols, double* %retMin_RES_TDEL) { +entry: + %panelTDEL.addr = alloca double*, align 4 ; [#uses=1] + %panelResTDEL = alloca [2560 x double], align 4 ; <[2560 x double]*> [#uses=0] + store double* %panelTDEL, double** %panelTDEL.addr + store double* %retMin_RES_TDEL, double** undef + store i32 0, i32* undef + unreachable +}