From 9409825b57cec078a2a90910978622073d31813d Mon Sep 17 00:00:00 2001 From: Robert Lytton Date: Tue, 18 Feb 2014 11:21:48 +0000 Subject: [PATCH] XCore target: Fix llvm.eh.return and EH info register handling git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@201561 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/XCore/XCoreFrameLowering.cpp | 137 ++++++--- lib/Target/XCore/XCoreMachineFunctionInfo.cpp | 12 + lib/Target/XCore/XCoreMachineFunctionInfo.h | 19 +- lib/Target/XCore/XCoreRegisterInfo.cpp | 2 +- test/CodeGen/XCore/llvm-intrinsics.ll | 280 +++++++++++++----- 5 files changed, 330 insertions(+), 120 deletions(-) diff --git a/lib/Target/XCore/XCoreFrameLowering.cpp b/lib/Target/XCore/XCoreFrameLowering.cpp index 9950d78b50f..8ea9788b1a8 100644 --- a/lib/Target/XCore/XCoreFrameLowering.cpp +++ b/lib/Target/XCore/XCoreFrameLowering.cpp @@ -25,8 +25,11 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetOptions.h" +#include // std::sort + using namespace llvm; static const unsigned FramePtr = XCore::R10; @@ -115,21 +118,58 @@ static void IfNeededLDAWSP(MachineBasicBlock &MBB, /// 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 > &SpillList, +/// As offsets are negative, the largest offsets will be first. +static void GetSpillList(SmallVectorImpl > &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::pair(XCore::LR, LRSpillOffset)); - fetchLR = false; + if (fetchLR) { + int Offset = MFI->getObjectOffset(XFI->getLRSpillSlot()); + SpillList.push_back(std::pair(Offset, XCore::LR)); + } + if (fetchFP) { + int Offset = MFI->getObjectOffset(XFI->getFPSpillSlot()); + SpillList.push_back(std::pair(Offset, FramePtr)); } - if (fetchFP) - SpillList.push_back(std::pair(FramePtr, FPSpillOffset)); - if (fetchLR) - SpillList.push_back(std::pair(XCore::LR, LRSpillOffset)); + std::sort(SpillList.begin(), SpillList.end()); +} + +/// Creates an ordered list of EH info register 'spills'. +/// These slots are only used by the unwinder and calls to llvm.eh.return(). +/// Registers are ordered according to their frame offset. +/// As offsets are negative, the largest offsets will be first. +static void GetEHSpillList(SmallVectorImpl > &SpillList, + MachineFrameInfo *MFI, XCoreFunctionInfo *XFI, + const TargetLowering *TL) { + assert(XFI->hasEHSpillSlot() && "There are no EH register spill slots"); + const int* EHSlot = XFI->getEHSpillSlot(); + SpillList.push_back( + std::pair(MFI->getObjectOffset(EHSlot[0]), + TL->getExceptionPointerRegister())); + SpillList.push_back( + std::pair(MFI->getObjectOffset(EHSlot[1]), + TL->getExceptionSelectorRegister())); + std::sort(SpillList.begin(), SpillList.end()); } +/// Restore clobbered registers with their spill slot value. +/// The SP will be adjusted at the same time, thus the SpillList must be ordered +/// with the largest (negative) offsets first. +static void +RestoreSpillList(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + DebugLoc dl, const TargetInstrInfo &TII, int &RemainingAdj, + SmallVectorImpl > &SpillList) { + for (unsigned i = 0, e = SpillList.size(); i != e; ++i) { + unsigned SpilledReg = SpillList[i].second; + int SpillOffset = SpillList[i].first; + 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); + } +} //===----------------------------------------------------------------------===// // XCoreFrameLowering: @@ -194,11 +234,13 @@ void XCoreFrameLowering::emitPrologue(MachineFunction &MF) const { } // If necessary, save LR and FP to the stack, as we EXTSP. - SmallVector,2> SpillList; + SmallVector,2> SpillList; GetSpillList(SpillList, MFI, XFI, saveLR, FP); + // We want the nearest (negative) offsets first, so reverse list. + std::reverse(SpillList.begin(),SpillList.end()); for (unsigned i = 0, e = SpillList.size(); i != e; ++i) { - unsigned SpillReg = SpillList[i].first; - int SpillOffset = SpillList[i].second; + unsigned SpillReg = SpillList[i].second; + int SpillOffset = SpillList[i].first; assert(SpillOffset % 4 == 0 && "Misaligned stack offset"); assert(SpillOffset <= 0 && "Unexpected positive stack offset"); int OffsetFromTop = - SpillOffset/4; @@ -239,6 +281,19 @@ void XCoreFrameLowering::emitPrologue(MachineFunction &MF) const { unsigned DRegNum = MRI->getDwarfRegNum(CSI.getReg(), true); EmitCfiOffset(MBB, MBBI, dl, TII, MMI, DRegNum, Offset, SpillLabel); } + if (XFI->hasEHSpillSlot()) { + // The unwinder requires stack slot & CFI offsets for the exception info. + // We do not save/spill these registers. + SmallVector,2> SpillList; + GetEHSpillList(SpillList, MFI, XFI, MF.getTarget().getTargetLowering()); + assert(SpillList.size()==2 && "Unexpected SpillList size"); + EmitCfiOffset(MBB, MBBI, dl, TII, MMI, + MRI->getDwarfRegNum(SpillList[0].second,true), + SpillList[0].first, NULL); + EmitCfiOffset(MBB, MBBI, dl, TII, MMI, + MRI->getDwarfRegNum(SpillList[1].second,true), + SpillList[1].first, NULL); + } } } @@ -252,7 +307,19 @@ void XCoreFrameLowering::emitEpilogue(MachineFunction &MF, DebugLoc dl = MBBI->getDebugLoc(); unsigned RetOpcode = MBBI->getOpcode(); + // Work out frame sizes. + // We will adjust the SP in stages towards the final FrameSize. + int RemainingAdj = MFI->getStackSize(); + assert(RemainingAdj%4 == 0 && "Misaligned frame size"); + RemainingAdj /= 4; + if (RetOpcode == XCore::EH_RETURN) { + // 'Restore' the exception info the unwinder has placed into the stack slots. + SmallVector,2> SpillList; + GetEHSpillList(SpillList, MFI, XFI, MF.getTarget().getTargetLowering()); + RestoreSpillList(MBB, MBBI, dl, TII, RemainingAdj, SpillList); + + // Return to the landing pad. unsigned EhStackReg = MBBI->getOperand(0).getReg(); unsigned EhHandlerReg = MBBI->getOperand(1).getReg(); BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r)).addReg(EhStackReg); @@ -261,12 +328,6 @@ void XCoreFrameLowering::emitEpilogue(MachineFunction &MF, return; } - // Work out frame sizes. - // 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->hasLRSpillSlot(); bool UseRETSP = restoreLR && RemainingAdj && (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0); @@ -278,20 +339,9 @@ void XCoreFrameLowering::emitEpilogue(MachineFunction &MF, BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r)).addReg(FramePtr); // If necessary, restore LR and FP from the stack, as we EXTSP. - SmallVector,2> SpillList; + SmallVector,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); - } + RestoreSpillList(MBB, MBBI, dl, TII, RemainingAdj, SpillList); if (RemainingAdj) { // Complete all but one of the remaining Stack adjustments. @@ -442,25 +492,32 @@ processFunctionBeforeCalleeSavedScan(MachineFunction &MF, XCoreFunctionInfo *XFI = MF.getInfo(); bool LRUsed = MF.getRegInfo().isPhysRegUsed(XCore::LR); - // If we need to extend the stack it is more efficient to use entsp / retsp. - // We force the LR to be saved so these instructions are used. + if (!LRUsed && !MF.getFunction()->isVarArg() && MF.getFrameInfo()->estimateStackSize(MF)) + // If we need to extend the stack it is more efficient to use entsp / retsp. + // We force the LR to be saved so these instructions are used. LRUsed = true; - // We will be spilling all callee saved registers in case of unwinding. - if (MF.getMMI().callsUnwindInit()) + + if (MF.getMMI().callsUnwindInit() || MF.getMMI().callsEHReturn()) { + // The unwinder expects to find spill slots for the exception info regs R0 + // & R1. These are used during llvm.eh.return() to 'restore' the exception + // info. N.B. we do not spill or restore R0, R1 during normal operation. + XFI->createEHSpillSlot(MF); + // As we will have a stack, we force the LR to be saved. LRUsed = true; + } - // We will handling LR in the prologue/epilogue - // and space on the stack ourselves. if (LRUsed) { + // We will handle the LR in the prologue/epilogue + // and allocate space on the stack ourselves. MF.getRegInfo().setPhysRegUnused(XCore::LR); XFI->createLRSpillSlot(MF); } - // A callee save register is used to hold the FP. - // This needs saving / restoring in the epilogue / prologue. if (hasFP(MF)) + // A callee save register is used to hold the FP. + // This needs saving / restoring in the epilogue / prologue. XFI->createFPSpillSlot(MF); } diff --git a/lib/Target/XCore/XCoreMachineFunctionInfo.cpp b/lib/Target/XCore/XCoreMachineFunctionInfo.cpp index c41a3d5f923..9ef9752d0a5 100644 --- a/lib/Target/XCore/XCoreMachineFunctionInfo.cpp +++ b/lib/Target/XCore/XCoreMachineFunctionInfo.cpp @@ -58,3 +58,15 @@ int XCoreFunctionInfo::createFPSpillSlot(MachineFunction &MF) { return FPSpillSlot; } +const int* XCoreFunctionInfo::createEHSpillSlot(MachineFunction &MF) { + if (EHSpillSlotSet) { + return EHSpillSlot; + } + const TargetRegisterClass *RC = &XCore::GRRegsRegClass; + MachineFrameInfo *MFI = MF.getFrameInfo(); + EHSpillSlot[0] = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(), true); + EHSpillSlot[1] = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(), true); + EHSpillSlotSet = true; + return EHSpillSlot; +} + diff --git a/lib/Target/XCore/XCoreMachineFunctionInfo.h b/lib/Target/XCore/XCoreMachineFunctionInfo.h index 6419c2fd65e..f1777a87e11 100644 --- a/lib/Target/XCore/XCoreMachineFunctionInfo.h +++ b/lib/Target/XCore/XCoreMachineFunctionInfo.h @@ -31,6 +31,8 @@ class XCoreFunctionInfo : public MachineFunctionInfo { int LRSpillSlot; bool FPSpillSlotSet; int FPSpillSlot; + bool EHSpillSlotSet; + int EHSpillSlot[2]; int VarArgsFrameIndex; mutable int CachedEStackSize; std::vector > SpillLabels; @@ -38,17 +40,15 @@ class XCoreFunctionInfo : public MachineFunctionInfo { public: XCoreFunctionInfo() : LRSpillSlotSet(false), - LRSpillSlot(0), FPSpillSlotSet(false), - FPSpillSlot(0), + EHSpillSlotSet(false), VarArgsFrameIndex(0), CachedEStackSize(-1) {} explicit XCoreFunctionInfo(MachineFunction &MF) : LRSpillSlotSet(false), - LRSpillSlot(0), FPSpillSlotSet(false), - FPSpillSlot(0), + EHSpillSlotSet(false), VarArgsFrameIndex(0), CachedEStackSize(-1) {} @@ -60,17 +60,24 @@ public: int createLRSpillSlot(MachineFunction &MF); bool hasLRSpillSlot() { return LRSpillSlotSet; } int getLRSpillSlot() const { - assert(LRSpillSlotSet && "LR Spill slot no set"); + assert(LRSpillSlotSet && "LR Spill slot not set"); return LRSpillSlot; } int createFPSpillSlot(MachineFunction &MF); bool hasFPSpillSlot() { return FPSpillSlotSet; } int getFPSpillSlot() const { - assert(FPSpillSlotSet && "FP Spill slot no set"); + assert(FPSpillSlotSet && "FP Spill slot not set"); return FPSpillSlot; } + const int* createEHSpillSlot(MachineFunction &MF); + bool hasEHSpillSlot() { return EHSpillSlotSet; } + const int* getEHSpillSlot() const { + assert(EHSpillSlotSet && "EH Spill slot not set"); + return EHSpillSlot; + } + bool isLargeFrame(const MachineFunction &MF) const; std::vector > &getSpillLabels() { diff --git a/lib/Target/XCore/XCoreRegisterInfo.cpp b/lib/Target/XCore/XCoreRegisterInfo.cpp index 367c79cc13c..d5a96d70b5e 100644 --- a/lib/Target/XCore/XCoreRegisterInfo.cpp +++ b/lib/Target/XCore/XCoreRegisterInfo.cpp @@ -200,7 +200,7 @@ 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. + // emitPrologue & emitEpilogue and related functions. static const uint16_t CalleeSavedRegs[] = { XCore::R4, XCore::R5, XCore::R6, XCore::R7, XCore::R8, XCore::R9, XCore::R10, diff --git a/test/CodeGen/XCore/llvm-intrinsics.ll b/test/CodeGen/XCore/llvm-intrinsics.ll index e7c78af2122..e0acd66e4a6 100644 --- a/test/CodeGen/XCore/llvm-intrinsics.ll +++ b/test/CodeGen/XCore/llvm-intrinsics.ll @@ -77,11 +77,18 @@ entry: define i8* @EH0(i32 %offset, i8* %handler) { entry: ; CHECK-LABEL: EH0 -; CHECK: ldc r2, 0 +; CHECK: entsp 2 +; CHECK: .cfi_def_cfa_offset 8 +; CHECK: .cfi_offset 15, 0 +; CHECK: .cfi_offset 1, -8 +; CHECK: .cfi_offset 0, -4 +; CHECK: ldc r2, 8 ; CHECK-NEXT: ldaw r3, sp[0] ; CHECK-NEXT: add r2, r3, r2 ; CHECK-NEXT: add r2, r2, r0 ; CHECK-NEXT: mov r3, r1 +; CHECK-NEXT: ldw r1, sp[0] +; CHECK-NEXT: ldw r0, sp[1] ; CHECK-NEXT: set sp, r2 ; CHECK-NEXT: bau r3 call void @llvm.eh.return.i32(i32 %offset, i8* %handler) @@ -92,19 +99,27 @@ declare void @foo(...) define i8* @EH1(i32 %offset, i8* %handler) { entry: ; CHECK-LABEL: EH1 -; CHECK: entsp 3 -; CHECK: stw r4, sp[2] -; CHECK: stw r5, sp[1] +; CHECK: entsp 5 +; CHECK: .cfi_def_cfa_offset 20 +; CHECK: .cfi_offset 15, 0 +; CHECK: .cfi_offset 1, -16 +; CHECK: .cfi_offset 0, -12 +; CHECK: stw r4, sp[4] +; CHECK: .cfi_offset 4, -4 +; CHECK: stw r5, sp[3] +; CHECK: .cfi_offset 5, -8 ; CHECK: mov r4, r1 ; CHECK-NEXT: mov r5, r0 ; CHECK-NEXT: bl foo -; CHECK-NEXT: ldc r0, 12 +; CHECK-NEXT: ldc r0, 20 ; CHECK-NEXT: ldaw r1, sp[0] ; CHECK-NEXT: add r0, r1, r0 ; CHECK-NEXT: add r2, r0, r5 ; CHECK-NEXT: mov r3, r4 -; CHECK-NEXT: ldw r5, sp[1] -; CHECK-NEXT: ldw r4, sp[2] +; CHECK-NEXT: ldw r5, sp[3] +; CHECK-NEXT: ldw r4, sp[4] +; CHECK-NEXT: ldw r1, sp[1] +; CHECK-NEXT: ldw r0, sp[2] ; CHECK-NEXT: set sp, r2 ; CHECK-NEXT: bau r3 call void (...)* @foo() @@ -117,14 +132,16 @@ entry: define i8* @EH2(i32 %r0, i32 %r1, i32 %r2, i32 %r3) { entry: ; CHECK-LABEL: EH2 -; CHECK: entsp 1 +; CHECK: entsp 3 ; CHECK: bl foo ; CHECK-NEXT: ldw r0, dp[offset] -; CHECK-NEXT: ldc r1, 4 +; CHECK-NEXT: ldc r1, 12 ; CHECK-NEXT: ldaw r2, sp[0] ; CHECK-NEXT: add r1, r2, r1 ; CHECK-NEXT: add r2, r1, r0 ; CHECK-NEXT: ldaw r3, dp[handler] +; CHECK-NEXT: ldw r1, sp[1] +; CHECK-NEXT: ldw r0, sp[2] ; CHECK-NEXT: set sp, r2 ; CHECK-NEXT: bau r3 call void (...)* @foo() @@ -134,96 +151,213 @@ entry: } -; FP: spill FP+SR+R4:9 = entsp 2 + 6 +; FP: spill FP+SR+R0:1+R4:9 = entsp 2+2+6 +; But we dont actually spill or restore R0:1 ; CHECKFP-LABEL: Unwind0: -; CHECKFP: entsp 8 +; CHECKFP: entsp 10 ; 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: stw r4, r10[9] +; CHECKFP: stw r5, r10[8] +; CHECKFP: stw r6, r10[7] +; CHECKFP: stw r7, r10[6] +; CHECKFP: stw r8, r10[5] +; CHECKFP: stw r9, r10[4] +; CHECKFP: ldw r9, r10[4] +; CHECKFP: ldw r8, r10[5] +; CHECKFP: ldw r7, r10[6] +; CHECKFP: ldw r6, r10[7] +; CHECKFP: ldw r5, r10[8] +; CHECKFP: ldw r4, r10[9] ; CHECKFP: set sp, r10 ; CHECKFP: ldw r10, sp[1] -; CHECKFP: retsp 8 +; CHECKFP: retsp 10 ; -; !FP: spill R4:10 = entsp 7 +; !FP: spill R0:1+R4:10 = entsp 2+7 +; But we dont actually spill or restore R0:1 ; 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 +; CHECK: entsp 9 +; CHECK: stw r4, sp[8] +; CHECK: stw r5, sp[7] +; CHECK: stw r6, sp[6] +; CHECK: stw r7, sp[5] +; CHECK: stw r8, sp[4] +; CHECK: stw r9, sp[3] +; CHECK: stw r10, sp[2] +; CHECK: ldw r10, sp[2] +; CHECK: ldw r9, sp[3] +; CHECK: ldw r8, sp[4] +; CHECK: ldw r7, sp[5] +; CHECK: ldw r6, sp[6] +; CHECK: ldw r5, sp[7] +; CHECK: ldw r4, sp[8] +; CHECK: retsp 9 define void @Unwind0() { call void @llvm.eh.unwind.init() ret void } -; FP: spill FP+SR+R4:9+LR = entsp 2 + 6 + extsp 1 +; FP: spill FP+SR+R0:1+R4:9+LR = entsp 2+2+6 + extsp 1 +; But we dont actually spill or restore R0:1 ; CHECKFP-LABEL: Unwind1: -; CHECKFP: entsp 8 +; CHECKFP: entsp 10 ; 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: stw r4, r10[9] +; CHECKFP: stw r5, r10[8] +; CHECKFP: stw r6, r10[7] +; CHECKFP: stw r7, r10[6] +; CHECKFP: stw r8, r10[5] +; CHECKFP: stw r9, r10[4] ; 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: ldw r9, r10[4] +; CHECKFP: ldw r8, r10[5] +; CHECKFP: ldw r7, r10[6] +; CHECKFP: ldw r6, r10[7] +; CHECKFP: ldw r5, r10[8] +; CHECKFP: ldw r4, r10[9] ; CHECKFP: set sp, r10 ; CHECKFP: ldw r10, sp[1] -; CHECKFP: retsp 8 +; CHECKFP: retsp 10 ; -; !FP: spill R4:10+LR = entsp 7 + 1 +; !FP: spill R0:1+R4:10+LR = entsp 2+7+1 +; But we dont actually spill or restore R0: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: entsp 10 +; CHECK: stw r4, sp[9] +; CHECK: stw r5, sp[8] +; CHECK: stw r6, sp[7] +; CHECK: stw r7, sp[6] +; CHECK: stw r8, sp[5] +; CHECK: stw r9, sp[4] +; CHECK: stw r10, sp[3] ; 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 +; CHECK: ldw r10, sp[3] +; CHECK: ldw r9, sp[4] +; CHECK: ldw r8, sp[5] +; CHECK: ldw r7, sp[6] +; CHECK: ldw r6, sp[7] +; CHECK: ldw r5, sp[8] +; CHECK: ldw r4, sp[9] +; CHECK: retsp 10 define void @Unwind1() { call void (...)* @foo() call void @llvm.eh.unwind.init() ret void } + +; FP: spill FP+SR+R0:1+R4:9 = entsp 2+2+6 +; We dont spill R0:1 +; We only restore R0:1 during eh.return +; CHECKFP-LABEL: UnwindEH: +; CHECKFP: entsp 10 +; CHECKFP: .cfi_def_cfa_offset 40 +; CHECKFP: .cfi_offset 15, 0 +; CHECKFP: stw r10, sp[1] +; CHECKFP: .cfi_offset 10, -36 +; CHECKFP: ldaw r10, sp[0] +; CHECKFP: .cfi_def_cfa_register 10 +; CHECKFP: .cfi_offset 1, -32 +; CHECKFP: .cfi_offset 0, -28 +; CHECKFP: stw r4, r10[9] +; CHECKFP: .cfi_offset 4, -4 +; CHECKFP: stw r5, r10[8] +; CHECKFP: .cfi_offset 5, -8 +; CHECKFP: stw r6, r10[7] +; CHECKFP: .cfi_offset 6, -12 +; CHECKFP: stw r7, r10[6] +; CHECKFP: .cfi_offset 7, -16 +; CHECKFP: stw r8, r10[5] +; CHECKFP: .cfi_offset 8, -20 +; CHECKFP: stw r9, r10[4] +; CHECKFP: .cfi_offset 9, -24 +; CHECKFP: bt r0, .LBB{{[0-9_]+}} +; CHECKFP: ldw r9, r10[4] +; CHECKFP-NEXT: ldw r8, r10[5] +; CHECKFP-NEXT: ldw r7, r10[6] +; CHECKFP-NEXT: ldw r6, r10[7] +; CHECKFP-NEXT: ldw r5, r10[8] +; CHECKFP-NEXT: ldw r4, r10[9] +; CHECKFP-NEXT: set sp, r10 +; CHECKFP-NEXT: ldw r10, sp[1] +; CHECKFP-NEXT: retsp 10 +; CHECKFP: .LBB{{[0-9_]+}} +; CHECKFP-NEXT: ldc r2, 40 +; CHECKFP-NEXT: add r2, r10, r2 +; CHECKFP-NEXT: add r0, r2, r0 +; CHECKFP-NEXT: mov r3, r1 +; CHECKFP-NEXT: mov r2, r0 +; CHECKFP-NEXT: ldw r9, r10[4] +; CHECKFP-NEXT: ldw r8, r10[5] +; CHECKFP-NEXT: ldw r7, r10[6] +; CHECKFP-NEXT: ldw r6, r10[7] +; CHECKFP-NEXT: ldw r5, r10[8] +; CHECKFP-NEXT: ldw r4, r10[9] +; CHECKFP-NEXT: ldw r1, sp[2] +; CHECKFP-NEXT: ldw r0, sp[3] +; CHECKFP-NEXT: set sp, r2 +; CHECKFP-NEXT: bau r3 +; +; !FP: spill R0:1+R4:10 = entsp 2+7 +; We dont spill R0:1 +; We only restore R0:1 during eh.return +; CHECK-LABEL: UnwindEH: +; CHECK: entsp 9 +; CHECK: .cfi_def_cfa_offset 36 +; CHECK: .cfi_offset 15, 0 +; CHECK: .cfi_offset 1, -36 +; CHECK: .cfi_offset 0, -32 +; CHECK: stw r4, sp[8] +; CHECK: .cfi_offset 4, -4 +; CHECK: stw r5, sp[7] +; CHECK: .cfi_offset 5, -8 +; CHECK: stw r6, sp[6] +; CHECK: .cfi_offset 6, -12 +; CHECK: stw r7, sp[5] +; CHECK: .cfi_offset 7, -16 +; CHECK: stw r8, sp[4] +; CHECK: .cfi_offset 8, -20 +; CHECK: stw r9, sp[3] +; CHECK: .cfi_offset 9, -24 +; CHECK: stw r10, sp[2] +; CHECK: .cfi_offset 10, -28 +; CHECK: bt r0, .LBB{{[0-9_]+}} +; CHECK: ldw r10, sp[2] +; CHECK-NEXT: ldw r9, sp[3] +; CHECK-NEXT: ldw r8, sp[4] +; CHECK-NEXT: ldw r7, sp[5] +; CHECK-NEXT: ldw r6, sp[6] +; CHECK-NEXT: ldw r5, sp[7] +; CHECK-NEXT: ldw r4, sp[8] +; CHECK-NEXT: retsp 9 +; CHECK: .LBB{{[0-9_]+}} +; CHECK-NEXT: ldc r2, 36 +; CHECK-NEXT: ldaw r3, sp[0] +; CHECK-NEXT: add r2, r3, r2 +; CHECK-NEXT: add r0, r2, r0 +; CHECK-NEXT: mov r3, r1 +; CHECK-NEXT: mov r2, r0 +; CHECK-NEXT: ldw r10, sp[2] +; CHECK-NEXT: ldw r9, sp[3] +; CHECK-NEXT: ldw r8, sp[4] +; CHECK-NEXT: ldw r7, sp[5] +; CHECK-NEXT: ldw r6, sp[6] +; CHECK-NEXT: ldw r5, sp[7] +; CHECK-NEXT: ldw r4, sp[8] +; CHECK-NEXT: ldw r1, sp[0] +; CHECK-NEXT: ldw r0, sp[1] +; CHECK-NEXT: set sp, r2 +; CHECK-NEXT: bau r3 +define void @UnwindEH(i32 %offset, i8* %handler) { + call void @llvm.eh.unwind.init() + %cmp = icmp eq i32 %offset, 0 + br i1 %cmp, label %normal, label %eh +eh: + call void @llvm.eh.return.i32(i32 %offset, i8* %handler) + unreachable +normal: + ret void +} -- 2.34.1