Lower RETURNADDR node in Mips backend.

Patch by Sasa Stankovic.

llvm-svn: 160031
This commit is contained in:
Akira Hatanaka 2012-07-11 00:53:32 +00:00
parent 8889cf008d
commit 878ad8b28d
4 changed files with 54 additions and 5 deletions

View File

@ -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);
}

View File

@ -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<ConstantSDNode>(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 {

View File

@ -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;

View File

@ -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()