Infrastructure for dynamic stack realignment on ARM. For now, this is off by

default behind a command line option. This will enable better performance for
vectors on NEON enabled processors.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85333 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jim Grosbach 2009-10-27 22:45:39 +00:00
parent de020736c0
commit 3dab277857
2 changed files with 76 additions and 2 deletions

View File

@ -29,6 +29,7 @@
#include "llvm/CodeGen/MachineLocation.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetFrameInfo.h"
@ -48,6 +49,10 @@ static cl::opt<bool>
ReuseFrameIndexVals("arm-reuse-frame-index-vals", cl::Hidden, cl::init(false),
cl::desc("Reuse repeated frame index values"));
static cl::opt<bool>
ARMDynamicStackAlign("arm-dynamic-stack-alignment", cl::Hidden, cl::init(false),
cl::desc("Dynamically re-align the stack as needed"));
unsigned ARMBaseRegisterInfo::getRegisterNumbering(unsigned RegEnum,
bool *isSPVFP) {
if (isSPVFP)
@ -466,6 +471,21 @@ ARMBaseRegisterInfo::UpdateRegAllocHint(unsigned Reg, unsigned NewReg,
}
}
static unsigned calculateMaxStackAlignment(const MachineFrameInfo *FFI) {
unsigned MaxAlign = 0;
for (int i = FFI->getObjectIndexBegin(),
e = FFI->getObjectIndexEnd(); i != e; ++i) {
if (FFI->isDeadObjectIndex(i))
continue;
unsigned Align = FFI->getObjectAlignment(i);
MaxAlign = std::max(MaxAlign, Align);
}
return MaxAlign;
}
/// hasFP - Return true if the specified function should have a dedicated frame
/// pointer register. This is true if the function has variable sized allocas
/// or if frame pointer elimination is disabled.
@ -473,10 +493,28 @@ ARMBaseRegisterInfo::UpdateRegAllocHint(unsigned Reg, unsigned NewReg,
bool ARMBaseRegisterInfo::hasFP(const MachineFunction &MF) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
return (NoFramePointerElim ||
needsStackRealignment(MF) ||
MFI->hasVarSizedObjects() ||
MFI->isFrameAddressTaken());
}
bool ARMBaseRegisterInfo::
needsStackRealignment(const MachineFunction &MF) const {
// Only do this for ARM if explicitly enabled
// FIXME: Once it's passing all the tests, enable by default
if (!ARMDynamicStackAlign)
return false;
const MachineFrameInfo *MFI = MF.getFrameInfo();
const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
unsigned StackAlign = MF.getTarget().getFrameInfo()->getStackAlignment();
return (RealignStack &&
!AFI->isThumb1OnlyFunction() &&
(MFI->getMaxAlignment() > StackAlign) &&
!MFI->hasVarSizedObjects());
}
bool ARMBaseRegisterInfo::cannotEliminateFrame(const MachineFunction &MF) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
if (NoFramePointerElim && MFI->hasCalls())
@ -552,6 +590,16 @@ ARMBaseRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
SmallVector<unsigned, 4> UnspilledCS2GPRs;
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
MachineFrameInfo *MFI = MF.getFrameInfo();
// Calculate and set max stack object alignment early, so we can decide
// whether we will need stack realignment (and thus FP).
if (ARMDynamicStackAlign) {
unsigned MaxAlign = std::max(MFI->getMaxAlignment(),
calculateMaxStackAlignment(MFI));
MFI->setMaxAlignment(MaxAlign);
}
// Don't spill FP if the frame can be eliminated. This is determined
// by scanning the callee-save registers to see if any is used.
const unsigned *CSRegs = getCalleeSavedRegs();
@ -1085,16 +1133,28 @@ ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int FrameIndex = MI.getOperand(i).getIndex();
int Offset = MFI->getObjectOffset(FrameIndex) + MFI->getStackSize() + SPAdj;
// When doing dynamic stack realignment, all of these need to change(?)
if (AFI->isGPRCalleeSavedArea1Frame(FrameIndex))
Offset -= AFI->getGPRCalleeSavedArea1Offset();
else if (AFI->isGPRCalleeSavedArea2Frame(FrameIndex))
Offset -= AFI->getGPRCalleeSavedArea2Offset();
else if (AFI->isDPRCalleeSavedAreaFrame(FrameIndex))
Offset -= AFI->getDPRCalleeSavedAreaOffset();
else if (hasFP(MF) && AFI->hasStackFrame()) {
else if (needsStackRealignment(MF)) {
// When dynamically realigning the stack, use the frame pointer for
// parameters, and the stack pointer for locals.
assert (hasFP(MF) && "dynamic stack realignment without a FP!");
if (FrameIndex < 0) {
FrameReg = getFrameRegister(MF);
Offset -= AFI->getFramePtrSpillOffset();
// When referencing from the frame pointer, stack pointer adjustments
// don't matter.
SPAdj = 0;
}
} else if (hasFP(MF) && AFI->hasStackFrame()) {
assert(SPAdj == 0 && "Unexpected stack offset!");
// Use frame pointer to reference fixed objects unless this is a
// frameless function,
// frameless function.
FrameReg = getFrameRegister(MF);
Offset -= AFI->getFramePtrSpillOffset();
}
@ -1303,6 +1363,18 @@ emitPrologue(MachineFunction &MF) const {
AFI->setGPRCalleeSavedArea1Size(GPRCS1Size);
AFI->setGPRCalleeSavedArea2Size(GPRCS2Size);
AFI->setDPRCalleeSavedAreaSize(DPRCSSize);
// If we need dynamic stack realignment, do it here.
if (needsStackRealignment(MF)) {
unsigned Opc;
unsigned MaxAlign = MFI->getMaxAlignment();
assert (!AFI->isThumb1OnlyFunction());
Opc = AFI->isThumbFunction() ? ARM::t2BICri : ARM::BICri;
AddDefaultCC(AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(Opc), ARM::SP)
.addReg(ARM::SP, RegState::Kill)
.addImm(MaxAlign-1)));
}
}
static bool isCalleeSavedRegister(unsigned Reg, const unsigned *CSRegs) {

View File

@ -96,6 +96,8 @@ public:
bool hasFP(const MachineFunction &MF) const;
bool needsStackRealignment(const MachineFunction &MF) const;
bool cannotEliminateFrame(const MachineFunction &MF) const;
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,