[clang] 82879c2 - [SystemZ] Support the kernel back chain.
Jonas Paulsson via cfe-commits
cfe-commits at lists.llvm.org
Sun Feb 23 13:44:23 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 cfe-commits
mailing list