unsigned MaxCallFrameSize = 0;
bool HasCalls = false;
+ std::vector<MachineBasicBlock::iterator> FrameSDOps;
for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB)
- for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); )
+ for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ++I)
if (I->getOpcode() == FrameSetupOpcode ||
I->getOpcode() == FrameDestroyOpcode) {
assert(I->getNumOperands() >= 1 && "Call Frame Setup/Destroy Pseudo"
unsigned Size = I->getOperand(0).getImmedValue();
if (Size > MaxCallFrameSize) MaxCallFrameSize = Size;
HasCalls = true;
- RegInfo->eliminateCallFramePseudoInstr(Fn, *BB, I++);
- } else {
- ++I;
+ FrameSDOps.push_back(I);
}
MachineFrameInfo *FFI = Fn.getFrameInfo();
FFI->setHasCalls(HasCalls);
FFI->setMaxCallFrameSize(MaxCallFrameSize);
+ for (unsigned i = 0, e = FrameSDOps.size(); i != e; ++i) {
+ MachineBasicBlock::iterator I = FrameSDOps[i];
+ RegInfo->eliminateCallFramePseudoInstr(Fn, *I->getParent(), I);
+ }
// Now figure out which *callee saved* registers are modified by the current
// function, thus needing to be saved and restored in the prolog/epilog.
// First assign frame offsets to stack objects that are used to spill
// callee saved registers.
if (StackGrowsDown) {
- for (unsigned i = 0, e = FFI->getObjectIndexEnd(); i != e; ++i) {
- if (i < MinCSFrameIndex || i > MaxCSFrameIndex)
- continue;
-
+ for (unsigned i = MinCSFrameIndex; i <= MaxCSFrameIndex; ++i) {
// If stack grows down, we need to add size of find the lowest
// address of the object.
Offset += FFI->getObjectSize(i);
FFI->setObjectOffset(i, -Offset); // Set the computed offset
}
} else {
- for (int i = FFI->getObjectIndexEnd()-1; i >= 0; --i) {
- if ((unsigned)i < MinCSFrameIndex || (unsigned)i > MaxCSFrameIndex)
- continue;
-
+ for (unsigned i = MaxCSFrameIndex; i >= MinCSFrameIndex; --i) {
unsigned Align = FFI->getObjectAlignment(i);
// If the alignment of this object is greater than that of the stack, then
// increase the stack alignment to match.
if (RS && RegInfo->hasFP(Fn)) {
int SFI = RS->getScavengingFrameIndex();
if (SFI >= 0) {
- // If stack grows down, we need to add size of find the lowest
+ // If stack grows down, we need to add size of the lowest
// address of the object.
if (StackGrowsDown)
Offset += FFI->getObjectSize(SFI);
// subroutines have their stack frames suitable aligned.
if (!RegInfo->targetHandlesStackFrameRounding() &&
(FFI->hasCalls() || FFI->hasVarSizedObjects())) {
- // When we have no frame pointer, we reserve argument space for call sites
- // in the function immediately on entry to the current function. This
- // eliminates the need for add/sub sp brackets around call sites.
- if (!RegInfo->hasFP(Fn))
+ // If we have reserved argument space for call sites in the function
+ // immediately on entry to the current function, count it as part of the
+ // overall stack size.
+ if (RegInfo->hasReservedCallFrame(Fn))
Offset += FFI->getMaxCallFrameSize();
unsigned AlignMask = TFI.getStackAlignment() - 1;
return NoFramePointerElim || MF.getFrameInfo()->hasVarSizedObjects();
}
+// hasReservedCallFrame - Under normal circumstances, when a frame pointer is
+// not required, we reserve argument space for call sites in the function
+// immediately on entry to the current function. This eliminates the need for
+// add/sub sp brackets around call sites. Returns true if the call frame is
+// included as part of the stack frame.
+bool ARMRegisterInfo::hasReservedCallFrame(MachineFunction &MF) const {
+ const MachineFrameInfo *FFI = MF.getFrameInfo();
+ unsigned CFSize = FFI->getMaxCallFrameSize();
+ ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
+ // It's not always a good idea to include the call frame as part of the
+ // stack frame. ARM (especially Thumb) has small immediate offset to
+ // address the stack frame. So a large call frame can cause poor codegen
+ // and may even makes it impossible to scavenge a register.
+ if (AFI->isThumbFunction()) {
+ if (CFSize >= ((1 << 8) - 1) * 4 / 2) // Half of imm8 * 4
+ return false;
+ } else {
+ if (CFSize >= ((1 << 12) - 1) / 2) // Half of imm12
+ return false;
+ }
+ return !hasFP(MF);
+}
+
/// emitARMRegPlusImmediate - Emits a series of instructions to materialize
/// a destreg = basereg + immediate in ARM code.
static
void ARMRegisterInfo::
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
- if (hasFP(MF)) {
+ if (!hasReservedCallFrame(MF)) {
// If we have alloca, convert as follows:
// ADJCALLSTACKDOWN -> sub, sp, sp, amount
// ADJCALLSTACKUP -> add, sp, sp, amount
Limit = (1 << 8) - 1;
goto DoneEstimating;
} else if (AddrMode == ARMII::AddrMode5) {
- Limit = ((1 << 8) - 1) * 4;
- goto DoneEstimating;
+ unsigned ThisLimit = ((1 << 8) - 1) * 4;
+ if (ThisLimit < Limit)
+ Limit = ThisLimit;
}
}
}