return FrameAddr;
}
+static SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG,
+ const VETargetLowering &TLI,
+ const VESubtarget *Subtarget) {
+ MachineFunction &MF = DAG.getMachineFunction();
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+ MFI.setReturnAddressIsTaken(true);
+
+ if (TLI.verifyReturnAddressArgumentIsConstant(Op, DAG))
+ return SDValue();
+
+ SDValue FrameAddr = lowerFRAMEADDR(Op, DAG, TLI, Subtarget);
+
+ SDLoc DL(Op);
+ EVT VT = Op.getValueType();
+ SDValue Offset = DAG.getConstant(8, DL, VT);
+ return DAG.getLoad(VT, DL, DAG.getEntryNode(),
+ DAG.getNode(ISD::ADD, DL, VT, FrameAddr, Offset),
+ MachinePointerInfo());
+}
+
static SDValue getSplatValue(SDNode *N) {
if (auto *BuildVec = dyn_cast<BuildVectorSDNode>(N)) {
return BuildVec->getSplatValue();
return lowerJumpTable(Op, DAG);
case ISD::LOAD:
return lowerLOAD(Op, DAG);
+ case ISD::RETURNADDR:
+ return lowerRETURNADDR(Op, DAG, *this, Subtarget);
case ISD::BUILD_VECTOR:
return lowerBUILD_VECTOR(Op, DAG);
case ISD::STORE:
--- /dev/null
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=ve-- | FileCheck %s
+
+define i8* @h() nounwind readnone optsize {
+; CHECK-LABEL: h:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: st %s9, (, %s11)
+; CHECK-NEXT: st %s10, 8(, %s11)
+; CHECK-NEXT: or %s9, 0, %s11
+; CHECK-NEXT: lea %s11, -176(, %s11)
+; CHECK-NEXT: brge.l.t %s11, %s8, .LBB0_2
+; CHECK-NEXT: # %bb.1: # %entry
+; CHECK-NEXT: ld %s61, 24(, %s14)
+; CHECK-NEXT: or %s62, 0, %s0
+; CHECK-NEXT: lea %s63, 315
+; CHECK-NEXT: shm.l %s63, (%s61)
+; CHECK-NEXT: shm.l %s8, 8(%s61)
+; CHECK-NEXT: shm.l %s11, 16(%s61)
+; CHECK-NEXT: monc
+; CHECK-NEXT: or %s0, 0, %s62
+; CHECK-NEXT: .LBB0_2: # %entry
+; CHECK-NEXT: ld %s0, (, %s9)
+; CHECK-NEXT: ld %s0, (, %s0)
+; CHECK-NEXT: ld %s0, 8(, %s0)
+; CHECK-NEXT: or %s11, 0, %s9
+; CHECK-NEXT: ld %s10, 8(, %s11)
+; CHECK-NEXT: ld %s9, (, %s11)
+; CHECK-NEXT: b.l.t (, %s10)
+entry:
+ %ret = tail call i8* @llvm.returnaddress(i32 2)
+ ret i8* %ret
+}
+
+declare i8* @llvm.returnaddress(i32) nounwind readnone
+
+define i8* @g() nounwind readnone optsize {
+; CHECK-LABEL: g:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: st %s9, (, %s11)
+; CHECK-NEXT: st %s10, 8(, %s11)
+; CHECK-NEXT: or %s9, 0, %s11
+; CHECK-NEXT: lea %s11, -176(, %s11)
+; CHECK-NEXT: brge.l.t %s11, %s8, .LBB1_2
+; CHECK-NEXT: # %bb.1: # %entry
+; CHECK-NEXT: ld %s61, 24(, %s14)
+; CHECK-NEXT: or %s62, 0, %s0
+; CHECK-NEXT: lea %s63, 315
+; CHECK-NEXT: shm.l %s63, (%s61)
+; CHECK-NEXT: shm.l %s8, 8(%s61)
+; CHECK-NEXT: shm.l %s11, 16(%s61)
+; CHECK-NEXT: monc
+; CHECK-NEXT: or %s0, 0, %s62
+; CHECK-NEXT: .LBB1_2: # %entry
+; CHECK-NEXT: ld %s0, (, %s9)
+; CHECK-NEXT: ld %s0, 8(, %s0)
+; CHECK-NEXT: or %s11, 0, %s9
+; CHECK-NEXT: ld %s10, 8(, %s11)
+; CHECK-NEXT: ld %s9, (, %s11)
+; CHECK-NEXT: b.l.t (, %s10)
+entry:
+ %ret = tail call i8* @llvm.returnaddress(i32 1)
+ ret i8* %ret
+}
+
+define i8* @f() nounwind readnone optsize {
+; CHECK-LABEL: f:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: st %s9, (, %s11)
+; CHECK-NEXT: st %s10, 8(, %s11)
+; CHECK-NEXT: or %s9, 0, %s11
+; CHECK-NEXT: lea %s11, -176(, %s11)
+; CHECK-NEXT: brge.l.t %s11, %s8, .LBB2_2
+; CHECK-NEXT: # %bb.1: # %entry
+; CHECK-NEXT: ld %s61, 24(, %s14)
+; CHECK-NEXT: or %s62, 0, %s0
+; CHECK-NEXT: lea %s63, 315
+; CHECK-NEXT: shm.l %s63, (%s61)
+; CHECK-NEXT: shm.l %s8, 8(%s61)
+; CHECK-NEXT: shm.l %s11, 16(%s61)
+; CHECK-NEXT: monc
+; CHECK-NEXT: or %s0, 0, %s62
+; CHECK-NEXT: .LBB2_2: # %entry
+; CHECK-NEXT: ld %s0, 8(, %s9)
+; CHECK-NEXT: or %s11, 0, %s9
+; CHECK-NEXT: ld %s10, 8(, %s11)
+; CHECK-NEXT: ld %s9, (, %s11)
+; CHECK-NEXT: b.l.t (, %s10)
+entry:
+ %ret = tail call i8* @llvm.returnaddress(i32 0)
+ ret i8* %ret
+}