[llvm] [SystemZ] Support builtin_{frame,return}_address() with non-zero argument (PR #69405)

Ilya Leoshkevich via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 18 08:06:29 PDT 2023


https://github.com/iii-i updated https://github.com/llvm/llvm-project/pull/69405

>From b088e20475b51c8f86f482f632c13d1ce9964a2a Mon Sep 17 00:00:00 2001
From: Ilya Leoshkevich <iii at linux.ibm.com>
Date: Tue, 17 Oct 2023 01:55:22 +0200
Subject: [PATCH] [SystemZ] Support builtin_{frame,return}_address() with
 non-zero argument

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.
---
 .../Target/SystemZ/SystemZISelLowering.cpp    | 26 +++++++++++--
 llvm/test/CodeGen/SystemZ/frameaddr-01.ll     | 21 ++++++++++
 llvm/test/CodeGen/SystemZ/frameaddr-02.ll     | 23 +++++++++++
 llvm/test/CodeGen/SystemZ/ret-addr-01.ll      | 23 +++++++++++
 llvm/test/CodeGen/SystemZ/ret-addr-02.ll      | 39 +++++++++++++++++++
 5 files changed, 128 insertions(+), 4 deletions(-)
 create mode 100644 llvm/test/CodeGen/SystemZ/ret-addr-02.ll

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