XCore Target: correct callee save register spilling when callsUnwindInit is true.
authorRobert Lytton <robert@xmos.com>
Mon, 6 Jan 2014 14:21:12 +0000 (14:21 +0000)
committerRobert Lytton <robert@xmos.com>
Mon, 6 Jan 2014 14:21:12 +0000 (14:21 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198616 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/XCore/XCoreFrameLowering.cpp
lib/Target/XCore/XCoreRegisterInfo.cpp
test/CodeGen/XCore/llvm-intrinsics.ll

index 109b74d445c52bcca78ded0da98177abe1547ee7..9950d78b50fc2663d4eff2316f2d4fe00e31bf0b 100644 (file)
@@ -335,6 +335,9 @@ spillCalleeSavedRegisters(MachineBasicBlock &MBB,
   for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin();
                                                     it != CSI.end(); ++it) {
     unsigned Reg = it->getReg();
+    assert(Reg != XCore::LR && !(Reg == XCore::R10 && hasFP(*MF)) &&
+           "LR & FP are always handled in emitPrologue");
+
     // Add the callee-saved register as live-in. It's killed at the spill.
     MBB.addLiveIn(Reg);
     const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
@@ -355,7 +358,6 @@ restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
                             const TargetRegisterInfo *TRI) const{
   MachineFunction *MF = MBB.getParent();
   const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
-
   bool AtStart = MI == MBB.begin();
   MachineBasicBlock::iterator BeforeI = MI;
   if (!AtStart)
@@ -363,6 +365,9 @@ restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
   for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin();
                                                     it != CSI.end(); ++it) {
     unsigned Reg = it->getReg();
+    assert(Reg != XCore::LR && !(Reg == XCore::R10 && hasFP(*MF)) &&
+           "LR & FP are always handled in emitEpilogue");
+
     const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
     TII.loadRegFromStackSlot(MBB, MI, Reg, it->getFrameIdx(), RC, TRI);
     assert(MI != MBB.begin() &&
@@ -442,6 +447,9 @@ processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
   if (!LRUsed && !MF.getFunction()->isVarArg() &&
       MF.getFrameInfo()->estimateStackSize(MF))
     LRUsed = true;
+  // We will be spilling all callee saved registers in case of unwinding.
+  if (MF.getMMI().callsUnwindInit())
+    LRUsed = true;
 
   // We will handling LR in the prologue/epilogue
   // and space on the stack ourselves.
index 7e594f406ada9f621be7eeccff5c94f112849b6c..367c79cc13c4cf8a154b893e760f51616ac72be5 100644 (file)
@@ -199,11 +199,21 @@ bool XCoreRegisterInfo::needsFrameMoves(const MachineFunction &MF) {
 
 const uint16_t* XCoreRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
                                                                          const {
+  // The callee saved registers LR & FP are explicitly handled during
+  // emitPrologue & emitEpilogue and releated functions.
   static const uint16_t CalleeSavedRegs[] = {
     XCore::R4, XCore::R5, XCore::R6, XCore::R7,
-    XCore::R8, XCore::R9, XCore::R10, XCore::LR,
+    XCore::R8, XCore::R9, XCore::R10,
     0
   };
+  static const uint16_t CalleeSavedRegsFP[] = {
+    XCore::R4, XCore::R5, XCore::R6, XCore::R7,
+    XCore::R8, XCore::R9,
+    0
+  };
+  const TargetFrameLowering *TFI = MF->getTarget().getFrameLowering();
+  if (TFI->hasFP(*MF))
+    return CalleeSavedRegsFP;
   return CalleeSavedRegs;
 }
 
index ac6453c8c7faf3d8fee8a643057beea8bae63d02..5650f9d8bda78dd70a25c72acb246d8d9c07611d 100644 (file)
@@ -1,6 +1,11 @@
 ; RUN: llc < %s -march=xcore | FileCheck %s
 
 declare i8* @llvm.frameaddress(i32) nounwind readnone
+declare i8* @llvm.returnaddress(i32) nounwind
+declare i8* @llvm.eh.dwarf.cfa(i32) nounwind
+declare void @llvm.eh.return.i32(i32, i8*) nounwind
+declare void @llvm.eh.unwind.init() nounwind
+
 define i8* @FA0() nounwind {
 entry:
 ; CHECK-LABEL: FA0
@@ -21,7 +26,6 @@ entry:
   ret i8* %1
 }
 
-declare i8* @llvm.returnaddress(i32) nounwind readnone
 define i8* @RA0() nounwind {
 entry:
 ; CHECK-LABEL: RA0
@@ -45,7 +49,6 @@ entry:
 }
 
 ; test FRAME_TO_ARGS_OFFSET lowering
-declare i8* @llvm.eh.dwarf.cfa(i32) nounwind
 define i8* @FTAO0() nounwind {
 entry:
 ; CHECK-LABEL: FTAO0
@@ -70,7 +73,6 @@ entry:
   ret i8* %1
 }
 
-declare void @llvm.eh.return.i32(i32, i8*)
 define i8* @EH0(i32 %offset, i8* %handler) {
 entry:
 ; CHECK-LABEL: EH0
@@ -130,3 +132,98 @@ entry:
   call void @llvm.eh.return.i32(i32 %0, i8* @handler)
   unreachable
 }
+
+
+; FP: spill FP+SR+R4:9 = entsp 2 + 6
+; CHECKFP-LABEL: Unwind0:
+; CHECKFP: entsp 8
+; CHECKFP: stw r10, sp[1]
+; CHECKFP: ldaw r10, sp[0]
+; CHECKFP: stw r4, r10[7]
+; CHECKFP: stw r5, r10[6]
+; CHECKFP: stw r6, r10[5]`
+; CHECKFP: stw r7, r10[4]
+; CHECKFP: stw r8, r10[3]
+; CHECKFP: stw r9, r10[2]
+; CHECKFP: ldw r9, r10[2]
+; CHECKFP: ldw r8, r10[3]
+; CHECKFP: ldw r7, r10[4]
+; CHECKFP: ldw r6, r10[5]
+; CHECKFP: ldw r5, r10[6]
+; CHECKFP: ldw r4, r10[7]
+; CHECKFP: set sp, r10
+; CHECKFP: ldw r10, sp[1]
+; CHECKFP: retsp 8
+;
+; !FP: spill R4:10 = entsp 7
+; CHECK-LABEL: Unwind0:
+; CHECK: entsp 7
+; CHECK: stw r4, sp[6]
+; CHECK: stw r5, sp[5]
+; CHECK: stw r6, sp[4]
+; CHECK: stw r7, sp[3]
+; CHECK: stw r8, sp[2]
+; CHECK: stw r9, sp[1]
+; CHECK: stw r10, sp[0]
+; CHECK: ldw r10, sp[0]
+; CHECK: ldw r9, sp[1]
+; CHECK: ldw r8, sp[2]
+; CHECK: ldw r7, sp[3]
+; CHECK: ldw r6, sp[4]
+; CHECK: ldw r5, sp[5]
+; CHECK: ldw r4, sp[6]
+; CHECK: retsp 7
+define void @Unwind0() {
+  call void @llvm.eh.unwind.init()
+  ret void
+}
+
+
+; FP: spill FP+SR+R4:9+LR = entsp 2 + 6 + extsp 1
+; CHECKFP-LABEL: Unwind1:
+; CHECKFP: entsp 8
+; CHECKFP: stw r10, sp[1]
+; CHECKFP: ldaw r10, sp[0]
+; CHECKFP: stw r4, r10[7]
+; CHECKFP: stw r5, r10[6]
+; CHECKFP: stw r6, r10[5]
+; CHECKFP: stw r7, r10[4]
+; CHECKFP: stw r8, r10[3]
+; CHECKFP: stw r9, r10[2]
+; CHECKFP: extsp 1
+; CHECKFP: bl foo
+; CHECKFP: ldaw sp, sp[1]
+; CHECKFP: ldw r9, r10[2]
+; CHECKFP: ldw r8, r10[3]
+; CHECKFP: ldw r7, r10[4]
+; CHECKFP: ldw r6, r10[5]
+; CHECKFP: ldw r5, r10[6]
+; CHECKFP: ldw r4, r10[7]
+; CHECKFP: set sp, r10
+; CHECKFP: ldw r10, sp[1]
+; CHECKFP: retsp 8
+;
+; !FP: spill R4:10+LR = entsp 7 + 1
+; CHECK-LABEL: Unwind1:
+; CHECK: entsp 8
+; CHECK: stw r4, sp[7]
+; CHECK: stw r5, sp[6]
+; CHECK: stw r6, sp[5]
+; CHECK: stw r7, sp[4]
+; CHECK: stw r8, sp[3]
+; CHECK: stw r9, sp[2]
+; CHECK: stw r10, sp[1]
+; CHECK: bl foo
+; CHECK: ldw r10, sp[1]
+; CHECK: ldw r9, sp[2]
+; CHECK: ldw r8, sp[3]
+; CHECK: ldw r7, sp[4]
+; CHECK: ldw r6, sp[5]
+; CHECK: ldw r5, sp[6]
+; CHECK: ldw r4, sp[7]
+; CHECK: retsp 8
+define void @Unwind1() {
+  call void (...)* @foo()
+  call void @llvm.eh.unwind.init()
+  ret void
+}