XCore target: Enable frames larger than 65535 to be lowered

llvm-svn: 196084
This commit is contained in:
Robert Lytton 2013-12-02 10:18:14 +00:00
parent e71e08d007
commit 9c8a9af745
2 changed files with 305 additions and 141 deletions

View File

@ -29,6 +29,9 @@
using namespace llvm;
static const unsigned FramePtr = XCore::R10;
static const int MaxImmU16 = (1<<16) - 1;
// helper functions. FIXME: Eliminate.
static inline bool isImmU6(unsigned val) {
return val < (1 << 6);
@ -38,34 +41,93 @@ static inline bool isImmU16(unsigned val) {
return val < (1 << 16);
}
static void loadFromStack(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned DstReg, int Offset, DebugLoc dl,
const TargetInstrInfo &TII) {
assert(Offset%4 == 0 && "Misaligned stack offset");
Offset/=4;
bool isU6 = isImmU6(Offset);
if (!isU6 && !isImmU16(Offset))
report_fatal_error("loadFromStack offset too big " + Twine(Offset));
int Opcode = isU6 ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6;
BuildMI(MBB, I, dl, TII.get(Opcode), DstReg)
.addImm(Offset);
static void EmitDefCfaRegister(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI, DebugLoc dl,
const TargetInstrInfo &TII,
MachineModuleInfo *MMI, unsigned DRegNum) {
MCSymbol *Label = MMI->getContext().CreateTempSymbol();
BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(Label);
MMI->addFrameInst(MCCFIInstruction::createDefCfaRegister(Label, DRegNum));
}
static void EmitDefCfaOffset(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI, DebugLoc dl,
const TargetInstrInfo &TII,
MachineModuleInfo *MMI, int Offset) {
MCSymbol *Label = MMI->getContext().CreateTempSymbol();
BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(Label);
MMI->addFrameInst(MCCFIInstruction::createDefCfaOffset(Label, -Offset));
}
static void storeToStack(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned SrcReg, int Offset, DebugLoc dl,
const TargetInstrInfo &TII) {
assert(Offset%4 == 0 && "Misaligned stack offset");
Offset/=4;
bool isU6 = isImmU6(Offset);
if (!isU6 && !isImmU16(Offset))
report_fatal_error("storeToStack offset too big " + Twine(Offset));
int Opcode = isU6 ? XCore::STWSP_ru6 : XCore::STWSP_lru6;
BuildMI(MBB, I, dl, TII.get(Opcode))
.addReg(SrcReg)
.addImm(Offset);
static void EmitCfiOffset(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI, DebugLoc dl,
const TargetInstrInfo &TII, MachineModuleInfo *MMI,
unsigned DRegNum, int Offset, MCSymbol *Label) {
if (!Label) {
Label = MMI->getContext().CreateTempSymbol();
BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(Label);
}
MMI->addFrameInst(MCCFIInstruction::createOffset(Label, DRegNum, Offset));
}
/// The SP register is moved in steps of 'MaxImmU16' towards the bottom of the
/// frame. During these steps, it may be necessary to spill registers.
/// IfNeededExtSP emits the necessary EXTSP instructions to move the SP only
/// as far as to make 'OffsetFromBottom' reachable using an STWSP_lru6.
/// \param OffsetFromTop the spill offset from the top of the frame.
/// \param [in] [out] Adjusted the current SP offset from the top of the frame.
static void IfNeededExtSP(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI, DebugLoc dl,
const TargetInstrInfo &TII, MachineModuleInfo *MMI,
int OffsetFromTop, int &Adjusted, int FrameSize,
bool emitFrameMoves) {
while (OffsetFromTop > Adjusted) {
assert(Adjusted < FrameSize && "OffsetFromTop is beyond FrameSize");
int remaining = FrameSize - Adjusted;
int OpImm = (remaining > MaxImmU16) ? MaxImmU16 : remaining;
int Opcode = isImmU6(OpImm) ? XCore::EXTSP_u6 : XCore::EXTSP_lu6;
BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(OpImm);
Adjusted += OpImm;
if (emitFrameMoves)
EmitDefCfaOffset(MBB, MBBI, dl, TII, MMI, Adjusted*4);
}
}
/// The SP register is moved in steps of 'MaxImmU16' towards the top of the
/// frame. During these steps, it may be necessary to re-load registers.
/// IfNeededLDAWSP emits the necessary LDAWSP instructions to move the SP only
/// as far as to make 'OffsetFromTop' reachable using an LDAWSP_lru6.
/// \param OffsetFromTop the spill offset from the top of the frame.
/// \param [in] [out] RemainingAdj the current SP offset from the top of the frame.
static void IfNeededLDAWSP(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI, DebugLoc dl,
const TargetInstrInfo &TII, int OffsetFromTop,
int &RemainingAdj) {
while (OffsetFromTop < RemainingAdj - MaxImmU16) {
assert(RemainingAdj && "OffsetFromTop is beyond FrameSize");
int OpImm = (RemainingAdj > MaxImmU16) ? MaxImmU16 : RemainingAdj;
int Opcode = isImmU6(OpImm) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6;
BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(OpImm);
RemainingAdj -= OpImm;
}
}
/// Creates an ordered list of registers that are spilled
/// during the emitPrologue/emitEpilogue.
/// Registers are ordered according to their frame offset.
static void GetSpillList(SmallVectorImpl<std::pair<unsigned,int> > &SpillList,
MachineFrameInfo *MFI, XCoreFunctionInfo *XFI,
bool fetchLR, bool fetchFP) {
int LRSpillOffset = fetchLR? MFI->getObjectOffset(XFI->getLRSpillSlot()) : 0;
int FPSpillOffset = fetchFP? MFI->getObjectOffset(XFI->getFPSpillSlot()) : 0;
if (fetchLR && fetchFP && LRSpillOffset > FPSpillOffset) {
SpillList.push_back(std::make_pair<unsigned,int>(XCore::LR,LRSpillOffset));
fetchLR = false;
}
if (fetchFP)
SpillList.push_back(std::make_pair<unsigned,int>(FramePtr, FPSpillOffset));
if (fetchLR)
SpillList.push_back(std::make_pair<unsigned,int>(XCore::LR,LRSpillOffset));
}
@ -80,7 +142,7 @@ XCoreFrameLowering::XCoreFrameLowering(const XCoreSubtarget &sti)
bool XCoreFrameLowering::hasFP(const MachineFunction &MF) const {
return MF.getTarget().Options.DisableFramePointerElim(MF) ||
MF.getFrameInfo()->hasVarSizedObjects();
MF.getFrameInfo()->hasVarSizedObjects();
}
void XCoreFrameLowering::emitPrologue(MachineFunction &MF) const {
@ -98,90 +160,69 @@ void XCoreFrameLowering::emitPrologue(MachineFunction &MF) const {
report_fatal_error("emitPrologue unsupported alignment: "
+ Twine(MFI->getMaxAlignment()));
bool FP = hasFP(MF);
const AttributeSet &PAL = MF.getFunction()->getAttributes();
if (PAL.hasAttrSomewhere(Attribute::Nest))
loadFromStack(MBB, MBBI, XCore::R11, 0, dl, TII);
BuildMI(MBB, MBBI, dl, TII.get(XCore::LDWSP_ru6), XCore::R11).addImm(0);
// Work out frame sizes.
int FrameSize = MFI->getStackSize();
assert(FrameSize%4 == 0 && "Misaligned frame size");
FrameSize/=4;
bool isU6 = isImmU6(FrameSize);
if (!isU6 && !isImmU16(FrameSize)) {
// FIXME could emit multiple instructions.
report_fatal_error("emitPrologue Frame size too big: " + Twine(FrameSize));
}
bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(MF);
// We will adjust the SP in stages towards the final FrameSize.
assert(MFI->getStackSize()%4 == 0 && "Misaligned frame size");
const int FrameSize = MFI->getStackSize() / 4;
int Adjusted = 0;
bool saveLR = XFI->getUsesLR();
// Do we need to allocate space on the stack?
if (FrameSize) {
bool LRSavedOnEntry = false;
int Opcode;
if (saveLR && (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0)) {
Opcode = (isU6) ? XCore::ENTSP_u6 : XCore::ENTSP_lu6;
MBB.addLiveIn(XCore::LR);
saveLR = false;
LRSavedOnEntry = true;
} else {
Opcode = (isU6) ? XCore::EXTSP_u6 : XCore::EXTSP_lu6;
}
BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize);
bool UseENTSP = saveLR && FrameSize
&& (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0);
if (UseENTSP)
saveLR = false;
bool FP = hasFP(MF);
bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(MF);
if (emitFrameMoves) {
// Show update of SP.
MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol();
BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel);
MMI->addFrameInst(MCCFIInstruction::createDefCfaOffset(FrameLabel,
-FrameSize*4));
if (LRSavedOnEntry) {
unsigned Reg = MRI->getDwarfRegNum(XCore::LR, true);
MMI->addFrameInst(MCCFIInstruction::createOffset(FrameLabel, Reg, 0));
}
}
}
if (saveLR) {
int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot());
storeToStack(MBB, MBBI, XCore::LR, LRSpillOffset + FrameSize*4, dl, TII);
if (UseENTSP) {
// Allocate space on the stack at the same time as saving LR.
Adjusted = (FrameSize > MaxImmU16) ? MaxImmU16 : FrameSize;
int Opcode = isImmU6(Adjusted) ? XCore::ENTSP_u6 : XCore::ENTSP_lu6;
BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(Adjusted);
MBB.addLiveIn(XCore::LR);
if (emitFrameMoves) {
MCSymbol *SaveLRLabel = MMI->getContext().CreateTempSymbol();
BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveLRLabel);
unsigned Reg = MRI->getDwarfRegNum(XCore::LR, true);
MMI->addFrameInst(MCCFIInstruction::createOffset(SaveLRLabel, Reg,
LRSpillOffset));
EmitDefCfaOffset(MBB, MBBI, dl, TII, MMI, Adjusted*4);
unsigned DRegNum = MRI->getDwarfRegNum(XCore::LR, true);
EmitCfiOffset(MBB, MBBI, dl, TII, MMI, DRegNum, 0, NULL);
}
}
// If necessary, save LR and FP to the stack, as we EXTSP.
SmallVector<std::pair<unsigned,int>,2> SpillList;
GetSpillList(SpillList, MFI, XFI, saveLR, FP);
for (unsigned i = 0, e = SpillList.size(); i != e; ++i) {
unsigned SpillReg = SpillList[i].first;
int SpillOffset = SpillList[i].second;
assert(SpillOffset % 4 == 0 && "Misaligned stack offset");
assert(SpillOffset <= 0 && "Unexpected positive stack offset");
int OffsetFromTop = - SpillOffset/4;
IfNeededExtSP(MBB, MBBI, dl, TII, MMI, OffsetFromTop, Adjusted, FrameSize,
emitFrameMoves);
int Offset = Adjusted - OffsetFromTop;
int Opcode = isImmU6(Offset) ? XCore::STWSP_ru6 : XCore::STWSP_lru6;
BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addReg(SpillReg).addImm(Offset);
MBB.addLiveIn(SpillReg);
if (emitFrameMoves) {
unsigned DRegNum = MRI->getDwarfRegNum(SpillReg, true);
EmitCfiOffset(MBB, MBBI, dl, TII, MMI, DRegNum, SpillOffset, NULL);
}
}
// Complete any remaining Stack adjustment.
IfNeededExtSP(MBB, MBBI, dl, TII, MMI, FrameSize, Adjusted, FrameSize,
emitFrameMoves);
assert(Adjusted==FrameSize && "IfNeededExtSP has not completed adjustment");
if (FP) {
// Save R10 to the stack.
int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot());
storeToStack(MBB, MBBI, XCore::R10, FPSpillOffset + FrameSize*4, dl, TII);
// R10 is live-in. It is killed at the spill.
MBB.addLiveIn(XCore::R10);
if (emitFrameMoves) {
MCSymbol *SaveR10Label = MMI->getContext().CreateTempSymbol();
BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveR10Label);
unsigned Reg = MRI->getDwarfRegNum(XCore::R10, true);
MMI->addFrameInst(MCCFIInstruction::createOffset(SaveR10Label, Reg,
FPSpillOffset));
}
// Set the FP from the SP.
unsigned FramePtr = XCore::R10;
BuildMI(MBB, MBBI, dl, TII.get(XCore::LDAWSP_ru6), FramePtr).addImm(0);
if (emitFrameMoves) {
// Show FP is now valid.
MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol();
BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel);
unsigned Reg = MRI->getDwarfRegNum(FramePtr, true);
MMI->addFrameInst(MCCFIInstruction::createDefCfaRegister(FrameLabel,
Reg));
}
if (emitFrameMoves)
EmitDefCfaRegister(MBB, MBBI, dl, TII, MMI,
MRI->getDwarfRegNum(FramePtr, true));
}
if (emitFrameMoves) {
@ -192,9 +233,8 @@ void XCoreFrameLowering::emitPrologue(MachineFunction &MF) const {
MCSymbol *SpillLabel = SpillLabels[I].first;
CalleeSavedInfo &CSI = SpillLabels[I].second;
int Offset = MFI->getObjectOffset(CSI.getFrameIdx());
unsigned Reg = MRI->getDwarfRegNum(CSI.getReg(), true);
MMI->addFrameInst(MCCFIInstruction::createOffset(SpillLabel, Reg,
Offset));
unsigned DRegNum = MRI->getDwarfRegNum(CSI.getReg(), true);
EmitCfiOffset(MBB, MBBI, dl, TII, MMI, DRegNum, Offset, SpillLabel);
}
}
}
@ -208,60 +248,58 @@ void XCoreFrameLowering::emitEpilogue(MachineFunction &MF,
XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
DebugLoc dl = MBBI->getDebugLoc();
bool FP = hasFP(MF);
if (FP) {
// Restore the stack pointer.
unsigned FramePtr = XCore::R10;
BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r))
.addReg(FramePtr);
}
// Work out frame sizes.
int FrameSize = MFI->getStackSize();
assert(FrameSize%4 == 0 && "Misaligned frame size");
FrameSize/=4;
bool isU6 = isImmU6(FrameSize);
if (!isU6 && !isImmU16(FrameSize)) {
// FIXME could emit multiple instructions.
report_fatal_error("emitEpilogue Frame size too big: " + Twine(FrameSize));
}
if (FP) {
// Restore R10
int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot());
FPSpillOffset += FrameSize*4;
loadFromStack(MBB, MBBI, XCore::R10, FPSpillOffset, dl, TII);
}
// We will adjust the SP in stages towards the final FrameSize.
int RemainingAdj = MFI->getStackSize();
assert(RemainingAdj%4 == 0 && "Misaligned frame size");
RemainingAdj /= 4;
bool restoreLR = XFI->getUsesLR();
if (restoreLR &&
(FrameSize == 0 || MFI->getObjectOffset(XFI->getLRSpillSlot()) != 0)) {
int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot());
LRSpillOffset += FrameSize*4;
loadFromStack(MBB, MBBI, XCore::LR, LRSpillOffset, dl, TII);
bool UseRETSP = restoreLR && RemainingAdj
&& (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0);
if (UseRETSP)
restoreLR = false;
bool FP = hasFP(MF);
if (FP) // Restore the stack pointer.
BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r)).addReg(FramePtr);
// If necessary, restore LR and FP from the stack, as we EXTSP.
SmallVector<std::pair<unsigned,int>,2> SpillList;
GetSpillList(SpillList, MFI, XFI, restoreLR, FP);
unsigned i = SpillList.size();
while (i--) {
unsigned SpilledReg = SpillList[i].first;
int SpillOffset = SpillList[i].second;
assert(SpillOffset % 4 == 0 && "Misaligned stack offset");
assert(SpillOffset <= 0 && "Unexpected positive stack offset");
int OffsetFromTop = - SpillOffset/4;
IfNeededLDAWSP(MBB, MBBI, dl, TII, OffsetFromTop, RemainingAdj);
int Offset = RemainingAdj - OffsetFromTop;
int Opcode = isImmU6(Offset) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6;
BuildMI(MBB, MBBI, dl, TII.get(Opcode), SpilledReg).addImm(Offset);
}
if (FrameSize) {
if (restoreLR) {
if (RemainingAdj) {
// Complete all but one of the remaining Stack adjustments.
IfNeededLDAWSP(MBB, MBBI, dl, TII, 0, RemainingAdj);
if (UseRETSP) {
// Fold prologue into return instruction
assert(MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0);
assert(MBBI->getOpcode() == XCore::RETSP_u6
|| MBBI->getOpcode() == XCore::RETSP_lu6);
int Opcode = (isU6) ? XCore::RETSP_u6 : XCore::RETSP_lu6;
MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize);
|| MBBI->getOpcode() == XCore::RETSP_lu6);
int Opcode = isImmU6(RemainingAdj) ? XCore::RETSP_u6 : XCore::RETSP_lu6;
MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opcode))
.addImm(RemainingAdj);
for (unsigned i = 3, e = MBBI->getNumOperands(); i < e; ++i)
MIB->addOperand(MBBI->getOperand(i)); // copy any variadic operands
MBB.erase(MBBI);
MBB.erase(MBBI); // Erase the previous return instruction.
} else {
int Opcode = (isU6) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6;
BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(FrameSize);
int Opcode = isImmU6(RemainingAdj) ? XCore::LDAWSP_ru6 :
XCore::LDAWSP_lru6;
BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(RemainingAdj);
// Don't erase the return instruction.
}
}
} // else Don't erase the return instruction.
}
bool XCoreFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
@ -278,7 +316,8 @@ bool XCoreFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(*MF);
DebugLoc DL;
if (MI != MBB.end()) DL = MI->getDebugLoc();
if (MI != MBB.end())
DL = MI->getDebugLoc();
for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin();
it != CSI.end(); ++it) {

View File

@ -1,5 +1,15 @@
; RUN: llc < %s -march=xcore | FileCheck %s
; RUN: llc < %s -march=xcore -disable-fp-elim | FileCheck %s -check-prefix=CHECKFP
; CHECKFP-LABEL: f1
; CHECKFP: entsp 2
; CHECKFP-NEXT: stw r10, sp[1]
; CHECKFP-NEXT: ldaw r10, sp[0]
; CHECKFP: set sp, r10
; CHECKFP-NEXT: ldw r10, sp[1]
; CHECKFP-NEXT: retsp 2
;
; CHECK-LABEL: f1
; CHECK: stw lr, sp[0]
; CHECK: ldw lr, sp[0]
@ -10,6 +20,22 @@ entry:
ret void
}
; CHECKFP-LABEL:f3
; CHECKFP: entsp 3
; CHECKFP-NEXT: stw r10, sp[1]
; CHECKFP-NEXT: ldaw r10, sp[0]
; CHECKFP-NEXT: stw [[REG:r[4-9]+]], r10[2]
; CHECKFP-NEXT: mov [[REG]], r0
; CHECKFP-NEXT: extsp 1
; CHECKFP-NEXT: bl f2
; CHECKFP-NEXT: ldaw sp, sp[1]
; CHECKFP-NEXT: mov r0, [[REG]]
; CHECKFP-NEXT: ldw [[REG]], r10[2]
; CHECKFP-NEXT: set sp, r10
; CHECKFP-NEXT: ldw r10, sp[1]
; CHECKFP-NEXT: retsp 3
;
; CHECK-LABEL: f3
; CHECK: entsp 2
; CHECK: stw [[REG:r[4-9]+]], sp[1]
@ -24,3 +50,102 @@ entry:
call void @f2()
ret i32 %i
}
; CHECKFP-LABEL: f4
; CHECKFP: extsp 65535
; CHECKFP-NEXT: .Ltmp{{[0-9]+}}
; CHECKFP-NEXT: .cfi_def_cfa_offset 262140
; CHECKFP-NEXT: extsp 34467
; CHECKFP-NEXT: .Ltmp{{[0-9]+}}
; CHECKFP-NEXT: .cfi_def_cfa_offset 400008
; CHECKFP-NEXT: stw r10, sp[1]
; CHECKFP-NEXT: .Ltmp{{[0-9]+}}
; CHECKFP-NEXT: .cfi_offset 10, -400004
; CHECKFP-NEXT: ldaw r10, sp[0]
; CHECKFP-NEXT: .Ltmp{{[0-9]+}}
; CHECKFP-NEXT: .cfi_def_cfa_register 10
; CHECKFP-NEXT: set sp, r10
; CHECKFP-NEXT: ldw r10, sp[1]
; CHECKFP-NEXT: ldaw sp, sp[65535]
; CHECKFP-NEXT: ldaw sp, sp[34467]
; CHECKFP-NEXT: retsp 0
;
; CHECK-LABEL: f4
; CHECK: extsp 65535
; CHECK-NEXT: .Ltmp{{[0-9]+}}
; CHECK-NEXT: .cfi_def_cfa_offset 262140
; CHECK-NEXT: extsp 34465
; CHECK-NEXT: .Ltmp{{[0-9]+}}
; CHECK-NEXT: .cfi_def_cfa_offset 400000
; CHECK-NEXT: ldaw sp, sp[65535]
; CHECK-NEXT: ldaw sp, sp[34465]
; CHECK-NEXT: retsp 0
define void @f4() {
entry:
%0 = alloca [100000 x i32], align 4
ret void
}
; CHECKFP-LABEL: f6
; CHECKFP: entsp 65535
; CHECKFP-NEXT: .Ltmp{{[0-9]+}}
; CHECKFP-NEXT: .cfi_def_cfa_offset 262140
; CHECKFP-NEXT: .Ltmp{{[0-9]+}}
; CHECKFP-NEXT: .cfi_offset 15, 0
; CHECKFP-NEXT: extsp 65535
; CHECKFP-NEXT: .Ltmp{{[0-9]+}}
; CHECKFP-NEXT: .cfi_def_cfa_offset 524280
; CHECKFP-NEXT: extsp 65535
; CHECKFP-NEXT: .Ltmp{{[0-9]+}}
; CHECKFP-NEXT: .cfi_def_cfa_offset 786420
; CHECKFP-NEXT: extsp 3396
; CHECKFP-NEXT: .Ltmp{{[0-9]+}}
; CHECKFP-NEXT: .cfi_def_cfa_offset 800004
; CHECKFP-NEXT: stw r10, sp[1]
; CHECKFP-NEXT: .Ltmp{{[0-9]+}}
; CHECKFP-NEXT: .cfi_offset 10, -800000
; CHECKFP-NEXT: ldaw r10, sp[0]
; CHECKFP-NEXT: .Ltmp{{[0-9]+}}
; CHECKFP-NEXT: .cfi_def_cfa_register 10
; CHECKFP-NEXT: extsp 1
; CHECKFP-NEXT: ldaw r0, r10[2]
; CHECKFP-NEXT: bl f5
; CHECKFP-NEXT: ldaw sp, sp[1]
; CHECKFP-NEXT: set sp, r10
; CHECKFP-NEXT: ldw r10, sp[1]
; CHECKFP-NEXT: ldaw sp, sp[65535]
; CHECKFP-NEXT: ldaw sp, sp[65535]
; CHECKFP-NEXT: ldaw sp, sp[65535]
; CHECKFP-NEXT: retsp 3396
;
; CHECK-LABEL: f6
; CHECK: entsp 65535
; CHECK-NEXT: .Ltmp{{[0-9]+}}
; CHECK-NEXT: .cfi_def_cfa_offset 262140
; CHECK-NEXT: .Ltmp{{[0-9]+}}
; CHECK-NEXT: .cfi_offset 15, 0
; CHECK-NEXT: extsp 65535
; CHECK-NEXT: .Ltmp{{[0-9]+}}
; CHECK-NEXT: .cfi_def_cfa_offset 524280
; CHECK-NEXT: extsp 65535
; CHECK-NEXT: .Ltmp{{[0-9]+}}
; CHECK-NEXT: .cfi_def_cfa_offset 786420
; CHECK-NEXT: extsp 3395
; CHECK-NEXT: .Ltmp{{[0-9]+}}
; CHECK-NEXT: .cfi_def_cfa_offset 800000
; CHECK-NEXT: ldaw r0, sp[1]
; CHECK-NEXT: bl f5
; CHECK-NEXT: ldaw sp, sp[65535]
; CHECK-NEXT: ldaw sp, sp[65535]
; CHECK-NEXT: ldaw sp, sp[65535]
; CHECK-NEXT: retsp 3395
declare void @f5(i32*)
define void @f6() {
entry:
%0 = alloca [199999 x i32], align 4
%1 = getelementptr inbounds [199999 x i32]* %0, i32 0, i32 0
call void @f5(i32* %1)
ret void
}