From ba584fe8feb840a82ad5966cb9eca6df0eeaafc2 Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Wed, 11 Jul 2012 00:53:32 +0000 Subject: [PATCH] Lower RETURNADDR node in Mips backend. Patch by Sasa Stankovic. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160031 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/MipsFrameLowering.cpp | 17 ++++++++++++----- lib/Target/Mips/MipsISelLowering.cpp | 18 ++++++++++++++++++ lib/Target/Mips/MipsISelLowering.h | 1 + test/CodeGen/Mips/return_address.ll | 23 +++++++++++++++++++++++ 4 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 test/CodeGen/Mips/return_address.ll diff --git a/lib/Target/Mips/MipsFrameLowering.cpp b/lib/Target/Mips/MipsFrameLowering.cpp index 95e2357dd7c..cb55995404c 100644 --- a/lib/Target/Mips/MipsFrameLowering.cpp +++ b/lib/Target/Mips/MipsFrameLowering.cpp @@ -273,14 +273,21 @@ spillCalleeSavedRegisters(MachineBasicBlock &MBB, const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); for (unsigned i = 0, e = CSI.size(); i != e; ++i) { - // Add the callee-saved register as live-in. - // It's killed at the spill. - EntryBlock->addLiveIn(CSI[i].getReg()); + // Add the callee-saved register as live-in. Do not add if the register is + // RA and return address is taken, because it has already been added in + // method MipsTargetLowering::LowerRETURNADDR. + // It's killed at the spill, unless the register is RA and return address + // is taken. + unsigned Reg = CSI[i].getReg(); + bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA || Reg == Mips::RA_64) + && MF->getFrameInfo()->isReturnAddressTaken(); + if (!IsRAAndRetAddrIsTaken) + EntryBlock->addLiveIn(Reg); // Insert the spill to the stack frame. - unsigned Reg = CSI[i].getReg(); + bool IsKill = !IsRAAndRetAddrIsTaken; const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); - TII.storeRegToStackSlot(*EntryBlock, MI, Reg, true, + TII.storeRegToStackSlot(*EntryBlock, MI, Reg, IsKill, CSI[i].getFrameIdx(), RC, TRI); } diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index ca002c0fc15..6858d84f08b 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -806,6 +806,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const case ISD::FCOPYSIGN: return LowerFCOPYSIGN(Op, DAG); case ISD::FABS: return LowerFABS(Op, DAG); case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); + case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG); case ISD::MEMBARRIER: return LowerMEMBARRIER(Op, DAG); case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG); case ISD::SHL_PARTS: return LowerShiftLeftParts(Op, DAG); @@ -2009,6 +2010,23 @@ LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { return FrameAddr; } +SDValue MipsTargetLowering::LowerRETURNADDR(SDValue Op, + SelectionDAG &DAG) const { + // check the depth + assert((cast(Op.getOperand(0))->getZExtValue() == 0) && + "Return address can be determined only for current frame."); + + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + EVT VT = Op.getValueType(); + unsigned RA = IsN64 ? Mips::RA_64 : Mips::RA; + MFI->setReturnAddressIsTaken(true); + + // Return RA, which contains the return address. Mark it an implicit live-in. + unsigned Reg = MF.addLiveIn(RA, getRegClassFor(VT)); + return DAG.getCopyFromReg(DAG.getEntryNode(), Op.getDebugLoc(), Reg, VT); +} + // TODO: set SType according to the desired memory barrier behavior. SDValue MipsTargetLowering::LowerMEMBARRIER(SDValue Op, SelectionDAG &DAG) const { diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index b4b1d259e8e..c8b96acc1b3 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -143,6 +143,7 @@ namespace llvm { SDValue LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFABS(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; SDValue LowerMEMBARRIER(SDValue Op, SelectionDAG& DAG) const; SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const; SDValue LowerShiftLeftParts(SDValue Op, SelectionDAG& DAG) const; diff --git a/test/CodeGen/Mips/return_address.ll b/test/CodeGen/Mips/return_address.ll new file mode 100644 index 00000000000..e1c9241984c --- /dev/null +++ b/test/CodeGen/Mips/return_address.ll @@ -0,0 +1,23 @@ +; RUN: llc -march=mipsel < %s | FileCheck %s + +define i8* @f1() nounwind { +entry: + %0 = call i8* @llvm.returnaddress(i32 0) + ret i8* %0 + +; CHECK: addu $2, $zero, $ra +} + +define i8* @f2() nounwind { +entry: + call void @g() + %0 = call i8* @llvm.returnaddress(i32 0) + ret i8* %0 + +; CHECK: addu $[[R0:[0-9]+]], $zero, $ra +; CHECK: jal +; CHECK: addu $2, $zero, $[[R0]] +} + +declare i8* @llvm.returnaddress(i32) nounwind readnone +declare void @g()