summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/XCore/XCoreFrameLowering.cpp62
-rw-r--r--lib/Target/XCore/XCoreFrameLowering.h3
-rw-r--r--lib/Target/XCore/XCoreMachineFunctionInfo.cpp16
-rw-r--r--lib/Target/XCore/XCoreMachineFunctionInfo.h9
-rw-r--r--lib/Target/XCore/XCoreRegisterInfo.cpp285
-rw-r--r--lib/Target/XCore/XCoreRegisterInfo.h13
-rw-r--r--test/CodeGen/XCore/epilogue_prologue.ll125
-rw-r--r--test/CodeGen/XCore/epilogue_prologue_fp.ll42
-rw-r--r--test/CodeGen/XCore/scavenging.ll70
9 files changed, 409 insertions, 216 deletions
diff --git a/lib/Target/XCore/XCoreFrameLowering.cpp b/lib/Target/XCore/XCoreFrameLowering.cpp
index 06eab7a4ce..ea25e71961 100644
--- a/lib/Target/XCore/XCoreFrameLowering.cpp
+++ b/lib/Target/XCore/XCoreFrameLowering.cpp
@@ -302,10 +302,11 @@ void XCoreFrameLowering::emitEpilogue(MachineFunction &MF,
} // else Don't erase the return instruction.
}
-bool XCoreFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- const std::vector<CalleeSavedInfo> &CSI,
- const TargetRegisterInfo *TRI) const {
+bool XCoreFrameLowering::
+spillCalleeSavedRegisters(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ const std::vector<CalleeSavedInfo> &CSI,
+ const TargetRegisterInfo *TRI) const {
if (CSI.empty())
return true;
@@ -337,10 +338,11 @@ bool XCoreFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
return true;
}
-bool XCoreFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- const std::vector<CalleeSavedInfo> &CSI,
- const TargetRegisterInfo *TRI) const{
+bool XCoreFrameLowering::
+restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ const std::vector<CalleeSavedInfo> &CSI,
+ const TargetRegisterInfo *TRI) const{
MachineFunction *MF = MBB.getParent();
const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
@@ -420,11 +422,10 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MBB.erase(I);
}
-void
-XCoreFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
- RegScavenger *RS) const {
+void XCoreFrameLowering::
+processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
+ RegScavenger *RS) const {
MachineFrameInfo *MFI = MF.getFrameInfo();
- const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo();
bool LRUsed = MF.getRegInfo().isPhysRegUsed(XCore::LR);
const TargetRegisterClass *RC = &XCore::GRRegsRegClass;
XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
@@ -434,7 +435,7 @@ XCoreFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
bool isVarArg = MF.getFunction()->isVarArg();
int FrameIdx;
if (! isVarArg) {
- // A fixed offset of 0 allows us to save / restore LR using entsp / retsp.
+ // A fixed offset of 0 allows us to save/restore LR using entsp/retsp.
FrameIdx = MFI->CreateFixedObject(RC->getSize(), 0, true);
} else {
FrameIdx = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(),
@@ -443,17 +444,32 @@ XCoreFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
XFI->setUsesLR(FrameIdx);
XFI->setLRSpillSlot(FrameIdx);
}
- if (RegInfo->requiresRegisterScavenging(MF)) {
- // Reserve a slot close to SP or frame pointer.
- RS->addScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
- RC->getAlignment(),
- false));
- }
- if (hasFP(MF)) {
- // A callee save register is used to hold the FP.
- // This needs saving / restoring in the epilogue / prologue.
+
+ // A callee save register is used to hold the FP.
+ // This needs saving / restoring in the epilogue / prologue.
+ if (hasFP(MF))
XFI->setFPSpillSlot(MFI->CreateStackObject(RC->getSize(),
RC->getAlignment(),
false));
- }
+}
+
+void XCoreFrameLowering::
+processFunctionBeforeFrameFinalized(MachineFunction &MF,
+ RegScavenger *RS) const {
+ assert(RS && "requiresRegisterScavenging failed");
+ MachineFrameInfo *MFI = MF.getFrameInfo();
+ const TargetRegisterClass *RC = &XCore::GRRegsRegClass;
+ XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
+ // Reserve slots close to SP or frame pointer for Scavenging spills.
+ // When using SP for small frames, we don't need any scratch registers.
+ // When using SP for large frames, we may need 2 scratch registers.
+ // When using FP, for large or small frames, we may need 1 scratch register.
+ if (XFI->isLargeFrame(MF) || hasFP(MF))
+ RS->addScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
+ RC->getAlignment(),
+ false));
+ if (XFI->isLargeFrame(MF) && !hasFP(MF))
+ RS->addScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
+ RC->getAlignment(),
+ false));
}
diff --git a/lib/Target/XCore/XCoreFrameLowering.h b/lib/Target/XCore/XCoreFrameLowering.h
index ebad62f2fa..6cd90c96e7 100644
--- a/lib/Target/XCore/XCoreFrameLowering.h
+++ b/lib/Target/XCore/XCoreFrameLowering.h
@@ -48,6 +48,9 @@ namespace llvm {
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
RegScavenger *RS = NULL) const;
+ void processFunctionBeforeFrameFinalized(MachineFunction &MF,
+ RegScavenger *RS = NULL) const;
+
//! Stack slot size (4 bytes)
static int stackSlotSize() {
return 4;
diff --git a/lib/Target/XCore/XCoreMachineFunctionInfo.cpp b/lib/Target/XCore/XCoreMachineFunctionInfo.cpp
index 7ca0672912..91b2976008 100644
--- a/lib/Target/XCore/XCoreMachineFunctionInfo.cpp
+++ b/lib/Target/XCore/XCoreMachineFunctionInfo.cpp
@@ -12,3 +12,19 @@
using namespace llvm;
void XCoreFunctionInfo::anchor() { }
+
+bool XCoreFunctionInfo::isLargeFrame(const MachineFunction &MF) const {
+ if (CachedEStackSize == -1) {
+ CachedEStackSize = MF.getFrameInfo()->estimateStackSize(MF);
+ }
+ // isLargeFrame() is used when deciding if spill slots should be added to
+ // allow eliminateFrameIndex() to scavenge registers.
+ // This is only required when there is no FP and offsets are greater than
+ // ~256KB (~64Kwords). Thus only for code run on the emulator!
+ //
+ // The arbitrary value of 0xf000 allows frames of up to ~240KB before spill
+ // slots are added for the use of eliminateFrameIndex() register scavenging.
+ // For frames less than 240KB, it is assumed that there will be less than
+ // 16KB of function arguments.
+ return CachedEStackSize > 0xf000;
+}
diff --git a/lib/Target/XCore/XCoreMachineFunctionInfo.h b/lib/Target/XCore/XCoreMachineFunctionInfo.h
index 69d5de3e03..4fa4ee5d9c 100644
--- a/lib/Target/XCore/XCoreMachineFunctionInfo.h
+++ b/lib/Target/XCore/XCoreMachineFunctionInfo.h
@@ -31,6 +31,7 @@ class XCoreFunctionInfo : public MachineFunctionInfo {
int LRSpillSlot;
int FPSpillSlot;
int VarArgsFrameIndex;
+ mutable int CachedEStackSize;
std::vector<std::pair<MCSymbol*, CalleeSavedInfo> > SpillLabels;
public:
@@ -38,13 +39,15 @@ public:
UsesLR(false),
LRSpillSlot(0),
FPSpillSlot(0),
- VarArgsFrameIndex(0) {}
+ VarArgsFrameIndex(0),
+ CachedEStackSize(-1) {}
explicit XCoreFunctionInfo(MachineFunction &MF) :
UsesLR(false),
LRSpillSlot(0),
FPSpillSlot(0),
- VarArgsFrameIndex(0) {}
+ VarArgsFrameIndex(0),
+ CachedEStackSize(-1) {}
~XCoreFunctionInfo() {}
@@ -60,6 +63,8 @@ public:
void setFPSpillSlot(int off) { FPSpillSlot = off; }
int getFPSpillSlot() const { return FPSpillSlot; }
+ bool isLargeFrame(const MachineFunction &MF) const;
+
std::vector<std::pair<MCSymbol*, CalleeSavedInfo> > &getSpillLabels() {
return SpillLabels;
}
diff --git a/lib/Target/XCore/XCoreRegisterInfo.cpp b/lib/Target/XCore/XCoreRegisterInfo.cpp
index 607e512b3e..7c2d842e77 100644
--- a/lib/Target/XCore/XCoreRegisterInfo.cpp
+++ b/lib/Target/XCore/XCoreRegisterInfo.cpp
@@ -57,6 +57,165 @@ static inline bool isImmU16(unsigned val) {
return val < (1 << 16);
}
+static void loadConstant(MachineBasicBlock::iterator II,
+ const TargetInstrInfo &TII,
+ unsigned DstReg, int64_t Value) {
+ MachineInstr &MI = *II;
+ MachineBasicBlock &MBB = *MI.getParent();
+ DebugLoc dl = MI.getDebugLoc();
+
+ if (isMask_32(Value)) {
+ int N = Log2_32(Value) + 1;
+ BuildMI(MBB, II, dl, TII.get(XCore::MKMSK_rus), DstReg).addImm(N);
+ } else if (isImmU16(Value)) {
+ int Opcode = isImmU6(Value) ? XCore::LDC_ru6 : XCore::LDC_lru6;
+ BuildMI(MBB, II, dl, TII.get(Opcode), DstReg).addImm(Value);
+ } else {
+ MachineConstantPool *ConstantPool = MBB.getParent()->getConstantPool();
+ const Constant *C = ConstantInt::get(
+ Type::getInt32Ty(MBB.getParent()->getFunction()->getContext()), Value);
+ unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4);
+ BuildMI(MBB, II, dl, TII.get(XCore::LDWCP_lru6), DstReg)
+ .addConstantPoolIndex(Idx);
+ }
+}
+
+static void InsertFPImmInst(MachineBasicBlock::iterator II,
+ const TargetInstrInfo &TII,
+ unsigned Reg, unsigned FrameReg, int Offset ) {
+ MachineInstr &MI = *II;
+ MachineBasicBlock &MBB = *MI.getParent();
+ DebugLoc dl = MI.getDebugLoc();
+
+ switch (MI.getOpcode()) {
+ case XCore::LDWFI:
+ BuildMI(MBB, II, dl, TII.get(XCore::LDW_2rus), Reg)
+ .addReg(FrameReg)
+ .addImm(Offset);
+ break;
+ case XCore::STWFI:
+ BuildMI(MBB, II, dl, TII.get(XCore::STW_2rus))
+ .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
+ .addReg(FrameReg)
+ .addImm(Offset);
+ break;
+ case XCore::LDAWFI:
+ BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l2rus), Reg)
+ .addReg(FrameReg)
+ .addImm(Offset);
+ break;
+ default:
+ llvm_unreachable("Unexpected Opcode");
+ }
+}
+
+static void InsertFPConstInst(MachineBasicBlock::iterator II,
+ const TargetInstrInfo &TII,
+ unsigned Reg, unsigned FrameReg,
+ int Offset, RegScavenger *RS ) {
+ assert(RS && "requiresRegisterScavenging failed");
+ MachineInstr &MI = *II;
+ MachineBasicBlock &MBB = *MI.getParent();
+ DebugLoc dl = MI.getDebugLoc();
+
+ unsigned ScratchOffset = RS->scavengeRegister(&XCore::GRRegsRegClass, II, 0);
+ RS->setUsed(ScratchOffset);
+ loadConstant(II, TII, ScratchOffset, Offset);
+
+ switch (MI.getOpcode()) {
+ case XCore::LDWFI:
+ BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg)
+ .addReg(FrameReg)
+ .addReg(ScratchOffset, RegState::Kill);
+ break;
+ case XCore::STWFI:
+ BuildMI(MBB, II, dl, TII.get(XCore::STW_l3r))
+ .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
+ .addReg(FrameReg)
+ .addReg(ScratchOffset, RegState::Kill);
+ break;
+ case XCore::LDAWFI:
+ BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg)
+ .addReg(FrameReg)
+ .addReg(ScratchOffset, RegState::Kill);
+ break;
+ default:
+ llvm_unreachable("Unexpected Opcode");
+ }
+}
+
+static void InsertSPImmInst(MachineBasicBlock::iterator II,
+ const TargetInstrInfo &TII,
+ unsigned Reg, int Offset) {
+ MachineInstr &MI = *II;
+ MachineBasicBlock &MBB = *MI.getParent();
+ DebugLoc dl = MI.getDebugLoc();
+ bool isU6 = isImmU6(Offset);
+ switch (MI.getOpcode()) {
+ int NewOpcode;
+ case XCore::LDWFI:
+ NewOpcode = (isU6) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6;
+ BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
+ .addImm(Offset);
+ break;
+ case XCore::STWFI:
+ NewOpcode = (isU6) ? XCore::STWSP_ru6 : XCore::STWSP_lru6;
+ BuildMI(MBB, II, dl, TII.get(NewOpcode))
+ .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
+ .addImm(Offset);
+ break;
+ case XCore::LDAWFI:
+ NewOpcode = (isU6) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6;
+ BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
+ .addImm(Offset);
+ break;
+ default:
+ llvm_unreachable("Unexpected Opcode");
+ }
+}
+
+static void InsertSPConstInst(MachineBasicBlock::iterator II,
+ const TargetInstrInfo &TII,
+ unsigned Reg, int Offset, RegScavenger *RS ) {
+ assert(RS && "requiresRegisterScavenging failed");
+ MachineInstr &MI = *II;
+ MachineBasicBlock &MBB = *MI.getParent();
+ DebugLoc dl = MI.getDebugLoc();
+ unsigned OpCode = MI.getOpcode();
+
+ unsigned ScratchBase;
+ if (OpCode==XCore::STWFI) {
+ ScratchBase = RS->scavengeRegister(&XCore::GRRegsRegClass, II, 0);
+ RS->setUsed(ScratchBase);
+ } else
+ ScratchBase = Reg;
+ BuildMI(MBB, II, dl, TII.get(XCore::LDAWSP_ru6), ScratchBase).addImm(0);
+ unsigned ScratchOffset = RS->scavengeRegister(&XCore::GRRegsRegClass, II, 0);
+ RS->setUsed(ScratchOffset);
+ loadConstant(II, TII, ScratchOffset, Offset);
+
+ switch (OpCode) {
+ case XCore::LDWFI:
+ BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg)
+ .addReg(ScratchBase, RegState::Kill)
+ .addReg(ScratchOffset, RegState::Kill);
+ break;
+ case XCore::STWFI:
+ BuildMI(MBB, II, dl, TII.get(XCore::STW_l3r))
+ .addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
+ .addReg(ScratchBase, RegState::Kill)
+ .addReg(ScratchOffset, RegState::Kill);
+ break;
+ case XCore::LDAWFI:
+ BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg)
+ .addReg(ScratchBase, RegState::Kill)
+ .addReg(ScratchOffset, RegState::Kill);
+ break;
+ default:
+ llvm_unreachable("Unexpected Opcode");
+ }
+}
+
bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) {
return MF.getMMI().hasDebugInfo() ||
MF.getFunction()->needsUnwindTableEntry();
@@ -88,15 +247,12 @@ BitVector XCoreRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
bool
XCoreRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const {
- const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
-
- // TODO can we estimate stack size?
- return TFI->hasFP(MF);
+ return true;
}
bool
XCoreRegisterInfo::trackLivenessAfterRegAlloc(const MachineFunction &MF) const {
- return requiresRegisterScavenging(MF);
+ return true;
}
bool
@@ -110,7 +266,6 @@ XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
RegScavenger *RS) const {
assert(SPAdj == 0 && "Unexpected");
MachineInstr &MI = *II;
- DebugLoc dl = MI.getDebugLoc();
MachineOperand &FrameOp = MI.getOperand(FIOperandNum);
int FrameIndex = FrameOp.getIndex();
@@ -146,124 +301,28 @@ XCoreRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0);
assert(Offset%4 == 0 && "Misaligned stack offset");
-
DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n");
-
Offset/=4;
- bool FP = TFI->hasFP(MF);
-
unsigned Reg = MI.getOperand(0).getReg();
- bool isKill = MI.getOpcode() == XCore::STWFI && MI.getOperand(0).isKill();
-
assert(XCore::GRRegsRegClass.contains(Reg) && "Unexpected register operand");
-
- MachineBasicBlock &MBB = *MI.getParent();
-
- if (FP) {
- bool isUs = isImmUs(Offset);
-
- if (!isUs) {
- if (!RS)
- report_fatal_error("eliminateFrameIndex Frame size too big: " +
- Twine(Offset));
- unsigned ScratchReg = RS->scavengeRegister(&XCore::GRRegsRegClass, II,
- SPAdj);
- loadConstant(MBB, II, ScratchReg, Offset, dl);
- switch (MI.getOpcode()) {
- case XCore::LDWFI:
- BuildMI(MBB, II, dl, TII.get(XCore::LDW_3r), Reg)
- .addReg(FrameReg)
- .addReg(ScratchReg, RegState::Kill);
- break;
- case XCore::STWFI:
- BuildMI(MBB, II, dl, TII.get(XCore::STW_l3r))
- .addReg(Reg, getKillRegState(isKill))
- .addReg(FrameReg)
- .addReg(ScratchReg, RegState::Kill);
- break;
- case XCore::LDAWFI:
- BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l3r), Reg)
- .addReg(FrameReg)
- .addReg(ScratchReg, RegState::Kill);
- break;
- default:
- llvm_unreachable("Unexpected Opcode");
- }
- } else {
- switch (MI.getOpcode()) {
- case XCore::LDWFI:
- BuildMI(MBB, II, dl, TII.get(XCore::LDW_2rus), Reg)
- .addReg(FrameReg)
- .addImm(Offset);
- break;
- case XCore::STWFI:
- BuildMI(MBB, II, dl, TII.get(XCore::STW_2rus))
- .addReg(Reg, getKillRegState(isKill))
- .addReg(FrameReg)
- .addImm(Offset);
- break;
- case XCore::LDAWFI:
- BuildMI(MBB, II, dl, TII.get(XCore::LDAWF_l2rus), Reg)
- .addReg(FrameReg)
- .addImm(Offset);
- break;
- default:
- llvm_unreachable("Unexpected Opcode");
- }
- }
+
+ if (TFI->hasFP(MF)) {
+ if (isImmUs(Offset))
+ InsertFPImmInst(II, TII, Reg, FrameReg, Offset);
+ else
+ InsertFPConstInst(II, TII, Reg, FrameReg, Offset, RS);
} else {
- bool isU6 = isImmU6(Offset);
- if (!isU6 && !isImmU16(Offset))
- report_fatal_error("eliminateFrameIndex Frame size too big: " +
- Twine(Offset));
-
- switch (MI.getOpcode()) {
- int NewOpcode;
- case XCore::LDWFI:
- NewOpcode = (isU6) ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6;
- BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
- .addImm(Offset);
- break;
- case XCore::STWFI:
- NewOpcode = (isU6) ? XCore::STWSP_ru6 : XCore::STWSP_lru6;
- BuildMI(MBB, II, dl, TII.get(NewOpcode))
- .addReg(Reg, getKillRegState(isKill))
- .addImm(Offset);
- break;
- case XCore::LDAWFI:
- NewOpcode = (isU6) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6;
- BuildMI(MBB, II, dl, TII.get(NewOpcode), Reg)
- .addImm(Offset);
- break;
- default:
- llvm_unreachable("Unexpected Opcode");
- }
+ if (isImmU16(Offset))
+ InsertSPImmInst(II, TII, Reg, Offset);
+ else
+ InsertSPConstInst(II, TII, Reg, Offset, RS);
}
// Erase old instruction.
+ MachineBasicBlock &MBB = *MI.getParent();
MBB.erase(II);
}
-void XCoreRegisterInfo::
-loadConstant(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
- unsigned DstReg, int64_t Value, DebugLoc dl) const {
- const TargetInstrInfo &TII = *MBB.getParent()->getTarget().getInstrInfo();
- if (isMask_32(Value)) {
- int N = Log2_32(Value) + 1;
- BuildMI(MBB, I, dl, TII.get(XCore::MKMSK_rus), DstReg).addImm(N);
- } else if (isImmU16(Value)) {
- int Opcode = isImmU6(Value) ? XCore::LDC_ru6 : XCore::LDC_lru6;
- BuildMI(MBB, I, dl, TII.get(Opcode), DstReg).addImm(Value);
- return;
- } else {
- MachineConstantPool *ConstantPool = MBB.getParent()->getConstantPool();
- const Constant *C = ConstantInt::get(
- Type::getInt32Ty(MBB.getParent()->getFunction()->getContext()), Value);
- unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4);
- BuildMI(MBB, I, dl, TII.get(XCore::LDWCP_lru6), DstReg)
- .addConstantPoolIndex(Idx);
- }
-}
unsigned XCoreRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
diff --git a/lib/Target/XCore/XCoreRegisterInfo.h b/lib/Target/XCore/XCoreRegisterInfo.h
index 2370c6280f..36ba7b46e5 100644
--- a/lib/Target/XCore/XCoreRegisterInfo.h
+++ b/lib/Target/XCore/XCoreRegisterInfo.h
@@ -24,19 +24,6 @@ namespace llvm {
class TargetInstrInfo;
struct XCoreRegisterInfo : public XCoreGenRegisterInfo {
-private:
- void loadConstant(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I,
- unsigned DstReg, int64_t Value, DebugLoc dl) const;
-
- void storeToStack(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I,
- unsigned SrcReg, int Offset, DebugLoc dl) const;
-
- void loadFromStack(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I,
- unsigned DstReg, int Offset, DebugLoc dl) const;
-
public:
XCoreRegisterInfo();
diff --git a/test/CodeGen/XCore/epilogue_prologue.ll b/test/CodeGen/XCore/epilogue_prologue.ll
index ffbe7a1571..2898ae5dc8 100644
--- a/test/CodeGen/XCore/epilogue_prologue.ll
+++ b/test/CodeGen/XCore/epilogue_prologue.ll
@@ -1,7 +1,11 @@
; RUN: llc < %s -march=xcore | FileCheck %s
; RUN: llc < %s -march=xcore -disable-fp-elim | FileCheck %s -check-prefix=CHECKFP
+; When using SP for small frames, we don't need any scratch registers (SR).
+; When using SP for large frames, we may need two scratch registers.
+; When using FP, for large or small frames, we may need one scratch register.
+; FP + small frame: spill FP+SR = entsp 2
; CHECKFP-LABEL: f1
; CHECKFP: entsp 2
; CHECKFP-NEXT: stw r10, sp[1]
@@ -10,6 +14,7 @@
; CHECKFP-NEXT: ldw r10, sp[1]
; CHECKFP-NEXT: retsp 2
;
+; !FP + small frame: no spills = no stack adjustment needed
; CHECK-LABEL: f1
; CHECK: stw lr, sp[0]
; CHECK: ldw lr, sp[0]
@@ -21,6 +26,7 @@ entry:
}
+; FP + small frame: spill FP+SR+R0+LR = entsp 3 + extsp 1
; CHECKFP-LABEL:f3
; CHECKFP: entsp 3
; CHECKFP-NEXT: stw r10, sp[1]
@@ -36,14 +42,15 @@ entry:
; CHECKFP-NEXT: ldw r10, sp[1]
; CHECKFP-NEXT: retsp 3
;
+; !FP + small frame: spill R0+LR = entsp 2
; CHECK-LABEL: f3
; CHECK: entsp 2
-; CHECK: stw [[REG:r[4-9]+]], sp[1]
-; CHECK: mov [[REG]], r0
-; CHECK: bl f2
-; CHECK: mov r0, [[REG]]
-; CHECK: ldw [[REG]], sp[1]
-; CHECK: retsp 2
+; CHECK-NEXT: stw [[REG:r[4-9]+]], sp[1]
+; CHECK-NEXT: mov [[REG]], r0
+; CHECK-NEXT: bl f2
+; CHECK-NEXT: mov r0, [[REG]]
+; CHECK-NEXT: ldw [[REG]], sp[1]
+; CHECK-NEXT: retsp 2
declare void @f2()
define i32 @f3(i32 %i) nounwind {
entry:
@@ -52,6 +59,7 @@ entry:
}
+; FP + large frame: spill FP+SR = entsp 2 + 100000
; CHECKFP-LABEL: f4
; CHECKFP: extsp 65535
; CHECKFP-NEXT: .Ltmp{{[0-9]+}}
@@ -71,23 +79,32 @@ entry:
; CHECKFP-NEXT: ldaw sp, sp[34467]
; CHECKFP-NEXT: retsp 0
;
+; !FP + large frame: spill SR+SR = entsp 2 + 100000
; CHECK-LABEL: f4
; CHECK: extsp 65535
; CHECK-NEXT: .Ltmp{{[0-9]+}}
; CHECK-NEXT: .cfi_def_cfa_offset 262140
-; CHECK-NEXT: extsp 34465
+; CHECK-NEXT: extsp 34467
; CHECK-NEXT: .Ltmp{{[0-9]+}}
-; CHECK-NEXT: .cfi_def_cfa_offset 400000
+; CHECK-NEXT: .cfi_def_cfa_offset 400008
; CHECK-NEXT: ldaw sp, sp[65535]
-; CHECK-NEXT: ldaw sp, sp[34465]
+; CHECK-NEXT: ldaw sp, sp[34467]
; CHECK-NEXT: retsp 0
define void @f4() {
entry:
- %0 = alloca [100000 x i32], align 4
+ %0 = alloca [100000 x i32]
ret void
}
+; FP + large frame: spill FP+SR+R4+LR = entsp 3 + 200000 + extsp 1
+; CHECKFP: .section .cp.rodata.cst4,"aMc",@progbits,4
+; CHECKFP-NEXT: .align 4
+; CHECKFP-NEXT: .LCPI[[CNST0:[0-9_]+]]:
+; CHECKFP-NEXT: .long 200002
+; CHECKFP-NEXT: .LCPI[[CNST1:[0-9_]+]]:
+; CHECKFP-NEXT: .long 200001
+; CHECKFP-NEXT: .text
; CHECKFP-LABEL: f6
; CHECKFP: entsp 65535
; CHECKFP-NEXT: .Ltmp{{[0-9]+}}
@@ -100,26 +117,47 @@ entry:
; CHECKFP-NEXT: extsp 65535
; CHECKFP-NEXT: .Ltmp{{[0-9]+}}
; CHECKFP-NEXT: .cfi_def_cfa_offset 786420
-; CHECKFP-NEXT: extsp 3396
+; CHECKFP-NEXT: extsp 3398
; CHECKFP-NEXT: .Ltmp{{[0-9]+}}
-; CHECKFP-NEXT: .cfi_def_cfa_offset 800004
+; CHECKFP-NEXT: .cfi_def_cfa_offset 800012
; CHECKFP-NEXT: stw r10, sp[1]
; CHECKFP-NEXT: .Ltmp{{[0-9]+}}
-; CHECKFP-NEXT: .cfi_offset 10, -800000
+; CHECKFP-NEXT: .cfi_offset 10, -800008
; CHECKFP-NEXT: ldaw r10, sp[0]
; CHECKFP-NEXT: .Ltmp{{[0-9]+}}
; CHECKFP-NEXT: .cfi_def_cfa_register 10
+; CHECKFP-NEXT: ldw r1, cp[.LCPI[[CNST0]]]
+; CHECKFP-NEXT: stw [[REG:r[4-9]+]], r10[r1]
+; CHECKFP-NEXT: .Ltmp{{[0-9]+}}
+; CHECKFP-NEXT: .cfi_offset 4, -4
+; CHECKFP-NEXT: mov [[REG]], r0
; CHECKFP-NEXT: extsp 1
; CHECKFP-NEXT: ldaw r0, r10[2]
; CHECKFP-NEXT: bl f5
; CHECKFP-NEXT: ldaw sp, sp[1]
+; CHECKFP-NEXT: ldw r1, cp[.LCPI3_1]
+; CHECKFP-NEXT: ldaw r0, r10[r1]
+; CHECKFP-NEXT: extsp 1
+; CHECKFP-NEXT: bl f5
+; CHECKFP-NEXT: ldaw sp, sp[1]
+; CHECKFP-NEXT: mov r0, [[REG]]
+; CHECKFP-NEXT: ldw r1, cp[.LCPI[[CNST0]]]
+; CHECKFP-NEXT: ldw [[REG]], r10[r1]
; 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
+; CHECKFP-NEXT: retsp 3398
;
+; !FP + large frame: spill SR+SR+R4+LR = entsp 4 + 200000
+; CHECK: .section .cp.rodata.cst4,"aMc",@progbits,4
+; CHECK-NEXT: .align 4
+; CHECK-NEXT: .LCPI[[CNST0:[0-9_]+]]:
+; CHECK-NEXT: .long 200003
+; CHECK-NEXT: .LCPI[[CNST1:[0-9_]+]]:
+; CHECK-NEXT: .long 200002
+; CHECK-NEXT: .text
; CHECK-LABEL: f6
; CHECK: entsp 65535
; CHECK-NEXT: .Ltmp{{[0-9]+}}
@@ -132,20 +170,65 @@ entry:
; CHECK-NEXT: extsp 65535
; CHECK-NEXT: .Ltmp{{[0-9]+}}
; CHECK-NEXT: .cfi_def_cfa_offset 786420
-; CHECK-NEXT: extsp 3395
+; CHECK-NEXT: extsp 3399
; CHECK-NEXT: .Ltmp{{[0-9]+}}
-; CHECK-NEXT: .cfi_def_cfa_offset 800000
-; CHECK-NEXT: ldaw r0, sp[1]
+; CHECK-NEXT: .cfi_def_cfa_offset 800016
+; CHECK-NEXT: ldaw r1, sp[0]
+; CHECK-NEXT: ldw r2, cp[.LCPI[[CNST0]]]
+; CHECK-NEXT: stw [[REG:r[4-9]+]], r1[r2]
+; CHECK-NEXT: .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .cfi_offset 4, -4
+; CHECK-NEXT: mov [[REG]], r0
+; CHECK-NEXT: ldaw r0, sp[3]
+; CHECK-NEXT: bl f5
+; CHECK-NEXT: ldaw r0, sp[0]
+; CHECK-NEXT: ldw r1, cp[.LCPI[[CNST1]]]
+; CHECK-NEXT: ldaw r0, r0[r1]
; CHECK-NEXT: bl f5
+; CHECK-NEXT: mov r0, [[REG]]
+; CHECK-NEXT: ldaw [[REG]], sp[0]
+; CHECK-NEXT: ldw r1, cp[.LCPI[[CNST0]]]
+; CHECK-NEXT: ldw [[REG]], [[REG]][r1]
; CHECK-NEXT: ldaw sp, sp[65535]
; CHECK-NEXT: ldaw sp, sp[65535]
; CHECK-NEXT: ldaw sp, sp[65535]
-; CHECK-NEXT: retsp 3395
+; CHECK-NEXT: retsp 3399
declare void @f5(i32*)
-define void @f6() {
+define i32 @f6(i32 %i) {
+entry:
+ %0 = alloca [200000 x i32]
+ %1 = getelementptr inbounds [200000 x i32]* %0, i32 0, i32 0
+ call void @f5(i32* %1)
+ %2 = getelementptr inbounds [200000 x i32]* %0, i32 0, i32 199999
+ call void @f5(i32* %2)
+ ret i32 %i
+}
+
+
+; FP + large frame: spill FP+SR+LR = entsp 2 + 32768 + extsp 1
+; CHECKFP-LABEL:f8
+; CHECKFP: entsp 32770
+; CHECKFP-NEXT: stw r10, sp[1]
+; CHECKFP-NEXT: ldaw r10, sp[0]
+; CHECKFP-NEXT: mkmsk r1, 15
+; CHECKFP-NEXT: ldaw r0, r10[r1]
+; CHECKFP-NEXT: extsp 1
+; CHECKFP-NEXT: bl f5
+; CHECKFP-NEXT: ldaw sp, sp[1]
+; CHECKFP-NEXT: set sp, r10
+; CHECKFP-NEXT: ldw r10, sp[1]
+; CHECKFP-NEXT: retsp 32770
+;
+; !FP + large frame: spill SR+SR+LR = entsp 3 + 32768
+; CHECK-LABEL:f8
+; CHECK: entsp 32771
+; CHECK-NEXT: ldaw r0, sp[32768]
+; CHECK-NEXT: bl f5
+; CHECK-NEXT: retsp 32771
+define void @f8() nounwind {
entry:
- %0 = alloca [199999 x i32], align 4
- %1 = getelementptr inbounds [199999 x i32]* %0, i32 0, i32 0
+ %0 = alloca [32768 x i32]
+ %1 = getelementptr inbounds [32768 x i32]* %0, i32 0, i32 32765
call void @f5(i32* %1)
ret void
}
diff --git a/test/CodeGen/XCore/epilogue_prologue_fp.ll b/test/CodeGen/XCore/epilogue_prologue_fp.ll
deleted file mode 100644
index 9b9837c90d..0000000000
--- a/test/CodeGen/XCore/epilogue_prologue_fp.ll
+++ /dev/null
@@ -1,42 +0,0 @@
-; Functions with frames > 256K bytes require a frame pointer to access the stack.
-; At present, functions must be compiled using '-fno-omit-frame-pointer'.
-; RUN: llc < %s -march=xcore -disable-fp-elim | FileCheck %s
-
-declare void @f0(i32*)
-
-; CHECK: .section .cp.rodata.cst4,"aMc",@progbits,4
-; CHECK: .LCPI[[NUM:[0-9_]+]]:
-; CHECK: .long 99999
-; CHECK: .text
-; CHECK-LABEL:f1
-; CHECK: entsp 65535
-; CHECK-NEXT: extsp 34465
-; CHECK-NEXT: stw r10, sp[1]
-; CHECK-NEXT: ldaw r10, sp[0]
-; CHECK-NEXT: ldw r1, cp[.LCPI[[NUM]]]
-; CHECK-NEXT: ldaw r0, r10[r1]
-; CHECK-NEXT: extsp 1
-; CHECK-NEXT: bl f0
-; CHECK-NEXT: ldaw sp, sp[1]
-; CHECK-NEXT: set sp, r10
-; CHECK-NEXT: ldw r10, sp[1]
-; CHECK-NEXT: ldaw sp, sp[65535]
-; CHECK-NEXT: retsp 34465
-define void @f1() nounwind {
-entry:
- %0 = alloca [99998 x i32]
- %1 = getelementptr inbounds [99998 x i32]* %0, i32 0, i32 99997
- call void @f0(i32* %1)
- ret void
-}
-
-; CHECK-LABEL:f2
-; CHECK: mkmsk [[REG:r[0-9]+]], 15
-; CHECK-NEXT: ldaw r0, r10{{\[}}[[REG]]{{\]}}
-define void @f2() nounwind {
-entry:
- %0 = alloca [32768 x i32]
- %1 = getelementptr inbounds [32768 x i32]* %0, i32 0, i32 32765
- call void @f0(i32* %1)
- ret void
-}
diff --git a/test/CodeGen/XCore/scavenging.ll b/test/CodeGen/XCore/scavenging.ll
index 5b612d0f9b..f96ecd3fc2 100644
--- a/test/CodeGen/XCore/scavenging.ll
+++ b/test/CodeGen/XCore/scavenging.ll
@@ -1,4 +1,5 @@
-; RUN: llc < %s -march=xcore
+; RUN: llc < %s -march=xcore | FileCheck %s
+
@size = global i32 0 ; <i32*> [#uses=1]
@g0 = external global i32 ; <i32*> [#uses=2]
@g1 = external global i32 ; <i32*> [#uses=2]
@@ -48,5 +49,70 @@ entry:
call void @g(i32* %x1, i32* %1) nounwind
ret void
}
-
declare void @g(i32*, i32*)
+
+
+; CHECK: .section .cp.rodata.cst4,"aMc",@progbits,4
+; CHECK: .align 4
+; CHECK: [[ARG5:.LCPI[0-9_]+]]:
+; CHECK: .long 100003
+; CHECK: [[INDEX0:.LCPI[0-9_]+]]:
+; CHECK: .long 80002
+; CHECK: [[INDEX1:.LCPI[0-9_]+]]:
+; CHECK: .long 81002
+; CHECK: [[INDEX2:.LCPI[0-9_]+]]:
+; CHECK: .long 82002
+; CHECK: [[INDEX3:.LCPI[0-9_]+]]:
+; CHECK: .long 83002
+; CHECK: [[INDEX4:.LCPI[0-9_]+]]:
+; CHECK: .long 84002
+; CHECK: .text
+; !FP + large frame: spill SR+SR = entsp 2 + 100000
+; CHECK-LABEL: ScavengeSlots:
+; CHECK: extsp 65535
+; CHECK: extsp 34467
+; scavenge r11
+; CHECK: ldaw r11, sp[0]
+; scavenge r4 using SR spill slot
+; CHECK: stw r4, sp[1]
+; CHECK: ldw r4, cp{{\[}}[[ARG5]]{{\]}}
+; r11 used to load 5th argument
+; CHECK: ldw r11, r11[r4]
+; CHECK: ldaw r4, sp[0]
+; scavenge r5 using SR spill slot
+; CHECK: stw r5, sp[0]
+; CHECK: ldw r5, cp{{\[}}[[INDEX0]]{{\]}}
+; r4 & r5 used by InsertSPConstInst() to emit STW_l3r instruction.
+; CHECK: stw r0, r4[r5]
+; CHECK: ldaw r0, sp[0]
+; CHECK: ldw r5, cp{{\[}}[[INDEX1]]{{\]}}
+; CHECK: stw r1, r0[r5]
+; CHECK: ldaw r0, sp[0]
+; CHECK: ldw r1, cp{{\[}}[[INDEX2]]{{\]}}
+; CHECK: stw r2, r0[r1]
+; CHECK: ldaw r0, sp[0]
+; CHECK: ldw r1, cp{{\[}}[[INDEX3]]{{\]}}
+; CHECK: stw r3, r0[r1]
+; CHECK: ldaw r0, sp[0]
+; CHECK: ldw r1, cp{{\[}}[[INDEX4]]{{\]}}
+; CHECK: stw r11, r0[r1]
+; CHECK: ldaw sp, sp[65535]
+; CHECK: ldaw sp, sp[34467]
+; CHECK: ldw r4, sp[1]
+; CHECK: ldw r5, sp[0]
+; CHECK: retsp 0
+define void @ScavengeSlots(i32 %r0, i32 %r1, i32 %r2, i32 %r3, i32 %r4) nounwind {
+entry:
+ %Data = alloca [100000 x i32]
+ %i0 = getelementptr inbounds [100000 x i32]* %Data, i32 0, i32 80000
+ store volatile i32 %r0, i32* %i0
+ %i1 = getelementptr inbounds [100000 x i32]* %Data, i32 0, i32 81000
+ store volatile i32 %r1, i32* %i1
+ %i2 = getelementptr inbounds [100000 x i32]* %Data, i32 0, i32 82000
+ store volatile i32 %r2, i32* %i2
+ %i3 = getelementptr inbounds [100000 x i32]* %Data, i32 0, i32 83000
+ store volatile i32 %r3, i32* %i3
+ %i4 = getelementptr inbounds [100000 x i32]* %Data, i32 0, i32 84000
+ store volatile i32 %r4, i32* %i4
+ ret void
+}