[llvm] 82879c2 - [SystemZ] Support the kernel back chain.

Jonas Paulsson via llvm-commits llvm-commits at lists.llvm.org
Sun Feb 23 13:44:22 PST 2020


Author: Jonas Paulsson
Date: 2020-02-23T13:42:36-08:00
New Revision: 82879c2913da69ef2deadee9d075140a84eb6e8c

URL: https://github.com/llvm/llvm-project/commit/82879c2913da69ef2deadee9d075140a84eb6e8c
DIFF: https://github.com/llvm/llvm-project/commit/82879c2913da69ef2deadee9d075140a84eb6e8c.diff

LOG: [SystemZ]  Support the kernel back chain.

In order to build the Linux kernel, the back chain must be supported with
packed-stack. The back chain is then stored topmost in the register save
area.

Review: Ulrich Weigand

Differential Revision: https://reviews.llvm.org/D74506

Added: 
    llvm/test/CodeGen/SystemZ/frame-23.ll
    llvm/test/CodeGen/SystemZ/frame-24.ll
    llvm/test/CodeGen/SystemZ/frameaddr-02.ll

Modified: 
    clang/lib/Driver/ToolChains/Clang.cpp
    clang/test/Driver/mbackchain.c
    llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
    llvm/lib/Target/SystemZ/SystemZFrameLowering.h
    llvm/lib/Target/SystemZ/SystemZISelLowering.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 32b2b417162c..4bd0b5e1fb27 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -2007,21 +2007,19 @@ void Clang::AddSystemZTargetArgs(const ArgList &Args,
                                    options::OPT_mno_backchain, false);
   bool HasPackedStack = Args.hasFlag(options::OPT_mpacked_stack,
                                      options::OPT_mno_packed_stack, false);
-  if (HasBackchain && HasPackedStack) {
+  systemz::FloatABI FloatABI =
+      systemz::getSystemZFloatABI(getToolChain().getDriver(), Args);
+  bool HasSoftFloat = (FloatABI == systemz::FloatABI::Soft);
+  if (HasBackchain && HasPackedStack && !HasSoftFloat) {
     const Driver &D = getToolChain().getDriver();
     D.Diag(diag::err_drv_unsupported_opt)
-      << Args.getLastArg(options::OPT_mpacked_stack)->getAsString(Args) +
-      " " + Args.getLastArg(options::OPT_mbackchain)->getAsString(Args);
+      << "-mpacked-stack -mbackchain -mhard-float";
   }
   if (HasBackchain)
     CmdArgs.push_back("-mbackchain");
   if (HasPackedStack)
     CmdArgs.push_back("-mpacked-stack");
-
-  systemz::FloatABI FloatABI =
-      systemz::getSystemZFloatABI(getToolChain().getDriver(), Args);
-
-  if (FloatABI == systemz::FloatABI::Soft) {
+  if (HasSoftFloat) {
     // Floating point operations and argument passing are soft.
     CmdArgs.push_back("-msoft-float");
     CmdArgs.push_back("-mfloat-abi");

diff  --git a/clang/test/Driver/mbackchain.c b/clang/test/Driver/mbackchain.c
index 33076829ccd7..f0a4f86558d7 100644
--- a/clang/test/Driver/mbackchain.c
+++ b/clang/test/Driver/mbackchain.c
@@ -1,3 +1,7 @@
 // RUN: %clang -target s390x -c -### %s -mpacked-stack -mbackchain 2>&1 | FileCheck %s
+// RUN: %clang -target s390x -c -### %s -mpacked-stack -mbackchain -msoft-float \
+// RUN:   2>&1 | FileCheck %s --check-prefix=KERNEL-BUILD
+// REQUIRES: systemz-registered-target
 
-// CHECK: error: unsupported option '-mpacked-stack -mbackchain'
+// CHECK: error: unsupported option '-mpacked-stack -mbackchain -mhard-float'
+// KERNEL-BUILD-NOT: error: unsupported option

diff  --git a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
index 0d9150394d8c..5b0b56f3e488 100644
--- a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
@@ -62,18 +62,6 @@ SystemZFrameLowering::SystemZFrameLowering()
     RegSpillOffsets[SpillOffsetTable[I].Reg] = SpillOffsetTable[I].Offset;
 }
 
-static bool usePackedStack(MachineFunction &MF) {
-  bool HasPackedStackAttr = MF.getFunction().hasFnAttribute("packed-stack");
-  bool IsVarArg = MF.getFunction().isVarArg();
-  bool CallConv = MF.getFunction().getCallingConv() != CallingConv::GHC;
-  bool BackChain = MF.getFunction().hasFnAttribute("backchain");
-  bool FramAddressTaken = MF.getFrameInfo().isFrameAddressTaken();
-  if (HasPackedStackAttr && BackChain)
-    report_fatal_error("packed-stack with backchain is currently unsupported.");
-  return HasPackedStackAttr && !IsVarArg && CallConv && !BackChain &&
-         !FramAddressTaken;
-}
-
 bool SystemZFrameLowering::
 assignCalleeSavedSpillSlots(MachineFunction &MF,
                             const TargetRegisterInfo *TRI,
@@ -87,71 +75,44 @@ assignCalleeSavedSpillSlots(MachineFunction &MF,
   unsigned LowGPR = 0;
   unsigned HighGPR = SystemZ::R15D;
   int StartSPOffset = SystemZMC::CallFrameSize;
-  int CurrOffset;
-  if (!usePackedStack(MF)) {
-    for (auto &CS : CSI) {
-      unsigned Reg = CS.getReg();
-      int Offset = RegSpillOffsets[Reg];
-      if (Offset) {
-        if (SystemZ::GR64BitRegClass.contains(Reg) && StartSPOffset > Offset) {
-          LowGPR = Reg;
-          StartSPOffset = Offset;
-        }
-        Offset -= SystemZMC::CallFrameSize;
-        int FrameIdx = MFFrame.CreateFixedSpillStackObject(8, Offset);
-        CS.setFrameIdx(FrameIdx);
-      } else
-        CS.setFrameIdx(INT32_MAX);
-    }
+  for (auto &CS : CSI) {
+    unsigned Reg = CS.getReg();
+    int Offset = getRegSpillOffset(MF, Reg);
+    if (Offset) {
+      if (SystemZ::GR64BitRegClass.contains(Reg) && StartSPOffset > Offset) {
+        LowGPR = Reg;
+        StartSPOffset = Offset;
+      }
+      Offset -= SystemZMC::CallFrameSize;
+      int FrameIdx = MFFrame.CreateFixedSpillStackObject(8, Offset);
+      CS.setFrameIdx(FrameIdx);
+    } else
+      CS.setFrameIdx(INT32_MAX);
+  }
 
-    // Save the range of call-saved registers, for use by the
-    // prologue/epilogue inserters.
-    ZFI->setRestoreGPRRegs(LowGPR, HighGPR, StartSPOffset);
-    if (IsVarArg) {
-      // Also save the GPR varargs, if any.  R6D is call-saved, so would
-      // already be included, but we also need to handle the call-clobbered
-      // argument registers.
-      unsigned FirstGPR = ZFI->getVarArgsFirstGPR();
-      if (FirstGPR < SystemZ::NumArgGPRs) {
-        unsigned Reg = SystemZ::ArgGPRs[FirstGPR];
-        int Offset = RegSpillOffsets[Reg];
-        if (StartSPOffset > Offset) {
-          LowGPR = Reg; StartSPOffset = Offset;
-        }
+  // Save the range of call-saved registers, for use by the
+  // prologue/epilogue inserters.
+  ZFI->setRestoreGPRRegs(LowGPR, HighGPR, StartSPOffset);
+  if (IsVarArg) {
+    // Also save the GPR varargs, if any.  R6D is call-saved, so would
+    // already be included, but we also need to handle the call-clobbered
+    // argument registers.
+    unsigned FirstGPR = ZFI->getVarArgsFirstGPR();
+    if (FirstGPR < SystemZ::NumArgGPRs) {
+      unsigned Reg = SystemZ::ArgGPRs[FirstGPR];
+      int Offset = getRegSpillOffset(MF, Reg);
+      if (StartSPOffset > Offset) {
+        LowGPR = Reg; StartSPOffset = Offset;
       }
     }
-    ZFI->setSpillGPRRegs(LowGPR, HighGPR, StartSPOffset);
-
-    CurrOffset = -SystemZMC::CallFrameSize;
-  } else {
-    // Packed stack: put all the GPRs at the top of the Register save area.
-    uint32_t LowGR64Num = UINT32_MAX;
-    for (auto &CS : CSI) {
-      unsigned Reg = CS.getReg();
-      if (SystemZ::GR64BitRegClass.contains(Reg)) {
-        unsigned GR64Num = SystemZMC::getFirstReg(Reg);
-        int Offset = -8 * (15 - GR64Num + 1);
-        if (LowGR64Num > GR64Num) {
-          LowGR64Num = GR64Num;
-          StartSPOffset = SystemZMC::CallFrameSize + Offset;
-        }
-        int FrameIdx = MFFrame.CreateFixedSpillStackObject(8, Offset);
-        CS.setFrameIdx(FrameIdx);
-      } else
-        CS.setFrameIdx(INT32_MAX);
-    }
-    if (LowGR64Num < UINT32_MAX)
-      LowGPR = SystemZMC::GR64Regs[LowGR64Num];
-
-    // Save the range of call-saved registers, for use by the
-    // prologue/epilogue inserters.
-    ZFI->setRestoreGPRRegs(LowGPR, HighGPR, StartSPOffset);
-    ZFI->setSpillGPRRegs(LowGPR, HighGPR, StartSPOffset);
-
-    CurrOffset = LowGPR ? -(SystemZMC::CallFrameSize - StartSPOffset) : 0;
   }
+  ZFI->setSpillGPRRegs(LowGPR, HighGPR, StartSPOffset);
 
   // Create fixed stack objects for the remaining registers.
+  int CurrOffset = -SystemZMC::CallFrameSize;
+  if (usePackedStack(MF))
+    CurrOffset += StartSPOffset;
+
   for (auto &CS : CSI) {
     if (CS.getFrameIdx() != INT32_MAX)
       continue;
@@ -511,10 +472,13 @@ void SystemZFrameLowering::emitPrologue(MachineFunction &MF,
         .addCFIIndex(CFIIndex);
     SPOffsetFromCFA += Delta;
 
-    if (StoreBackchain)
+    if (StoreBackchain) {
+      // The back chain is stored topmost with packed-stack.
+      int Offset = usePackedStack(MF) ? SystemZMC::CallFrameSize - 8 : 0;
       BuildMI(MBB, MBBI, DL, ZII->get(SystemZ::STG))
-        .addReg(SystemZ::R1D, RegState::Kill).addReg(SystemZ::R15D).addImm(0)
-        .addReg(0);
+        .addReg(SystemZ::R1D, RegState::Kill).addReg(SystemZ::R15D)
+        .addImm(Offset).addReg(0);
+    }
   }
 
   if (HasFP) {
@@ -662,14 +626,43 @@ eliminateCallFramePseudoInstr(MachineFunction &MF,
   }
 }
 
+unsigned SystemZFrameLowering::getRegSpillOffset(MachineFunction &MF,
+                                                 unsigned Reg) const {
+  bool IsVarArg = MF.getFunction().isVarArg();
+  bool BackChain = MF.getFunction().hasFnAttribute("backchain");
+  bool SoftFloat = MF.getSubtarget<SystemZSubtarget>().hasSoftFloat();
+  unsigned Offset = RegSpillOffsets[Reg];
+  if (usePackedStack(MF) && !(IsVarArg && !SoftFloat)) {
+    if (SystemZ::GR64BitRegClass.contains(Reg))
+      // Put all GPRs at the top of the Register save area with packed
+      // stack. Make room for the backchain if needed.
+      Offset += BackChain ? 24 : 32;
+    else
+      Offset = 0;
+  }
+  return Offset;
+}
+
 int SystemZFrameLowering::
 getOrCreateFramePointerSaveIndex(MachineFunction &MF) const {
   SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
   int FI = ZFI->getFramePointerSaveIndex();
   if (!FI) {
     MachineFrameInfo &MFFrame = MF.getFrameInfo();
-    FI = MFFrame.CreateFixedObject(8, -SystemZMC::CallFrameSize, false);
+    // The back chain is stored topmost with packed-stack.
+    int Offset = usePackedStack(MF) ? -8 : -SystemZMC::CallFrameSize;
+    FI = MFFrame.CreateFixedObject(8, Offset, false);
     ZFI->setFramePointerSaveIndex(FI);
   }
   return FI;
 }
+
+bool SystemZFrameLowering::usePackedStack(MachineFunction &MF) const {
+  bool HasPackedStackAttr = MF.getFunction().hasFnAttribute("packed-stack");
+  bool BackChain = MF.getFunction().hasFnAttribute("backchain");
+  bool SoftFloat = MF.getSubtarget<SystemZSubtarget>().hasSoftFloat();
+  if (HasPackedStackAttr && BackChain && !SoftFloat)
+    report_fatal_error("packed-stack + backchain + hard-float is unsupported.");
+  bool CallConv = MF.getFunction().getCallingConv() != CallingConv::GHC;
+  return HasPackedStackAttr && CallConv;
+}

diff  --git a/llvm/lib/Target/SystemZ/SystemZFrameLowering.h b/llvm/lib/Target/SystemZ/SystemZFrameLowering.h
index 177dfeb138e6..5a40ade6d861 100644
--- a/llvm/lib/Target/SystemZ/SystemZFrameLowering.h
+++ b/llvm/lib/Target/SystemZ/SystemZFrameLowering.h
@@ -52,13 +52,14 @@ class SystemZFrameLowering : public TargetFrameLowering {
                                 MachineBasicBlock::iterator MI) const override;
 
   // Return the byte offset from the incoming stack pointer of Reg's
-  // ABI-defined save slot.  Return 0 if no slot is defined for Reg.
-  unsigned getRegSpillOffset(unsigned Reg) const {
-    return RegSpillOffsets[Reg];
-  }
+  // ABI-defined save slot.  Return 0 if no slot is defined for Reg.  Adjust
+  // the offset in case MF has packed-stack.
+  unsigned getRegSpillOffset(MachineFunction &MF, unsigned Reg) const;
 
   // Get or create the frame index of where the old frame pointer is stored.
   int getOrCreateFramePointerSaveIndex(MachineFunction &MF) const;
+
+  bool usePackedStack(MachineFunction &MF) const;
 };
 } // end namespace llvm
 

diff  --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 224b8dde84dd..37f0041d5440 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -1464,7 +1464,8 @@ SDValue SystemZTargetLowering::LowerFormalArguments(
 
     // ...and a similar frame index for the caller-allocated save area
     // that will be used to store the incoming registers.
-    int64_t RegSaveOffset = -SystemZMC::CallFrameSize;
+    int64_t RegSaveOffset =
+      -SystemZMC::CallFrameSize + TFL->getRegSpillOffset(MF, SystemZ::R2D) - 16;
     unsigned RegSaveIndex = MFI.CreateFixedObject(1, RegSaveOffset, true);
     FuncInfo->setRegSaveFrameIndex(RegSaveIndex);
 
@@ -1473,8 +1474,9 @@ SDValue SystemZTargetLowering::LowerFormalArguments(
     if (NumFixedFPRs < SystemZ::NumArgFPRs && !useSoftFloat()) {
       SDValue MemOps[SystemZ::NumArgFPRs];
       for (unsigned I = NumFixedFPRs; I < SystemZ::NumArgFPRs; ++I) {
-        unsigned Offset = TFL->getRegSpillOffset(SystemZ::ArgFPRs[I]);
-        int FI = MFI.CreateFixedObject(8, RegSaveOffset + Offset, true);
+        unsigned Offset = TFL->getRegSpillOffset(MF, SystemZ::ArgFPRs[I]);
+        int FI =
+          MFI.CreateFixedObject(8, -SystemZMC::CallFrameSize + Offset, true);
         SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
         unsigned VReg = MF.addLiveIn(SystemZ::ArgFPRs[I],
                                      &SystemZ::FP64BitRegClass);
@@ -3241,6 +3243,8 @@ SDValue SystemZTargetLowering::lowerConstantPool(ConstantPoolSDNode *CP,
 
 SDValue SystemZTargetLowering::lowerFRAMEADDR(SDValue Op,
                                               SelectionDAG &DAG) const {
+  auto *TFL =
+      static_cast<const SystemZFrameLowering *>(Subtarget.getFrameLowering());
   MachineFunction &MF = DAG.getMachineFunction();
   MachineFrameInfo &MFI = MF.getFrameInfo();
   MFI.setFrameAddressIsTaken(true);
@@ -3249,9 +3253,12 @@ SDValue SystemZTargetLowering::lowerFRAMEADDR(SDValue Op,
   unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
   EVT PtrVT = getPointerTy(DAG.getDataLayout());
 
+  // Return null if the back chain is not present.
+  bool HasBackChain = MF.getFunction().hasFnAttribute("backchain");
+  if (TFL->usePackedStack(MF) && !HasBackChain)
+    return DAG.getConstant(0, DL, PtrVT);
+
   // By definition, the frame address is the address of the back chain.
-  auto *TFL =
-      static_cast<const SystemZFrameLowering *>(Subtarget.getFrameLowering());
   int BackChainIdx = TFL->getOrCreateFramePointerSaveIndex(MF);
   SDValue BackChain = DAG.getFrameIndex(BackChainIdx, PtrVT);
 

diff  --git a/llvm/test/CodeGen/SystemZ/frame-23.ll b/llvm/test/CodeGen/SystemZ/frame-23.ll
new file mode 100644
index 000000000000..e1c8b2b05c94
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/frame-23.ll
@@ -0,0 +1,20 @@
+; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
+;
+; Test backchain with packed-stack, which requires soft-float.
+
+attributes #0 = { nounwind "backchain" "packed-stack" "use-soft-float"="true" }
+define i64 @fun0(i64 %a) #0 {
+; CHECK-LABEL: fun0:
+; CHECK:      stmg	%r14, %r15, 136(%r15)
+; CHECK-NEXT: lgr	%r1, %r15
+; CHECK-NEXT: aghi	%r15, -24
+; CHECK-NEXT: stg	%r1, 152(%r15)
+; CHECK-NEXT: brasl	%r14, foo at PLT
+; CHECK-NEXT: lmg	%r14, %r15, 160(%r15)
+; CHECK-NEXT: br	%r14
+entry:
+  %call = call i64 @foo(i64 %a)
+  ret i64 %call
+}
+
+declare i64 @foo(i64)

diff  --git a/llvm/test/CodeGen/SystemZ/frame-24.ll b/llvm/test/CodeGen/SystemZ/frame-24.ll
new file mode 100644
index 000000000000..37ba7eee16a1
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/frame-24.ll
@@ -0,0 +1,72 @@
+; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
+;
+; Test saving of vararg registers and backchain with packed stack.
+
+%struct.__va_list_tag = type { i64, i64, i8*, i8* }
+declare void @llvm.va_start(i8*)
+
+attributes #0 = { nounwind "packed-stack"="true" }
+define void @fun0(i64 %g0, double %d0, i64 %n, ...) #0 {
+; CHECK-LABEL: fun0:
+; CHECK:      stmg	%r4, %r15, 32(%r15)
+; CHECK-NEXT: aghi	%r15, -192
+; CHECK-NEXT: std	%f2, 328(%r15)
+; CHECK-NEXT: std	%f4, 336(%r15)
+; CHECK-NEXT: std	%f6, 344(%r15)
+; CHECK-NEXT: la	%r0, 352(%r15)
+; CHECK-NEXT: stg	%r0, 176(%r15)
+; CHECK-NEXT: la	%r0, 192(%r15)
+; CHECK-NEXT: stg	%r0, 184(%r15)
+; CHECK-NEXT: mvghi	160(%r15), 2
+; CHECK-NEXT: mvghi	168(%r15), 1
+; CHECK-NEXT: lmg	%r6, %r15, 240(%r15)
+; CHECK-NEXT: br	%r14
+entry:
+  %vl = alloca [1 x %struct.__va_list_tag], align 8
+  %0 = bitcast [1 x %struct.__va_list_tag]* %vl to i8*
+  call void @llvm.va_start(i8* nonnull %0)
+  ret void
+}
+
+attributes #1 = { nounwind "packed-stack"="true" "use-soft-float"="true" }
+define void @fun1(i64 %g0, double %d0, i64 %n, ...) #1 {
+; CHECK-LABEL: fun1:
+; CHECK:      stmg	%r5, %r15, 72(%r15)
+; CHECK-NEXT: aghi	%r15, -160
+; CHECK-NEXT: la	%r0, 192(%r15)
+; CHECK-NEXT: stg	%r0, 184(%r15)
+; CHECK-NEXT: la	%r0, 320(%r15)
+; CHECK-NEXT: stg	%r0, 176(%r15)
+; CHECK-NEXT: mvghi	168(%r15), 0
+; CHECK-NEXT: mvghi	160(%r15), 3
+; CHECK-NEXT: lmg	%r6, %r15, 240(%r15)
+; CHECK-NEXT: br	%r14
+entry:
+  %vl = alloca [1 x %struct.__va_list_tag], align 8
+  %0 = bitcast [1 x %struct.__va_list_tag]* %vl to i8*
+  call void @llvm.va_start(i8* nonnull %0)
+  ret void
+}
+
+attributes #2 = { nounwind "packed-stack"="true" "use-soft-float"="true" "backchain"}
+define void @fun2(i64 %g0, double %d0, i64 %n, ...) #2 {
+; CHECK-LABEL: fun2:
+; CHECK:      stmg	%r5, %r15, 64(%r15)
+; CHECK-NEXT: lgr	%r1, %r15
+; CHECK-NEXT: aghi	%r15, -168
+; CHECK-NEXT: stg	%r1, 152(%r15)
+; CHECK-NEXT: la	%r0, 192(%r15)
+; CHECK-NEXT: stg	%r0, 184(%r15)
+; CHECK-NEXT: la	%r0, 328(%r15)
+; CHECK-NEXT: stg	%r0, 176(%r15)
+; CHECK-NEXT: mvghi	168(%r15), 0
+; CHECK-NEXT: mvghi	160(%r15), 3
+; CHECK-NEXT: lmg	%r6, %r15, 240(%r15)
+; CHECK-NEXT: br	%r14
+entry:
+  %vl = alloca [1 x %struct.__va_list_tag], align 8
+  %0 = bitcast [1 x %struct.__va_list_tag]* %vl to i8*
+  call void @llvm.va_start(i8* nonnull %0)
+  ret void
+}
+

diff  --git a/llvm/test/CodeGen/SystemZ/frameaddr-02.ll b/llvm/test/CodeGen/SystemZ/frameaddr-02.ll
new file mode 100644
index 000000000000..f1b62f6928a8
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/frameaddr-02.ll
@@ -0,0 +1,54 @@
+; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
+
+; Test lowering of @llvm.frameaddress with packed-stack.
+
+; With back chain
+attributes #0 = { nounwind "packed-stack" "backchain" "use-soft-float"="true" }
+define i8* @fp0() #0 {
+entry:
+; CHECK-LABEL: fp0:
+; CHECK:      la   %r2, 152(%r15)
+; CHECK-NEXT: br   %r14
+  %0 = tail call i8* @llvm.frameaddress(i32 0)
+  ret i8* %0
+}
+
+define i8* @fp0f() #0 {
+entry:
+; CHECK-LABEL: fp0f:
+; CHECK:      lgr	%r1, %r15
+; CHECK-NEXT: aghi	%r15, -16
+; CHECK-NEXT: stg	%r1, 152(%r15)
+; CHECK-NEXT: la	%r2, 168(%r15)
+; CHECK-NEXT: aghi	%r15, 16
+; CHECK-NEXT: br	%r14
+  %0 = alloca i64, align 8
+  %1 = tail call i8* @llvm.frameaddress(i32 0)
+  ret i8* %1
+}
+
+; Without back chain
+
+attributes #1 = { nounwind "packed-stack" }
+define i8* @fp1() #1 {
+entry:
+; CHECK-LABEL: fp1:
+; CHECK:      lghi %r2, 0
+; CHECK-NEXT: br   %r14
+  %0 = tail call i8* @llvm.frameaddress(i32 0)
+  ret i8* %0
+}
+
+define i8* @fp1f() #1 {
+entry:
+; CHECK-LABEL: fp1f:
+; CHECK:      aghi	%r15, -8
+; CHECK-NEXT: lghi	%r2, 0
+; CHECK-NEXT: aghi	%r15, 8
+; CHECK-NEXT: br	%r14
+  %0 = alloca i64, align 8
+  %1 = tail call i8* @llvm.frameaddress(i32 0)
+  ret i8* %1
+}
+
+declare i8* @llvm.frameaddress(i32) nounwind readnone


        


More information about the llvm-commits mailing list