[llvm] r254227 - [Stack realignment] Handling of aligned allocas.
Jonas Paulsson via llvm-commits
llvm-commits at lists.llvm.org
Sat Nov 28 03:02:33 PST 2015
Author: jonpa
Date: Sat Nov 28 05:02:32 2015
New Revision: 254227
URL: http://llvm.org/viewvc/llvm-project?rev=254227&view=rev
Log:
[Stack realignment] Handling of aligned allocas.
This patch implements dynamic realignment of stack objects for targets
with a non-realigned stack pointer. Behaviour in FunctionLoweringInfo
is changed so that for a target that has StackRealignable set to
false, over-aligned static allocas are considered to be variable-sized
objects and are handled with DYNAMIC_STACKALLOC nodes.
It would be good to group aligned allocas into a single big alloca as
an optimization, but this is yet todo.
SystemZ benefits from this, due to its stack frame layout.
New tests SystemZ/alloca-03.ll for aligned allocas, and
SystemZ/alloca-04.ll for "no-realign-stack" attribute on functions.
Review and help from Ulrich Weigand and Hal Finkel.
Added:
llvm/trunk/test/CodeGen/SystemZ/alloca-03.ll
llvm/trunk/test/CodeGen/SystemZ/alloca-04.ll
Modified:
llvm/trunk/include/llvm/CodeGen/MachineFrameInfo.h
llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
llvm/trunk/lib/Target/SystemZ/SystemZFrameLowering.cpp
llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp
Modified: llvm/trunk/include/llvm/CodeGen/MachineFrameInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineFrameInfo.h?rev=254227&r1=254226&r2=254227&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/MachineFrameInfo.h (original)
+++ llvm/trunk/include/llvm/CodeGen/MachineFrameInfo.h Sat Nov 28 05:02:32 2015
@@ -125,6 +125,16 @@ class MachineFrameInfo {
unsigned StackAlignment;
/// Can the stack be realigned.
+ /// Targets that set this to false don't have the ability to overalign
+ /// their stack frame, and thus, overaligned allocas are all treated
+ /// as dynamic allocations and the target must handle them as part
+ /// of DYNAMIC_STACKALLOC lowering.
+ /// FIXME: There is room for improvement in this case, in terms of
+ /// grouping overaligned allocas into a "secondary stack frame" and
+ /// then only use a single alloca to allocate this frame and only a
+ /// single virtual register to access it. Currently, without such an
+ /// optimization, each such alloca gets it's own dynamic
+ /// realignment.
bool StackRealignable;
/// The list of stack objects allocated.
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp?rev=254227&r1=254226&r2=254227&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp Sat Nov 28 05:02:32 2015
@@ -87,6 +87,7 @@ void FunctionLoweringInfo::set(const Fun
TLI = MF->getSubtarget().getTargetLowering();
RegInfo = &MF->getRegInfo();
MachineModuleInfo &MMI = MF->getMMI();
+ const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering();
// Check whether the function can return without sret-demotion.
SmallVector<ISD::OutputArg, 4> Outs;
@@ -103,28 +104,29 @@ void FunctionLoweringInfo::set(const Fun
for (BasicBlock::const_iterator I = BB->begin(), E = BB->end();
I != E; ++I) {
if (const AllocaInst *AI = dyn_cast<AllocaInst>(I)) {
- // Static allocas can be folded into the initial stack frame adjustment.
- if (AI->isStaticAlloca()) {
+ Type *Ty = AI->getAllocatedType();
+ unsigned Align =
+ std::max((unsigned)MF->getDataLayout().getPrefTypeAlignment(Ty),
+ AI->getAlignment());
+ unsigned StackAlign = TFI->getStackAlignment();
+
+ // Static allocas can be folded into the initial stack frame
+ // adjustment. For targets that don't realign the stack, don't
+ // do this if there is an extra alignment requirement.
+ if (AI->isStaticAlloca() &&
+ (TFI->isStackRealignable() || (Align <= StackAlign))) {
const ConstantInt *CUI = cast<ConstantInt>(AI->getArraySize());
- Type *Ty = AI->getAllocatedType();
uint64_t TySize = MF->getDataLayout().getTypeAllocSize(Ty);
- unsigned Align =
- std::max((unsigned)MF->getDataLayout().getPrefTypeAlignment(Ty),
- AI->getAlignment());
TySize *= CUI->getZExtValue(); // Get total allocated size.
if (TySize == 0) TySize = 1; // Don't create zero-sized stack objects.
StaticAllocaMap[AI] =
MF->getFrameInfo()->CreateStackObject(TySize, Align, false, AI);
-
} else {
- unsigned Align =
- std::max((unsigned)MF->getDataLayout().getPrefTypeAlignment(
- AI->getAllocatedType()),
- AI->getAlignment());
- unsigned StackAlign =
- MF->getSubtarget().getFrameLowering()->getStackAlignment();
+ // FIXME: Overaligned static allocas should be grouped into
+ // a single dynamic allocation instead of using a separate
+ // stack allocation for each one.
if (Align <= StackAlign)
Align = 0;
// Inform the Frame Information that we have variable-sized objects.
Modified: llvm/trunk/lib/Target/SystemZ/SystemZFrameLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZFrameLowering.cpp?rev=254227&r1=254226&r2=254227&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZFrameLowering.cpp (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZFrameLowering.cpp Sat Nov 28 05:02:32 2015
@@ -48,7 +48,8 @@ static const TargetFrameLowering::SpillS
SystemZFrameLowering::SystemZFrameLowering()
: TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 8,
- -SystemZMC::CallFrameSize, 8) {
+ -SystemZMC::CallFrameSize, 8,
+ false /* StackRealignable */) {
// Create a mapping from register number to save slot offset.
RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS);
for (unsigned I = 0, E = array_lengthof(SpillOffsetTable); I != E; ++I)
Modified: llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp?rev=254227&r1=254226&r2=254227&view=diff
==============================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp Sat Nov 28 05:02:32 2015
@@ -2739,17 +2739,37 @@ SDValue SystemZTargetLowering::lowerVACO
SDValue SystemZTargetLowering::
lowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const {
+ const TargetFrameLowering *TFI = Subtarget.getFrameLowering();
+ bool RealignOpt = !DAG.getMachineFunction().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;
+
unsigned SPReg = getStackPointerRegisterToSaveRestore();
+ SDValue NeededSpace = Size;
// Get a reference to the stack pointer.
SDValue OldSP = DAG.getCopyFromReg(Chain, DL, SPReg, MVT::i64);
+ // Add extra space for alignment if needed.
+ if (ExtraAlignSpace)
+ NeededSpace = DAG.getNode(ISD::ADD, DL, MVT::i64, NeededSpace,
+ DAG.getConstant(ExtraAlignSpace, DL, MVT::i64));
+
// Get the new stack pointer value.
- SDValue NewSP = DAG.getNode(ISD::SUB, DL, MVT::i64, OldSP, Size);
+ SDValue NewSP = DAG.getNode(ISD::SUB, DL, MVT::i64, OldSP, NeededSpace);
// Copy the new stack pointer back.
Chain = DAG.getCopyToReg(Chain, DL, SPReg, NewSP);
@@ -2760,6 +2780,16 @@ lowerDYNAMIC_STACKALLOC(SDValue Op, Sele
SDValue ArgAdjust = DAG.getNode(SystemZISD::ADJDYNALLOC, DL, MVT::i64);
SDValue Result = DAG.getNode(ISD::ADD, DL, MVT::i64, NewSP, ArgAdjust);
+ // Dynamically realign if needed.
+ if (RequiredAlign > StackAlign) {
+ Result =
+ DAG.getNode(ISD::ADD, DL, MVT::i64, Result,
+ DAG.getConstant(ExtraAlignSpace, DL, MVT::i64));
+ Result =
+ DAG.getNode(ISD::AND, DL, MVT::i64, Result,
+ DAG.getConstant(~(RequiredAlign - 1), DL, MVT::i64));
+ }
+
SDValue Ops[2] = { Result, Chain };
return DAG.getMergeValues(Ops, DL);
}
Added: llvm/trunk/test/CodeGen/SystemZ/alloca-03.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/alloca-03.ll?rev=254227&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/alloca-03.ll (added)
+++ llvm/trunk/test/CodeGen/SystemZ/alloca-03.ll Sat Nov 28 05:02:32 2015
@@ -0,0 +1,84 @@
+; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
+
+; Allocate 8 bytes, no need to align stack.
+define void @f0() {
+; CHECK-LABEL: f0:
+; CHECK: aghi %r15, -168
+; CHECK-NOT: nil
+; CHECK: mvghi 160(%r15), 10
+; CHECK: aghi %r15, 168
+ %x = alloca i64
+ store volatile i64 10, i64* %x
+ ret void
+}
+
+; Allocate %len * 8, no need to align stack.
+define void @f1(i64 %len) {
+; CHECK-LABEL: f1:
+; CHECK: sllg %r0, %r2, 3
+; CHECK: lgr %r1, %r15
+; CHECK: sgr %r1, %r0
+; CHECK-NOT: ngr
+; CHECK: lgr %r15, %r1
+; CHECK: la %r1, 160(%r1)
+; CHECK: mvghi 0(%r1), 10
+ %x = alloca i64, i64 %len
+ store volatile i64 10, i64* %x
+ ret void
+}
+
+; Static alloca, align 128.
+define void @f2() {
+; CHECK-LABEL: f2:
+; CHECK: aghi %r1, -128
+; CHECK: lgr %r15, %r1
+; CHECK: la %r1, 280(%r1)
+; CHECK: nill %r1, 65408
+; CHECK: mvghi 0(%r1), 10
+ %x = alloca i64, i64 1, align 128
+ store volatile i64 10, i64* %x, align 128
+ ret void
+}
+
+; Dynamic alloca, align 128.
+define void @f3(i64 %len) {
+; CHECK-LABEL: f3:
+; CHECK: sllg %r1, %r2, 3
+; CHECK: la %r0, 120(%r1)
+; CHECK: lgr %r1, %r15
+; CHECK: sgr %r1, %r0
+; CHECK: lgr %r15, %r1
+; CHECK: la %r1, 280(%r1)
+; CHECK: nill %r1, 65408
+; CHECK: mvghi 0(%r1), 10
+ %x = alloca i64, i64 %len, align 128
+ store volatile i64 10, i64* %x, align 128
+ ret void
+}
+
+; Static alloca w/out alignment - part of frame.
+define void @f4() {
+; CHECK-LABEL: f4:
+; CHECK: aghi %r15, -168
+; CHECK: mvhi 164(%r15), 10
+; CHECK: aghi %r15, 168
+ %x = alloca i32
+ store volatile i32 10, i32* %x
+ ret void
+}
+
+; Static alloca of one i32, aligned by 128.
+define void @f5() {
+; CHECK-LABEL: f5:
+
+; CHECK: lgr %r1, %r15
+; CHECK: aghi %r1, -128
+; CHECK: lgr %r15, %r1
+; CHECK: la %r1, 280(%r1)
+; CHECK: nill %r1, 65408
+; CHECK: mvhi 0(%r1), 10
+ %x = alloca i32, i64 1, align 128
+ store volatile i32 10, i32* %x
+ ret void
+}
+
Added: llvm/trunk/test/CodeGen/SystemZ/alloca-04.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/alloca-04.ll?rev=254227&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/alloca-04.ll (added)
+++ llvm/trunk/test/CodeGen/SystemZ/alloca-04.ll Sat Nov 28 05:02:32 2015
@@ -0,0 +1,14 @@
+; Check the "no-realign-stack" function attribute. We should get a warning.
+
+; RUN: llc < %s -mtriple=s390x-linux-gnu -debug-only=codegen 2>&1 | \
+; RUN: FileCheck %s
+
+
+define void @f6() "no-realign-stack" {
+ %x = alloca i64, i64 1, align 128
+ store volatile i64 10, i64* %x, align 128
+ ret void
+}
+
+; CHECK: Warning: requested alignment 128 exceeds the stack alignment 8
+; CHECK-NOT: nill
More information about the llvm-commits
mailing list