[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