From: Jim Grosbach Date: Tue, 24 Aug 2010 21:19:33 +0000 (+0000) Subject: Add ARM heuristic for when to allocate a virtual base register for stack X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=3197380143cdc18837722129ac888528b9fbfc2b;p=oota-llvm.git Add ARM heuristic for when to allocate a virtual base register for stack access. rdar://8277890&7352504 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@111968 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 492499899f8..5bb092c1217 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -653,7 +653,7 @@ public: /// reference would be better served by a base register other than FP /// or SP. Used by LocalStackFrameAllocation to determine which frame index /// references it should create new base registers for. - virtual bool needsFrameBaseReg(MachineInstr *MI, unsigned operand) const { + virtual bool needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const { return false; } diff --git a/lib/CodeGen/LocalStackSlotAllocation.cpp b/lib/CodeGen/LocalStackSlotAllocation.cpp index 3f79593b4ed..8bb802fa167 100644 --- a/lib/CodeGen/LocalStackSlotAllocation.cpp +++ b/lib/CodeGen/LocalStackSlotAllocation.cpp @@ -250,7 +250,7 @@ bool LocalStackSlotPass::insertFrameReferenceRegisters(MachineFunction &Fn) { continue; DEBUG(dbgs() << "Considering: " << *MI); - if (TRI->needsFrameBaseReg(MI, i)) { + if (TRI->needsFrameBaseReg(MI, LocalOffsets[FrameIdx])) { unsigned BaseReg = 0; int64_t Offset = 0; int64_t FrameSizeAdjust = StackGrowsDown ? MFI->getLocalFrameSize() diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index edfacc72e0c..850f9b4d601 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -44,7 +44,7 @@ cl::opt ReuseFrameIndexVals("arm-reuse-frame-index-vals", cl::Hidden, cl::init(true), cl::desc("Reuse repeated frame index values")); static cl::opt -ForceAllBaseRegAlloc("arm-force-base-reg-alloc", cl::Hidden, cl::init(true), +ForceAllBaseRegAlloc("arm-force-base-reg-alloc", cl::Hidden, cl::init(false), cl::desc("Force use of virtual base registers for stack load/store")); static cl::opt EnableLocalStackAlloc("enable-local-stack-alloc", cl::init(false), cl::Hidden, @@ -1436,9 +1436,10 @@ getFrameIndexInstrOffset(MachineInstr *MI, int Idx) const { /// or SP. Used by LocalStackFrameAllocation to determine which frame index /// references it should create new base registers for. bool ARMBaseRegisterInfo:: -needsFrameBaseReg(MachineInstr *MI, unsigned operand) const { - assert (MI->getOperand(operand).isFI() && - "needsFrameBaseReg() called on non Frame Index operand!"); +needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const { + for (unsigned i = 0; !MI->getOperand(i).isFI(); ++i) { + assert(i < MI->getNumOperands() &&"Instr doesn't have FrameIndex operand!"); + } // It's the load/store FI references that cause issues, as it can be difficult // to materialize the offset if it won't fit in the literal field. Estimate @@ -1465,12 +1466,49 @@ needsFrameBaseReg(MachineInstr *MI, unsigned operand) const { return false; } - // FIXME: TODO // Without a virtual base register, if the function has variable sized // objects, all fixed-size local references will be via the frame pointer, - // otherwise via the stack pointer. Approximate the offset and see if it's - // legal for the instruction. + // Approximate the offset and see if it's legal for the instruction. + // Note that the incoming offset is based on the SP value at function entry, + // so it'll be negative. + MachineFunction &MF = *MI->getParent()->getParent(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + ARMFunctionInfo *AFI = MF.getInfo(); + + // Estimate an offset from the frame pointer. + // Conservatively assume all callee-saved registers get pushed. R4-R6 + // will be earlier than the FP, so we ignore those. + // R7, LR + int64_t FPOffset = Offset - 8; + // ARM and Thumb2 functions also need to consider R8-R11 and D8-D15 + if (!AFI->isThumbFunction() || !AFI->isThumb1OnlyFunction()) + FPOffset -= 80; + // Estimate an offset from the stack pointer. + Offset = -Offset; + // Assume that we'll have at least some spill slots allocated. + // FIXME: This is a total SWAG number. We should run some statistics + // and pick a real one. + Offset += 128; // 128 bytes of spill slots + + // If there is a frame pointer, try using it. + // The FP is only available if there is no dynamic realignment. We + // don't know for sure yet whether we'll need that, so we guess based + // on whether there are any local variables that would trigger it. + unsigned StackAlign = MF.getTarget().getFrameInfo()->getStackAlignment(); + if (hasFP(MF) && + !((MFI->getLocalFrameMaxAlign() > StackAlign) && canRealignStack(MF))) { + if (isFrameOffsetLegal(MI, FPOffset)) + return false; + } + // If we can reference via the stack pointer, try that. + // FIXME: This (and the code that resolves the references) can be improved + // to only disallow SP relative references in the live range of + // the VLA(s). In practice, it's unclear how much difference that + // would make, but it may be worth doing. + if (!MFI->hasVarSizedObjects() && isFrameOffsetLegal(MI, Offset)) + return false; + // The offset likely isn't legal, we want to allocate a virtual base register. return true; } diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.h b/lib/Target/ARM/ARMBaseRegisterInfo.h index 7044b74e7dc..7c1a04ca3b0 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.h +++ b/lib/Target/ARM/ARMBaseRegisterInfo.h @@ -106,7 +106,7 @@ public: bool canRealignStack(const MachineFunction &MF) const; bool needsStackRealignment(const MachineFunction &MF) const; int64_t getFrameIndexInstrOffset(MachineInstr *MI, int Idx) const; - bool needsFrameBaseReg(MachineInstr *MI, unsigned operand) const; + bool needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const; void materializeFrameBaseRegister(MachineBasicBlock::iterator I, unsigned BaseReg, int FrameIdx, int64_t Offset) const;