Index: lib/Target/AMDGPU/AMDGPUISelLowering.h =================================================================== --- lib/Target/AMDGPU/AMDGPUISelLowering.h +++ lib/Target/AMDGPU/AMDGPUISelLowering.h @@ -73,6 +73,8 @@ SDValue LowerSIGN_EXTEND_INREG(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; + protected: bool shouldCombineMemoryType(EVT VT) const; SDValue performLoadCombine(SDNode *N, DAGCombinerInfo &DCI) const; Index: lib/Target/AMDGPU/AMDGPUISelLowering.cpp =================================================================== --- lib/Target/AMDGPU/AMDGPUISelLowering.cpp +++ lib/Target/AMDGPU/AMDGPUISelLowering.cpp @@ -1156,6 +1156,7 @@ "instruction is not implemented yet!"); break; case ISD::SIGN_EXTEND_INREG: return LowerSIGN_EXTEND_INREG(Op, DAG); + case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG); case ISD::CONCAT_VECTORS: return LowerCONCAT_VECTORS(Op, DAG); case ISD::EXTRACT_SUBVECTOR: return LowerEXTRACT_SUBVECTOR(Op, DAG); case ISD::UDIVREM: return LowerUDIVREM(Op, DAG); @@ -2787,6 +2788,36 @@ return DAG.getBuildVector(VT, DL, Args); } +SDValue AMDGPUTargetLowering::LowerRETURNADDR(SDValue Op, + SelectionDAG &DAG) const { + // argument to '__builtin_return_address' must be a constant integer + if (verifyReturnAddressArgumentIsConstant(Op, DAG)) + return SDValue(); + + MachineFunction &MF = DAG.getMachineFunction(); + + // Return the frame info object for the current function. This object contains + // information about objects allocated on the stack frame of the + // current function in an abstract way. + MachineFrameInfo &MFI = MF.getFrameInfo(); + + // There is a call to @llvm.returnaddress in this function + MFI.setReturnAddressIsTaken(true); + + // This node represents llvm.returnaddress on DAG. Zero indicates the + // current function's return address + assert((cast(Op.getOperand(0))->getZExtValue() == 0) && + "Return address can be determined only for current frame."); + + MVT VT = Op.getSimpleValueType(); + // Return AMDGPU::SGPR30_SGPR31 which contains the return address; + // Mark it as an implicit live-in + unsigned Reg = MF.addLiveIn(AMDGPU::SGPR30_SGPR31, getRegClassFor(VT)); + + return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), Reg, VT); +} + + //===----------------------------------------------------------------------===// // Custom DAG optimizations //===----------------------------------------------------------------------===// Index: test/CodeGen/AMDGPU/returnaddress.ll =================================================================== --- /dev/null +++ test/CodeGen/AMDGPU/returnaddress.ll @@ -0,0 +1,13 @@ +; RUN: llc -march=amdgcn -mcpu=gfx900 -verify-machineinstrs < %s | FileCheck --check-prefix=GCN %s + +; GCN-LABEL: {{^}}func1 +; GCN: v_mov_b32_e32 v0, s30 +; GCN: v_mov_b32_e32 v1, s31 +; GCN: s_setpc_b64 s[30:31] +define i8* @func1() nounwind { +entry: + %0 = tail call i8* @llvm.returnaddress(i32 0) + ret i8* %0 +} + +declare i8* @llvm.returnaddress(i32) nounwind readnone