summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlya Leoshkevich <iii@linux.ibm.com>2023-11-08 15:05:47 +0100
committerGitHub <noreply@github.com>2023-11-08 15:05:47 +0100
commitd79fff0abb5a8ae6f49f5e3fd4f31d65717c7a37 (patch)
tree6db183091d0bb4f20ae1a53ee8fbdd069bf39c66
parent0d48a4645d9a3e9f188a0c9503df3f82ca5759e3 (diff)
[SystemZ] Add backchain target-feature (#71668)
GCC supports building individual functions with backchain using the __attribute__((target("backchain"))) syntax, and Clang should too. Clang translates this into the "target-features"="+backchain" attribute, and the -mbackchain command-line option into the "backchain" attribute. The backend currently checks only the latter; furthermore, the backchain target feature is not defined. Handle backchain like soft-float. Define a target feature, convert function attribute into it in getSubtargetImpl(), and check for target feature instead of function attribute everywhere. Add an end-to-end test to the Clang testsuite.
-rw-r--r--clang/test/CodeGen/SystemZ/mbackchain-4.c11
-rw-r--r--llvm/lib/Target/SystemZ/SystemZFeatures.td5
-rw-r--r--llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp20
-rw-r--r--llvm/lib/Target/SystemZ/SystemZISelLowering.cpp8
-rw-r--r--llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp8
5 files changed, 36 insertions, 16 deletions
diff --git a/clang/test/CodeGen/SystemZ/mbackchain-4.c b/clang/test/CodeGen/SystemZ/mbackchain-4.c
new file mode 100644
index 000000000000..6e5f4fc5da40
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/mbackchain-4.c
@@ -0,0 +1,11 @@
+// RUN: %clang --target=s390x-linux -O1 -S -o - %s | FileCheck %s
+
+__attribute__((target("backchain")))
+void *foo(void) {
+ return __builtin_return_address(1);
+}
+
+// CHECK-LABEL: foo:
+// CHECK: lg %r1, 0(%r15)
+// CHECK: lg %r2, 112(%r1)
+// CHECK: br %r14
diff --git a/llvm/lib/Target/SystemZ/SystemZFeatures.td b/llvm/lib/Target/SystemZ/SystemZFeatures.td
index 78b8394d6486..fdd94206421a 100644
--- a/llvm/lib/Target/SystemZ/SystemZFeatures.td
+++ b/llvm/lib/Target/SystemZ/SystemZFeatures.td
@@ -32,6 +32,11 @@ def FeatureSoftFloat : SystemZFeature<
"Use software emulation for floating point"
>;
+def FeatureBackChain : SystemZFeature<
+ "backchain", "BackChain", (all_of FeatureBackChain),
+ "Store the address of the caller's frame into the callee's stack frame"
+>;
+
//===----------------------------------------------------------------------===//
//
// New features added in the Ninth Edition of the z/Architecture
diff --git a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
index bfd31709eb3e..7522998fd06d 100644
--- a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
@@ -443,7 +443,7 @@ void SystemZELFFrameLowering::processFunctionBeforeFrameFinalized(
MachineFrameInfo &MFFrame = MF.getFrameInfo();
SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>();
MachineRegisterInfo *MRI = &MF.getRegInfo();
- bool BackChain = MF.getFunction().hasFnAttribute("backchain");
+ bool BackChain = MF.getSubtarget<SystemZSubtarget>().hasBackChain();
if (!usePackedStack(MF) || BackChain)
// Create the incoming register save area.
@@ -628,7 +628,7 @@ void SystemZELFFrameLowering::emitPrologue(MachineFunction &MF,
.addImm(StackSize);
}
else {
- bool StoreBackchain = MF.getFunction().hasFnAttribute("backchain");
+ bool StoreBackchain = MF.getSubtarget<SystemZSubtarget>().hasBackChain();
// If we need backchain, save current stack pointer. R1 is free at
// this point.
if (StoreBackchain)
@@ -786,7 +786,7 @@ void SystemZELFFrameLowering::inlineStackProbe(
.addMemOperand(MMO);
};
- bool StoreBackchain = MF.getFunction().hasFnAttribute("backchain");
+ bool StoreBackchain = MF.getSubtarget<SystemZSubtarget>().hasBackChain();
if (StoreBackchain)
BuildMI(*MBB, MBBI, DL, ZII->get(SystemZ::LGR))
.addReg(SystemZ::R1D, RegState::Define).addReg(SystemZ::R15D);
@@ -861,8 +861,9 @@ StackOffset SystemZELFFrameLowering::getFrameIndexReference(
unsigned SystemZELFFrameLowering::getRegSpillOffset(MachineFunction &MF,
Register Reg) const {
bool IsVarArg = MF.getFunction().isVarArg();
- bool BackChain = MF.getFunction().hasFnAttribute("backchain");
- bool SoftFloat = MF.getSubtarget<SystemZSubtarget>().hasSoftFloat();
+ const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
+ bool BackChain = Subtarget.hasBackChain();
+ bool SoftFloat = Subtarget.hasSoftFloat();
unsigned Offset = RegSpillOffsets[Reg];
if (usePackedStack(MF) && !(IsVarArg && !SoftFloat)) {
if (SystemZ::GR64BitRegClass.contains(Reg))
@@ -890,8 +891,9 @@ int SystemZELFFrameLowering::getOrCreateFramePointerSaveIndex(
bool SystemZELFFrameLowering::usePackedStack(MachineFunction &MF) const {
bool HasPackedStackAttr = MF.getFunction().hasFnAttribute("packed-stack");
- bool BackChain = MF.getFunction().hasFnAttribute("backchain");
- bool SoftFloat = MF.getSubtarget<SystemZSubtarget>().hasSoftFloat();
+ const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();
+ bool BackChain = Subtarget.hasBackChain();
+ bool SoftFloat = Subtarget.hasSoftFloat();
if (HasPackedStackAttr && BackChain && !SoftFloat)
report_fatal_error("packed-stack + backchain + hard-float is unsupported.");
bool CallConv = MF.getFunction().getCallingConv() != CallingConv::GHC;
@@ -946,7 +948,7 @@ static bool isXPLeafCandidate(const MachineFunction &MF) {
return false;
// If the backchain pointer should be stored, then it is not a XPLeaf routine.
- if (MF.getFunction().hasFnAttribute("backchain"))
+ if (MF.getSubtarget<SystemZSubtarget>().hasBackChain())
return false;
// If function acquires its own stack frame, then it is not a XPLeaf routine.
@@ -989,7 +991,7 @@ bool SystemZXPLINKFrameLowering::assignCalleeSavedSpillSlots(
// If the function needs a frame pointer, or if the backchain pointer should
// be stored, then save the stack pointer register R4.
- if (hasFP(MF) || MF.getFunction().hasFnAttribute("backchain"))
+ if (hasFP(MF) || Subtarget.hasBackChain())
CSI.push_back(CalleeSavedInfo(Regs.getStackPointerRegister()));
// Scan the call-saved GPRs and find the bounds of the register spill area.
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index e6ea4205623d..4e57986206dc 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -3631,7 +3631,7 @@ SDValue SystemZTargetLowering::lowerFRAMEADDR(SDValue Op,
if (Depth > 0) {
// FIXME The frontend should detect this case.
- if (!MF.getFunction().hasFnAttribute("backchain"))
+ if (!MF.getSubtarget<SystemZSubtarget>().hasBackChain())
report_fatal_error("Unsupported stack frame traversal count");
SDValue Offset = DAG.getConstant(TFL->getBackchainOffset(MF), DL, PtrVT);
@@ -3660,7 +3660,7 @@ SDValue SystemZTargetLowering::lowerRETURNADDR(SDValue Op,
if (Depth > 0) {
// FIXME The frontend should detect this case.
- if (!MF.getFunction().hasFnAttribute("backchain"))
+ if (!MF.getSubtarget<SystemZSubtarget>().hasBackChain())
report_fatal_error("Unsupported stack frame traversal count");
SDValue FrameAddr = lowerFRAMEADDR(Op, DAG);
@@ -3886,7 +3886,7 @@ SystemZTargetLowering::lowerDYNAMIC_STACKALLOC_ELF(SDValue Op,
const TargetFrameLowering *TFI = Subtarget.getFrameLowering();
MachineFunction &MF = DAG.getMachineFunction();
bool RealignOpt = !MF.getFunction().hasFnAttribute("no-realign-stack");
- bool StoreBackchain = MF.getFunction().hasFnAttribute("backchain");
+ bool StoreBackchain = MF.getSubtarget<SystemZSubtarget>().hasBackChain();
SDValue Chain = Op.getOperand(0);
SDValue Size = Op.getOperand(1);
@@ -4563,7 +4563,7 @@ SDValue SystemZTargetLowering::lowerSTACKRESTORE(SDValue Op,
SelectionDAG &DAG) const {
MachineFunction &MF = DAG.getMachineFunction();
auto *Regs = Subtarget.getSpecialRegisters();
- bool StoreBackchain = MF.getFunction().hasFnAttribute("backchain");
+ bool StoreBackchain = MF.getSubtarget<SystemZSubtarget>().hasBackChain();
if (MF.getFunction().getCallingConv() == CallingConv::GHC)
report_fatal_error("Variable-sized stack allocations are not supported "
diff --git a/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp b/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp
index 186494ad2ac6..73e01e3ec184 100644
--- a/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp
@@ -169,12 +169,14 @@ SystemZTargetMachine::getSubtargetImpl(const Function &F) const {
FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
// FIXME: This is related to the code below to reset the target options,
- // we need to know whether or not the soft float flag is set on the
- // function, so we can enable it as a subtarget feature.
+ // we need to know whether the soft float and backchain flags are set on the
+ // function, so we can enable them as subtarget features.
bool SoftFloat = F.getFnAttribute("use-soft-float").getValueAsBool();
-
if (SoftFloat)
FS += FS.empty() ? "+soft-float" : ",+soft-float";
+ bool BackChain = F.hasFnAttribute("backchain");
+ if (BackChain)
+ FS += FS.empty() ? "+backchain" : ",+backchain";
auto &I = SubtargetMap[CPU + TuneCPU + FS];
if (!I) {