Pull in r198480 from upstream llvm trunk (by Venkatraman Govindaraju): [SparcV9]: Implement RETURNADDR and FRAMEADDR lowering in SPARC64. Introduced here: http://svnweb.freebsd.org/changeset/base/262261 Index: lib/Target/Sparc/SparcISelLowering.cpp =================================================================== --- lib/Target/Sparc/SparcISelLowering.cpp +++ lib/Target/Sparc/SparcISelLowering.cpp @@ -2415,7 +2415,8 @@ static SDValue getFLUSHW(SDValue Op, SelectionDAG return Chain; } -static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) { +static SDValue getFRAMEADDR(uint64_t depth, SDValue Op, SelectionDAG &DAG, + const SparcSubtarget *Subtarget) { MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); MFI->setFrameAddressIsTaken(true); @@ -2422,32 +2423,49 @@ static SDValue getFLUSHW(SDValue Op, SelectionDAG EVT VT = Op.getValueType(); SDLoc dl(Op); unsigned FrameReg = SP::I6; + unsigned stackBias = Subtarget->getStackPointerBias(); - uint64_t depth = Op.getConstantOperandVal(0); + SDValue FrameAddr; - SDValue FrameAddr; - if (depth == 0) + if (depth == 0) { FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT); - else { - // flush first to make sure the windowed registers' values are in stack - SDValue Chain = getFLUSHW(Op, DAG); - FrameAddr = DAG.getCopyFromReg(Chain, dl, FrameReg, VT); + if (Subtarget->is64Bit()) + FrameAddr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr, + DAG.getIntPtrConstant(stackBias)); + return FrameAddr; + } - for (uint64_t i = 0; i != depth; ++i) { - SDValue Ptr = DAG.getNode(ISD::ADD, - dl, MVT::i32, - FrameAddr, DAG.getIntPtrConstant(56)); - FrameAddr = DAG.getLoad(MVT::i32, dl, - Chain, - Ptr, - MachinePointerInfo(), false, false, false, 0); - } + // flush first to make sure the windowed registers' values are in stack + SDValue Chain = getFLUSHW(Op, DAG); + FrameAddr = DAG.getCopyFromReg(Chain, dl, FrameReg, VT); + + unsigned Offset = (Subtarget->is64Bit()) ? (stackBias + 112) : 56; + + while (depth--) { + SDValue Ptr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr, + DAG.getIntPtrConstant(Offset)); + FrameAddr = DAG.getLoad(VT, dl, Chain, Ptr, MachinePointerInfo(), + false, false, false, 0); } + if (Subtarget->is64Bit()) + FrameAddr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr, + DAG.getIntPtrConstant(stackBias)); return FrameAddr; } + +static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG, + const SparcSubtarget *Subtarget) { + + uint64_t depth = Op.getConstantOperandVal(0); + + return getFRAMEADDR(depth, Op, DAG, Subtarget); + +} + static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG, - const SparcTargetLowering &TLI) { + const SparcTargetLowering &TLI, + const SparcSubtarget *Subtarget) { MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); MFI->setReturnAddressIsTaken(true); @@ -2461,25 +2479,20 @@ static SDValue LowerRETURNADDR(SDValue Op, Selecti unsigned RetReg = MF.addLiveIn(SP::I7, TLI.getRegClassFor(TLI.getPointerTy())); RetAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, RetReg, VT); - } else { - // Need frame address to find return address of the caller. - MFI->setFrameAddressIsTaken(true); + return RetAddr; + } - // flush first to make sure the windowed registers' values are in stack - SDValue Chain = getFLUSHW(Op, DAG); - RetAddr = DAG.getCopyFromReg(Chain, dl, SP::I6, VT); + // Need frame address to find return address of the caller. + SDValue FrameAddr = getFRAMEADDR(depth - 1, Op, DAG, Subtarget); - for (uint64_t i = 0; i != depth; ++i) { - SDValue Ptr = DAG.getNode(ISD::ADD, - dl, MVT::i32, - RetAddr, - DAG.getIntPtrConstant((i == depth-1)?60:56)); - RetAddr = DAG.getLoad(MVT::i32, dl, - Chain, - Ptr, - MachinePointerInfo(), false, false, false, 0); - } - } + unsigned Offset = (Subtarget->is64Bit()) ? 120 : 60; + SDValue Ptr = DAG.getNode(ISD::ADD, + dl, VT, + FrameAddr, + DAG.getIntPtrConstant(Offset)); + RetAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), Ptr, + MachinePointerInfo(), false, false, false, 0); + return RetAddr; } @@ -2763,8 +2776,10 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) cons switch (Op.getOpcode()) { default: llvm_unreachable("Should not custom lower this!"); - case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG, *this); - case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); + case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG, *this, + Subtarget); + case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG, + Subtarget); case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); Index: test/CodeGen/SPARC/2011-01-11-FrameAddr.ll =================================================================== --- test/CodeGen/SPARC/2011-01-11-FrameAddr.ll +++ test/CodeGen/SPARC/2011-01-11-FrameAddr.ll @@ -2,6 +2,7 @@ ;RUN: llc -march=sparc -mattr=v9 < %s | FileCheck %s -check-prefix=V9 ;RUN: llc -march=sparc -regalloc=basic < %s | FileCheck %s -check-prefix=V8 ;RUN: llc -march=sparc -regalloc=basic -mattr=v9 < %s | FileCheck %s -check-prefix=V9 +;RUN: llc -march=sparcv9 < %s | FileCheck %s -check-prefix=SPARC64 define i8* @frameaddr() nounwind readnone { @@ -15,6 +16,13 @@ entry: ;V9: save %sp, -96, %sp ;V9: jmp %i7+8 ;V9: restore %g0, %fp, %o0 + +;SPARC64-LABEL: frameaddr +;SPARC64: save %sp, -128, %sp +;SPARC64: add %fp, 2047, %i0 +;SPARC64: jmp %i7+8 +;SPARC64: restore %g0, %g0, %g0 + %0 = tail call i8* @llvm.frameaddress(i32 0) ret i8* %0 } @@ -32,6 +40,14 @@ entry: ;V9: ld [%fp+56], {{.+}} ;V9: ld [{{.+}}+56], {{.+}} ;V9: ld [{{.+}}+56], {{.+}} + +;SPARC64-LABEL: frameaddr2 +;SPARC64: flushw +;SPARC64: ldx [%fp+2159], %[[R0:[goli][0-7]]] +;SPARC64: ldx [%[[R0]]+2159], %[[R1:[goli][0-7]]] +;SPARC64: ldx [%[[R1]]+2159], %[[R2:[goli][0-7]]] +;SPARC64: add %[[R2]], 2047, {{.+}} + %0 = tail call i8* @llvm.frameaddress(i32 3) ret i8* %0 } @@ -48,6 +64,9 @@ entry: ;V9-LABEL: retaddr: ;V9: or %g0, %o7, {{.+}} +;SPARC64-LABEL: retaddr +;SPARC64: or %g0, %o7, {{.+}} + %0 = tail call i8* @llvm.returnaddress(i32 0) ret i8* %0 } @@ -66,18 +85,12 @@ entry: ;V9: ld [{{.+}}+56], {{.+}} ;V9: ld [{{.+}}+60], {{.+}} -;V8LEAF-LABEL: retaddr2: -;V8LEAF: ta 3 -;V8LEAF: ld [%fp+56], %[[R:[goli][0-7]]] -;V8LEAF: ld [%[[R]]+56], %[[R1:[goli][0-7]]] -;V8LEAF: ld [%[[R1]]+60], {{.+}} +;SPARC64-LABEL: retaddr2 +;SPARC64: flushw +;SPARC64: ldx [%fp+2159], %[[R0:[goli][0-7]]] +;SPARC64: ldx [%[[R0]]+2159], %[[R1:[goli][0-7]]] +;SPARC64: ldx [%[[R1]]+2167], {{.+}} -;V9LEAF-LABEL: retaddr2: -;V9LEAF: flushw -;V9LEAF: ld [%fp+56], %[[R:[goli][0-7]]] -;V9LEAF: ld [%[[R]]+56], %[[R1:[goli][0-7]]] -;V9LEAF: ld [%[[R1]]+60], {{.+}} - %0 = tail call i8* @llvm.returnaddress(i32 3) ret i8* %0 }