mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-26 21:32:10 +00:00
Enable ARM base pointer when calling functions with large arguments.
When an outgoing call takes more than 2k of arguments on the stack, we don't allocate that call frame in the prolog, but adjust the stack pointer immediately before the call instead. This causes problems with the emergency spill slot because PEI can't track stack pointer adjustments on the second pass, and if the outgoing arguments are too big, SP can't be used to reach the emergency spill slot at all. Work around these problems by ensuring there is a base or frame pointer that can be used to access the emergency spill slot. <rdar://problem/10917166> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151604 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
dfa1896b6b
commit
0f9d07fb25
@ -484,11 +484,16 @@ ARMBaseRegisterInfo::avoidWriteAfterWrite(const TargetRegisterClass *RC) const {
|
||||
bool ARMBaseRegisterInfo::hasBasePointer(const MachineFunction &MF) const {
|
||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
|
||||
|
||||
if (!EnableBasePointer)
|
||||
return false;
|
||||
|
||||
if (needsStackRealignment(MF) && MFI->hasVarSizedObjects())
|
||||
// When outgoing call frames are so large that we adjust the stack pointer
|
||||
// around the call, we can no longer use the stack pointer to reach the
|
||||
// emergency spill slot.
|
||||
if (needsStackRealignment(MF) && (MFI->hasVarSizedObjects() ||
|
||||
!TFI->hasReservedCallFrame(MF)))
|
||||
return true;
|
||||
|
||||
// Thumb has trouble with negative offsets from the FP. Thumb2 has a limited
|
||||
@ -1056,6 +1061,21 @@ ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
|
||||
int Offset = TFI->ResolveFrameIndexReference(MF, FrameIndex, FrameReg, SPAdj);
|
||||
|
||||
// PEI::scavengeFrameVirtualRegs() cannot accurately track SPAdj because the
|
||||
// call frame setup/destroy instructions have already been eliminated. That
|
||||
// means the stack pointer cannot be used to access the emergency spill slot
|
||||
// when !hasReservedCallFrame().
|
||||
#ifndef NDEBUG
|
||||
if (RS && FrameReg == ARM::SP && FrameIndex == RS->getScavengingFrameIndex()){
|
||||
assert(TFI->hasReservedCallFrame(MF) &&
|
||||
"Cannot use SP to access the emergency spill slot in "
|
||||
"functions without a reserved call frame");
|
||||
assert(!MF.getFrameInfo()->hasVarSizedObjects() &&
|
||||
"Cannot use SP to access the emergency spill slot in "
|
||||
"functions with variable sized frame objects");
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
// Special handling of dbg_value instructions.
|
||||
if (MI.isDebugValue()) {
|
||||
MI.getOperand(i). ChangeToRegister(FrameReg, false /*isDef*/);
|
||||
|
@ -499,6 +499,10 @@ ARMFrameLowering::ResolveFrameIndexReference(const MachineFunction &MF,
|
||||
else if (AFI->isDPRCalleeSavedAreaFrame(FI))
|
||||
return Offset - AFI->getDPRCalleeSavedAreaOffset();
|
||||
|
||||
// SP can move around if there are allocas. We may also lose track of SP
|
||||
// when emergency spilling inside a non-reserved call frame setup.
|
||||
bool hasMovingSP = MFI->hasVarSizedObjects() || !hasReservedCallFrame(MF);
|
||||
|
||||
// When dynamically realigning the stack, use the frame pointer for
|
||||
// parameters, and the stack/base pointer for locals.
|
||||
if (RegInfo->needsStackRealignment(MF)) {
|
||||
@ -506,7 +510,7 @@ ARMFrameLowering::ResolveFrameIndexReference(const MachineFunction &MF,
|
||||
if (isFixed) {
|
||||
FrameReg = RegInfo->getFrameRegister(MF);
|
||||
Offset = FPOffset;
|
||||
} else if (MFI->hasVarSizedObjects()) {
|
||||
} else if (hasMovingSP) {
|
||||
assert(RegInfo->hasBasePointer(MF) &&
|
||||
"VLAs and dynamic stack alignment, but missing base pointer!");
|
||||
FrameReg = RegInfo->getBaseRegister();
|
||||
@ -518,11 +522,10 @@ ARMFrameLowering::ResolveFrameIndexReference(const MachineFunction &MF,
|
||||
if (hasFP(MF) && AFI->hasStackFrame()) {
|
||||
// Use frame pointer to reference fixed objects. Use it for locals if
|
||||
// there are VLAs (and thus the SP isn't reliable as a base).
|
||||
if (isFixed || (MFI->hasVarSizedObjects() &&
|
||||
!RegInfo->hasBasePointer(MF))) {
|
||||
if (isFixed || (hasMovingSP && !RegInfo->hasBasePointer(MF))) {
|
||||
FrameReg = RegInfo->getFrameRegister(MF);
|
||||
return FPOffset;
|
||||
} else if (MFI->hasVarSizedObjects()) {
|
||||
} else if (hasMovingSP) {
|
||||
assert(RegInfo->hasBasePointer(MF) && "missing base pointer!");
|
||||
if (AFI->isThumb2Function()) {
|
||||
// Try to use the frame pointer if we can, else use the base pointer
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/RegisterScavenging.h"
|
||||
#include "llvm/Target/TargetFrameLowering.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
@ -624,6 +625,21 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
FrameReg = BasePtr;
|
||||
}
|
||||
|
||||
// PEI::scavengeFrameVirtualRegs() cannot accurately track SPAdj because the
|
||||
// call frame setup/destroy instructions have already been eliminated. That
|
||||
// means the stack pointer cannot be used to access the emergency spill slot
|
||||
// when !hasReservedCallFrame().
|
||||
#ifndef NDEBUG
|
||||
if (RS && FrameReg == ARM::SP && FrameIndex == RS->getScavengingFrameIndex()){
|
||||
assert(MF.getTarget().getFrameLowering()->hasReservedCallFrame(MF) &&
|
||||
"Cannot use SP to access the emergency spill slot in "
|
||||
"functions without a reserved call frame");
|
||||
assert(!MF.getFrameInfo()->hasVarSizedObjects() &&
|
||||
"Cannot use SP to access the emergency spill slot in "
|
||||
"functions with variable sized frame objects");
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
// Special handling of dbg_value instructions.
|
||||
if (MI.isDebugValue()) {
|
||||
MI.getOperand(i). ChangeToRegister(FrameReg, false /*isDef*/);
|
||||
|
29
test/CodeGen/Thumb2/large-call.ll
Normal file
29
test/CodeGen/Thumb2/large-call.ll
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user