[llvm] 8e810dc - [SystemZ] Support builtin_{frame,return}_address() with non-zero argument (#69405)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 18 10:05:36 PDT 2023
Author: Ilya Leoshkevich
Date: 2023-10-18T19:05:31+02:00
New Revision: 8e810dc7d93bebe5e2d3980d4db084f58248b37f
URL: https://github.com/llvm/llvm-project/commit/8e810dc7d93bebe5e2d3980d4db084f58248b37f
DIFF: https://github.com/llvm/llvm-project/commit/8e810dc7d93bebe5e2d3980d4db084f58248b37f.diff
LOG: [SystemZ] Support builtin_{frame,return}_address() with non-zero argument (#69405)
When the code is built with -mbackchain, it is possible to retrieve the
caller's frame and return addresses. GCC already can do this, add this
support to Clang as well. Use RISCVTargetLowering and GCC's
s390_return_addr_rtx() as inspiration. Add tests based on what GCC is
emitting.
Added:
llvm/test/CodeGen/SystemZ/ret-addr-02.ll
Modified:
llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
llvm/test/CodeGen/SystemZ/frameaddr-01.ll
llvm/test/CodeGen/SystemZ/frameaddr-02.ll
llvm/test/CodeGen/SystemZ/ret-addr-01.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index f88bd9b45aee601..3db777f904df0ad 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -3620,9 +3620,17 @@ SDValue SystemZTargetLowering::lowerFRAMEADDR(SDValue Op,
int BackChainIdx = TFL->getOrCreateFramePointerSaveIndex(MF);
SDValue BackChain = DAG.getFrameIndex(BackChainIdx, PtrVT);
- // FIXME The frontend should detect this case.
if (Depth > 0) {
- report_fatal_error("Unsupported stack frame traversal count");
+ // FIXME The frontend should detect this case.
+ if (!MF.getFunction().hasFnAttribute("backchain"))
+ report_fatal_error("Unsupported stack frame traversal count");
+
+ SDValue Offset = DAG.getConstant(TFL->getBackchainOffset(MF), DL, PtrVT);
+ while (Depth--) {
+ BackChain = DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), BackChain,
+ MachinePointerInfo());
+ BackChain = DAG.getNode(ISD::ADD, DL, PtrVT, BackChain, Offset);
+ }
}
return BackChain;
@@ -3641,9 +3649,19 @@ SDValue SystemZTargetLowering::lowerRETURNADDR(SDValue Op,
unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
EVT PtrVT = getPointerTy(DAG.getDataLayout());
- // FIXME The frontend should detect this case.
if (Depth > 0) {
- report_fatal_error("Unsupported stack frame traversal count");
+ // FIXME The frontend should detect this case.
+ if (!MF.getFunction().hasFnAttribute("backchain"))
+ report_fatal_error("Unsupported stack frame traversal count");
+
+ SDValue FrameAddr = lowerFRAMEADDR(Op, DAG);
+ auto *TFL = Subtarget.getFrameLowering<SystemZELFFrameLowering>();
+ int Offset = (TFL->usePackedStack(MF) ? -2 : 14) *
+ getTargetMachine().getPointerSize(0);
+ SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, FrameAddr,
+ DAG.getConstant(Offset, DL, PtrVT));
+ return DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), Ptr,
+ MachinePointerInfo());
}
// Return R14D, which has the return address. Mark it an implicit live-in.
diff --git a/llvm/test/CodeGen/SystemZ/frameaddr-01.ll b/llvm/test/CodeGen/SystemZ/frameaddr-01.ll
index db3d7b33f94cae3..e8521883f08873c 100644
--- a/llvm/test/CodeGen/SystemZ/frameaddr-01.ll
+++ b/llvm/test/CodeGen/SystemZ/frameaddr-01.ll
@@ -25,4 +25,25 @@ entry:
ret ptr %1
}
+; Check the caller's frame address.
+define ptr @fpcaller() nounwind "backchain" {
+entry:
+; CHECK-LABEL: fpcaller:
+; CHECK: lg %r2, 0(%r15)
+; CHECK: br %r14
+ %0 = tail call ptr @llvm.frameaddress(i32 1)
+ ret ptr %0
+}
+
+; Check the caller's frame address.
+define ptr @fpcallercaller() nounwind "backchain" {
+entry:
+; CHECK-LABEL: fpcallercaller:
+; CHECK: lg %r1, 0(%r15)
+; CHECK: lg %r2, 0(%r1)
+; CHECK: br %r14
+ %0 = tail call ptr @llvm.frameaddress(i32 2)
+ ret ptr %0
+}
+
declare ptr @llvm.frameaddress(i32) nounwind readnone
diff --git a/llvm/test/CodeGen/SystemZ/frameaddr-02.ll b/llvm/test/CodeGen/SystemZ/frameaddr-02.ll
index a5e7e701c30e2d2..d3977928d41b87e 100644
--- a/llvm/test/CodeGen/SystemZ/frameaddr-02.ll
+++ b/llvm/test/CodeGen/SystemZ/frameaddr-02.ll
@@ -27,6 +27,29 @@ entry:
ret ptr %1
}
+; Check the caller's frame address.
+define ptr @fpcaller() #0 {
+entry:
+; CHECK-LABEL: fpcaller:
+; CHECK: lghi %r2, 152
+; CHECK: ag %r2, 152(%r15)
+; CHECK: br %r14
+ %0 = tail call ptr @llvm.frameaddress(i32 1)
+ ret ptr %0
+}
+
+; Check the caller's caller's frame address.
+define ptr @fpcallercaller() #0 {
+entry:
+; CHECK-LABEL: fpcallercaller:
+; CHECK: lg %r1, 152(%r15)
+; CHECK: lghi %r2, 152
+; CHECK: ag %r2, 152(%r1)
+; CHECK: br %r14
+ %0 = tail call ptr @llvm.frameaddress(i32 2)
+ ret ptr %0
+}
+
; Without back chain
attributes #1 = { nounwind "packed-stack" }
diff --git a/llvm/test/CodeGen/SystemZ/ret-addr-01.ll b/llvm/test/CodeGen/SystemZ/ret-addr-01.ll
index 8111d2a72456d59..e3644feb0b49b7c 100644
--- a/llvm/test/CodeGen/SystemZ/ret-addr-01.ll
+++ b/llvm/test/CodeGen/SystemZ/ret-addr-01.ll
@@ -12,4 +12,27 @@ entry:
ret ptr %0
}
+; Check the caller's return address.
+define ptr @rtcaller() nounwind "backchain" {
+entry:
+; CHECK-LABEL: rtcaller:
+; CHECK: lg %r1, 0(%r15)
+; CHECK lg %r2, 112(%r1)
+; CHECK: br %r14
+ %0 = tail call ptr @llvm.returnaddress(i32 1)
+ ret ptr %0
+}
+
+; Check the caller's caller's return address.
+define ptr @rtcallercaller() nounwind "backchain" {
+entry:
+; CHECK-LABEL: rtcallercaller:
+; CHECK: lg %r1, 0(%r15)
+; CHECK: lg %r1, 0(%r1)
+; CHECK lg %r2, 112(%r1)
+; CHECK: br %r14
+ %0 = tail call ptr @llvm.returnaddress(i32 2)
+ ret ptr %0
+}
+
declare ptr @llvm.returnaddress(i32) nounwind readnone
diff --git a/llvm/test/CodeGen/SystemZ/ret-addr-02.ll b/llvm/test/CodeGen/SystemZ/ret-addr-02.ll
new file mode 100644
index 000000000000000..5c1e56d56c0284e
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/ret-addr-02.ll
@@ -0,0 +1,39 @@
+; Test support for the llvm.returnaddress intrinsic with packed-stack.
+
+; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
+
+; The current function's return address is in the link register.
+attributes #0 = { nounwind "packed-stack" "backchain" "use-soft-float"="true" }
+define ptr @rt0() #0 {
+entry:
+; CHECK-LABEL: rt0:
+; CHECK: lgr %r2, %r14
+; CHECK: br %r14
+ %0 = tail call ptr @llvm.returnaddress(i32 0)
+ ret ptr %0
+}
+
+; Check the caller's return address.
+define ptr @rtcaller() #0 {
+entry:
+; CHECK-LABEL: rtcaller:
+; CHECK: lg %r1, 152(%r15)
+; CHECK lg %r2, 136(%r1)
+; CHECK: br %r14
+ %0 = tail call ptr @llvm.returnaddress(i32 1)
+ ret ptr %0
+}
+
+; Check the caller's caller's return address.
+define ptr @rtcallercaller() #0 {
+entry:
+; CHECK-LABEL: rtcallercaller:
+; CHECK: lg %r1, 152(%r15)
+; CHECK: lg %r1, 152(%r1)
+; CHECK lg %r2, 136(%r1)
+; CHECK: br %r14
+ %0 = tail call ptr @llvm.returnaddress(i32 2)
+ ret ptr %0
+}
+
+declare ptr @llvm.returnaddress(i32) nounwind readnone
More information about the llvm-commits
mailing list