[llvm] 713496d - [SystemZ/z/OS] Add XPLINK dynamic stack allocation
Kai Nacke via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 14 10:35:47 PST 2022
Author: Kai Nacke
Date: 2022-02-14T13:35:28-05:00
New Revision: 713496d9c9088387f143c521d8f981bfe2be92ad
URL: https://github.com/llvm/llvm-project/commit/713496d9c9088387f143c521d8f981bfe2be92ad
DIFF: https://github.com/llvm/llvm-project/commit/713496d9c9088387f143c521d8f981bfe2be92ad.diff
LOG: [SystemZ/z/OS] Add XPLINK dynamic stack allocation
With XPLINK, dynamic stack allocations requires calling
a runtime function, which allocates the stack memory,
moves the register save area, and returns the new
stack pointer.
Reviewed By: uweigand
Differential Revision: https://reviews.llvm.org/D119732
Added:
Modified:
llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
llvm/lib/Target/SystemZ/SystemZISelLowering.h
llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
llvm/test/CodeGen/SystemZ/zos-prologue-epilog.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index f10651d5c5d7e..0eded62347bee 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -1833,6 +1833,40 @@ SystemZTargetLowering::LowerCall(CallLoweringInfo &CLI,
return Chain;
}
+// Generate a call taking the given operands as arguments and returning a
+// result of type RetVT.
+std::pair<SDValue, SDValue> SystemZTargetLowering::makeExternalCall(
+ SDValue Chain, SelectionDAG &DAG, const char *CalleeName, EVT RetVT,
+ ArrayRef<SDValue> Ops, CallingConv::ID CallConv, bool IsSigned, SDLoc DL,
+ bool DoesNotReturn, bool IsReturnValueUsed) const {
+ TargetLowering::ArgListTy Args;
+ Args.reserve(Ops.size());
+
+ TargetLowering::ArgListEntry Entry;
+ for (SDValue Op : Ops) {
+ Entry.Node = Op;
+ Entry.Ty = Entry.Node.getValueType().getTypeForEVT(*DAG.getContext());
+ Entry.IsSExt = shouldSignExtendTypeInLibCall(Op.getValueType(), IsSigned);
+ Entry.IsZExt = !shouldSignExtendTypeInLibCall(Op.getValueType(), IsSigned);
+ Args.push_back(Entry);
+ }
+
+ SDValue Callee =
+ DAG.getExternalSymbol(CalleeName, getPointerTy(DAG.getDataLayout()));
+
+ Type *RetTy = RetVT.getTypeForEVT(*DAG.getContext());
+ TargetLowering::CallLoweringInfo CLI(DAG);
+ bool SignExtend = shouldSignExtendTypeInLibCall(RetVT, IsSigned);
+ CLI.setDebugLoc(DL)
+ .setChain(Chain)
+ .setCallee(CallConv, RetTy, Callee, std::move(Args))
+ .setNoReturn(DoesNotReturn)
+ .setDiscardResult(!IsReturnValueUsed)
+ .setSExtResult(SignExtend)
+ .setZExtResult(!SignExtend);
+ return LowerCallTo(CLI);
+}
+
bool SystemZTargetLowering::
CanLowerReturn(CallingConv::ID CallConv,
MachineFunction &MF, bool isVarArg,
@@ -3520,8 +3554,82 @@ SDValue SystemZTargetLowering::lowerVACOPY(SDValue Op,
MachinePointerInfo(SrcSV));
}
-SDValue SystemZTargetLowering::
-lowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const {
+SDValue
+SystemZTargetLowering::lowerDYNAMIC_STACKALLOC(SDValue Op,
+ SelectionDAG &DAG) const {
+ if (Subtarget.isTargetXPLINK64())
+ return lowerDYNAMIC_STACKALLOC_XPLINK(Op, DAG);
+ else
+ return lowerDYNAMIC_STACKALLOC_ELF(Op, DAG);
+}
+
+SDValue
+SystemZTargetLowering::lowerDYNAMIC_STACKALLOC_XPLINK(SDValue Op,
+ SelectionDAG &DAG) const {
+ const TargetFrameLowering *TFI = Subtarget.getFrameLowering();
+ MachineFunction &MF = DAG.getMachineFunction();
+ bool RealignOpt = !MF.getFunction().hasFnAttribute("no-realign-stack");
+ SDValue Chain = Op.getOperand(0);
+ SDValue Size = Op.getOperand(1);
+ SDValue Align = Op.getOperand(2);
+ SDLoc DL(Op);
+
+ // If user has set the no alignment function attribute, ignore
+ // alloca alignments.
+ uint64_t AlignVal =
+ (RealignOpt ? dyn_cast<ConstantSDNode>(Align)->getZExtValue() : 0);
+
+ uint64_t StackAlign = TFI->getStackAlignment();
+ uint64_t RequiredAlign = std::max(AlignVal, StackAlign);
+ uint64_t ExtraAlignSpace = RequiredAlign - StackAlign;
+
+ SDValue NeededSpace = Size;
+
+ // Add extra space for alignment if needed.
+ EVT PtrVT = getPointerTy(MF.getDataLayout());
+ if (ExtraAlignSpace)
+ NeededSpace = DAG.getNode(ISD::ADD, DL, PtrVT, NeededSpace,
+ DAG.getConstant(ExtraAlignSpace, DL, PtrVT));
+
+ bool IsSigned = false;
+ bool DoesNotReturn = false;
+ bool IsReturnValueUsed = false;
+ EVT VT = Op.getValueType();
+ SDValue AllocaCall =
+ makeExternalCall(Chain, DAG, "@@ALCAXP", VT, makeArrayRef(NeededSpace),
+ CallingConv::C, IsSigned, DL, DoesNotReturn,
+ IsReturnValueUsed)
+ .first;
+
+ // Perform a CopyFromReg from %GPR4 (stack pointer register). Chain and Glue
+ // to end of call in order to ensure it isn't broken up from the call
+ // sequence.
+ auto &Regs = Subtarget.getSpecialRegisters<SystemZXPLINK64Registers>();
+ Register SPReg = Regs.getStackPointerRegister();
+ Chain = AllocaCall.getValue(1);
+ SDValue Glue = AllocaCall.getValue(2);
+ SDValue NewSPRegNode = DAG.getCopyFromReg(Chain, DL, SPReg, PtrVT, Glue);
+ Chain = NewSPRegNode.getValue(1);
+
+ MVT PtrMVT = getPointerMemTy(MF.getDataLayout());
+ SDValue ArgAdjust = DAG.getNode(SystemZISD::ADJDYNALLOC, DL, PtrMVT);
+ SDValue Result = DAG.getNode(ISD::ADD, DL, PtrMVT, NewSPRegNode, ArgAdjust);
+
+ // Dynamically realign if needed.
+ if (ExtraAlignSpace) {
+ Result = DAG.getNode(ISD::ADD, DL, PtrVT, Result,
+ DAG.getConstant(ExtraAlignSpace, DL, PtrVT));
+ Result = DAG.getNode(ISD::AND, DL, PtrVT, Result,
+ DAG.getConstant(~(RequiredAlign - 1), DL, PtrVT));
+ }
+
+ SDValue Ops[2] = {Result, Chain};
+ return DAG.getMergeValues(Ops, DL);
+}
+
+SDValue
+SystemZTargetLowering::lowerDYNAMIC_STACKALLOC_ELF(SDValue Op,
+ SelectionDAG &DAG) const {
const TargetFrameLowering *TFI = Subtarget.getFrameLowering();
MachineFunction &MF = DAG.getMachineFunction();
bool RealignOpt = !MF.getFunction().hasFnAttribute("no-realign-stack");
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
index de446f33f5f18..448d3d048e02d 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -553,6 +553,12 @@ class SystemZTargetLowering : public TargetLowering {
SDValue LowerCall(CallLoweringInfo &CLI,
SmallVectorImpl<SDValue> &InVals) const override;
+ std::pair<SDValue, SDValue>
+ makeExternalCall(SDValue Chain, SelectionDAG &DAG, const char *CalleeName,
+ EVT RetVT, ArrayRef<SDValue> Ops, CallingConv::ID CallConv,
+ bool IsSigned, SDLoc DL, bool DoesNotReturn,
+ bool IsReturnValueUsed) const;
+
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
@@ -624,6 +630,8 @@ class SystemZTargetLowering : public TargetLowering {
SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerVACOPY(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
+ SDValue lowerDYNAMIC_STACKALLOC_ELF(SDValue Op, SelectionDAG &DAG) const;
+ SDValue lowerDYNAMIC_STACKALLOC_XPLINK(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerGET_DYNAMIC_AREA_OFFSET(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerUMUL_LOHI(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
index aca1c27f97954..3f7c27dab7203 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
@@ -119,9 +119,11 @@ void SystemZInstrInfo::splitAdjDynAlloc(MachineBasicBlock::iterator MI) const {
MachineFunction &MF = *MBB->getParent();
MachineFrameInfo &MFFrame = MF.getFrameInfo();
MachineOperand &OffsetMO = MI->getOperand(2);
+ SystemZCallingConventionRegisters *Regs = STI.getSpecialRegisters();
uint64_t Offset = (MFFrame.getMaxCallFrameSize() +
- SystemZMC::ELFCallFrameSize +
+ Regs->getCallFrameSize() +
+ Regs->getStackPointerBias() +
OffsetMO.getImm());
unsigned NewOpcode = getOpcodeForOffset(SystemZ::LA, Offset);
assert(NewOpcode && "No support for huge argument lists yet");
diff --git a/llvm/test/CodeGen/SystemZ/zos-prologue-epilog.ll b/llvm/test/CodeGen/SystemZ/zos-prologue-epilog.ll
index 5db880eb50fe4..563896fb93fbe 100644
--- a/llvm/test/CodeGen/SystemZ/zos-prologue-epilog.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-prologue-epilog.ll
@@ -280,10 +280,14 @@ define void @func3() {
}
; Requires the saving of r4 due to variable sized
-; object in stack frame. (Eg: VLA)
-; CHECK64: stmg 4, 8, 1856(4)
+; object in stack frame. (Eg: VLA) Sets up frame pointer in r8
+; CHECK64: stmg 4, 9, 1856(4)
; CHECK64: aghi 4, -192
-; CHECK64: lmg 4, 8, 2048(4)
+; CHECK64: lgr 8, 4
+; TODO Will change to basr with ADA introduction.
+; CHECK64: brasl 7, @@ALCAXP
+; CHECK64-NEXT: bcr 0, 3
+; CHECK64: lmg 4, 9, 2048(4)
define i64 @func4(i64 %n) {
%vla = alloca i64, i64 %n, align 8
%call = call i64 @fun2(i64 %n, i64* nonnull %vla, i64* nonnull %vla)
@@ -294,8 +298,12 @@ define i64 @func4(i64 %n) {
; to force use of agfi before stmg.
; CHECK64: lgr 0, 4
; CHECK64: agfi 4, -1040192
-; CHECK64: stmg 4, 8, 2048(4)
-; CHECK64: lmg 4, 8, 2048(4)
+; CHECK64: stmg 4, 9, 2048(4)
+; CHECK64: lgr 8, 4
+; TODO Will change to basr with ADA introduction.
+; CHECK64: brasl 7, @@ALCAXP
+; CHECK64-NEXT: bcr 0, 3
+;; CHECK64: lmg 4, 9, 2048(4)
define i64 @func5(i64 %n) {
%vla = alloca i64, i64 %n, align 8
%arr = alloca [130000 x i64], align 8
More information about the llvm-commits
mailing list