return DAG.getMergeValues(Ops, DL);
}
+static SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG,
+ const VETargetLowering &TLI,
+ const VESubtarget *Subtarget) {
+ SDLoc DL(Op);
+ MachineFunction &MF = DAG.getMachineFunction();
+ EVT PtrVT = TLI.getPointerTy(MF.getDataLayout());
+
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+ MFI.setFrameAddressIsTaken(true);
+
+ unsigned Depth = Op.getConstantOperandVal(0);
+ const VERegisterInfo *RegInfo = Subtarget->getRegisterInfo();
+ unsigned FrameReg = RegInfo->getFrameRegister(MF);
+ SDValue FrameAddr =
+ DAG.getCopyFromReg(DAG.getEntryNode(), DL, FrameReg, PtrVT);
+ while (Depth--)
+ FrameAddr = DAG.getLoad(Op.getValueType(), DL, DAG.getEntryNode(),
+ FrameAddr, MachinePointerInfo());
+ return FrameAddr;
+}
+
static SDValue getSplatValue(SDNode *N) {
if (auto *BuildVec = dyn_cast<BuildVectorSDNode>(N)) {
return BuildVec->getSplatValue();
return lowerConstantPool(Op, DAG);
case ISD::DYNAMIC_STACKALLOC:
return lowerDYNAMIC_STACKALLOC(Op, DAG);
+ case ISD::FRAMEADDR:
+ return lowerFRAMEADDR(Op, DAG, *this, Subtarget);
case ISD::GlobalAddress:
return lowerGlobalAddress(Op, DAG);
case ISD::GlobalTLSAddress:
--- /dev/null
+; RUN: llc < %s -mtriple=ve | FileCheck %s
+
+define i8* @test1() nounwind {
+; CHECK-LABEL: test1:
+; CHECK: .LBB{{[0-9]+}}_2:
+; CHECK-NEXT: or %s0, 0, %s9
+; CHECK-NEXT: or %s11, 0, %s9
+entry:
+ %ret = tail call i8* @llvm.frameaddress(i32 0)
+ ret i8* %ret
+}
+
+define i8* @test2() nounwind {
+; CHECK-LABEL: test2:
+; CHECK: .LBB{{[0-9]+}}_2:
+; CHECK-NEXT: ld %s0, (, %s9)
+; CHECK-NEXT: ld %s0, (, %s0)
+; CHECK-NEXT: or %s11, 0, %s9
+entry:
+ %ret = tail call i8* @llvm.frameaddress(i32 2)
+ ret i8* %ret
+}
+
+declare i8* @llvm.frameaddress(i32) nounwind readnone