mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-08 03:30:22 +00:00
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:
parent
de020736c0
commit
3dab277857
@ -29,6 +29,7 @@
|
|||||||
#include "llvm/CodeGen/MachineLocation.h"
|
#include "llvm/CodeGen/MachineLocation.h"
|
||||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||||
#include "llvm/CodeGen/RegisterScavenging.h"
|
#include "llvm/CodeGen/RegisterScavenging.h"
|
||||||
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include "llvm/Target/TargetFrameInfo.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),
|
ReuseFrameIndexVals("arm-reuse-frame-index-vals", cl::Hidden, cl::init(false),
|
||||||
cl::desc("Reuse repeated frame index values"));
|
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,
|
unsigned ARMBaseRegisterInfo::getRegisterNumbering(unsigned RegEnum,
|
||||||
bool *isSPVFP) {
|
bool *isSPVFP) {
|
||||||
if (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
|
/// hasFP - Return true if the specified function should have a dedicated frame
|
||||||
/// pointer register. This is true if the function has variable sized allocas
|
/// pointer register. This is true if the function has variable sized allocas
|
||||||
/// or if frame pointer elimination is disabled.
|
/// or if frame pointer elimination is disabled.
|
||||||
@ -473,10 +493,28 @@ ARMBaseRegisterInfo::UpdateRegAllocHint(unsigned Reg, unsigned NewReg,
|
|||||||
bool ARMBaseRegisterInfo::hasFP(const MachineFunction &MF) const {
|
bool ARMBaseRegisterInfo::hasFP(const MachineFunction &MF) const {
|
||||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
return (NoFramePointerElim ||
|
return (NoFramePointerElim ||
|
||||||
|
needsStackRealignment(MF) ||
|
||||||
MFI->hasVarSizedObjects() ||
|
MFI->hasVarSizedObjects() ||
|
||||||
MFI->isFrameAddressTaken());
|
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 {
|
bool ARMBaseRegisterInfo::cannotEliminateFrame(const MachineFunction &MF) const {
|
||||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
if (NoFramePointerElim && MFI->hasCalls())
|
if (NoFramePointerElim && MFI->hasCalls())
|
||||||
@ -552,6 +590,16 @@ ARMBaseRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
|||||||
SmallVector<unsigned, 4> UnspilledCS2GPRs;
|
SmallVector<unsigned, 4> UnspilledCS2GPRs;
|
||||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
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
|
// 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.
|
// by scanning the callee-save registers to see if any is used.
|
||||||
const unsigned *CSRegs = getCalleeSavedRegs();
|
const unsigned *CSRegs = getCalleeSavedRegs();
|
||||||
@ -1085,16 +1133,28 @@ ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|||||||
int FrameIndex = MI.getOperand(i).getIndex();
|
int FrameIndex = MI.getOperand(i).getIndex();
|
||||||
int Offset = MFI->getObjectOffset(FrameIndex) + MFI->getStackSize() + SPAdj;
|
int Offset = MFI->getObjectOffset(FrameIndex) + MFI->getStackSize() + SPAdj;
|
||||||
|
|
||||||
|
// When doing dynamic stack realignment, all of these need to change(?)
|
||||||
if (AFI->isGPRCalleeSavedArea1Frame(FrameIndex))
|
if (AFI->isGPRCalleeSavedArea1Frame(FrameIndex))
|
||||||
Offset -= AFI->getGPRCalleeSavedArea1Offset();
|
Offset -= AFI->getGPRCalleeSavedArea1Offset();
|
||||||
else if (AFI->isGPRCalleeSavedArea2Frame(FrameIndex))
|
else if (AFI->isGPRCalleeSavedArea2Frame(FrameIndex))
|
||||||
Offset -= AFI->getGPRCalleeSavedArea2Offset();
|
Offset -= AFI->getGPRCalleeSavedArea2Offset();
|
||||||
else if (AFI->isDPRCalleeSavedAreaFrame(FrameIndex))
|
else if (AFI->isDPRCalleeSavedAreaFrame(FrameIndex))
|
||||||
Offset -= AFI->getDPRCalleeSavedAreaOffset();
|
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!");
|
assert(SPAdj == 0 && "Unexpected stack offset!");
|
||||||
// Use frame pointer to reference fixed objects unless this is a
|
// Use frame pointer to reference fixed objects unless this is a
|
||||||
// frameless function,
|
// frameless function.
|
||||||
FrameReg = getFrameRegister(MF);
|
FrameReg = getFrameRegister(MF);
|
||||||
Offset -= AFI->getFramePtrSpillOffset();
|
Offset -= AFI->getFramePtrSpillOffset();
|
||||||
}
|
}
|
||||||
@ -1303,6 +1363,18 @@ emitPrologue(MachineFunction &MF) const {
|
|||||||
AFI->setGPRCalleeSavedArea1Size(GPRCS1Size);
|
AFI->setGPRCalleeSavedArea1Size(GPRCS1Size);
|
||||||
AFI->setGPRCalleeSavedArea2Size(GPRCS2Size);
|
AFI->setGPRCalleeSavedArea2Size(GPRCS2Size);
|
||||||
AFI->setDPRCalleeSavedAreaSize(DPRCSSize);
|
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) {
|
static bool isCalleeSavedRegister(unsigned Reg, const unsigned *CSRegs) {
|
||||||
|
@ -96,6 +96,8 @@ public:
|
|||||||
|
|
||||||
bool hasFP(const MachineFunction &MF) const;
|
bool hasFP(const MachineFunction &MF) const;
|
||||||
|
|
||||||
|
bool needsStackRealignment(const MachineFunction &MF) const;
|
||||||
|
|
||||||
bool cannotEliminateFrame(const MachineFunction &MF) const;
|
bool cannotEliminateFrame(const MachineFunction &MF) const;
|
||||||
|
|
||||||
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||||
|
Loading…
Reference in New Issue
Block a user