Index: include/llvm/CodeGen/MachineFrameInfo.h =================================================================== --- include/llvm/CodeGen/MachineFrameInfo.h +++ include/llvm/CodeGen/MachineFrameInfo.h @@ -125,6 +125,9 @@ unsigned StackAlignment; /// Can the stack be realigned. + /// Targets that set this to false have to handle alignment of all + /// allocas themselves, i.e. while lowering DYNAMIC_STACKALLOC + /// nodes. bool StackRealignable; /// The list of stack objects allocated. Index: lib/CodeGen/MachineFunction.cpp =================================================================== --- lib/CodeGen/MachineFunction.cpp +++ lib/CodeGen/MachineFunction.cpp @@ -511,12 +511,16 @@ /// Clamp the alignment if requested and emit a warning. static inline unsigned clampStackAlignment(bool ShouldClamp, unsigned Align, - unsigned StackAlign) { + unsigned StackAlign, + bool ShouldWarn) { if (!ShouldClamp || Align <= StackAlign) return Align; - DEBUG(dbgs() << "Warning: requested alignment " << Align - << " exceeds the stack alignment " << StackAlign - << " when stack realignment is off" << '\n'); + + DEBUG(if (ShouldWarn) + dbgs() << "Warning: requested alignment " << Align + << " exceeds the stack alignment " << StackAlign + << " when stack realignment is off" << '\n'); + return StackAlign; } @@ -526,7 +530,8 @@ bool isSS, const AllocaInst *Alloca) { assert(Size != 0 && "Cannot allocate zero size stack objects!"); Alignment = clampStackAlignment(!StackRealignable || !RealignOption, - Alignment, StackAlignment); + Alignment, StackAlignment, + StackRealignable || !RealignOption); Objects.push_back(StackObject(Size, Alignment, 0, false, isSS, Alloca, !isSS)); int Index = (int)Objects.size() - NumFixedObjects - 1; @@ -540,7 +545,8 @@ int MachineFrameInfo::CreateSpillStackObject(uint64_t Size, unsigned Alignment) { Alignment = clampStackAlignment(!StackRealignable || !RealignOption, - Alignment, StackAlignment); + Alignment, StackAlignment, + StackRealignable || !RealignOption); CreateStackObject(Size, Alignment, true); int Index = (int)Objects.size() - NumFixedObjects - 1; ensureMaxAlignment(Alignment); @@ -554,7 +560,8 @@ const AllocaInst *Alloca) { HasVarSizedObjects = true; Alignment = clampStackAlignment(!StackRealignable || !RealignOption, - Alignment, StackAlignment); + Alignment, StackAlignment, + StackRealignable || !RealignOption); Objects.push_back(StackObject(0, Alignment, 0, false, false, Alloca, true)); ensureMaxAlignment(Alignment); return (int)Objects.size()-NumFixedObjects-1; @@ -573,7 +580,8 @@ // object is 16-byte aligned. unsigned Align = MinAlign(SPOffset, StackAlignment); Align = clampStackAlignment(!StackRealignable || !RealignOption, Align, - StackAlignment); + StackAlignment, + StackRealignable || !RealignOption); Objects.insert(Objects.begin(), StackObject(Size, Align, SPOffset, Immutable, /*isSS*/ false, /*Alloca*/ nullptr, isAliased)); @@ -586,7 +594,8 @@ int64_t SPOffset) { unsigned Align = MinAlign(SPOffset, StackAlignment); Align = clampStackAlignment(!StackRealignable || !RealignOption, Align, - StackAlignment); + StackAlignment, + StackRealignable || !RealignOption); Objects.insert(Objects.begin(), StackObject(Size, Align, SPOffset, /*Immutable*/ true, /*isSS*/ true, Index: lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp =================================================================== --- lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -87,6 +87,7 @@ 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 Outs; @@ -103,14 +104,19 @@ for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I) { if (const AllocaInst *AI = dyn_cast(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(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. @@ -119,12 +125,6 @@ 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(); if (Align <= StackAlign) Align = 0; // Inform the Frame Information that we have variable-sized objects. Index: lib/Target/SystemZ/SystemZFrameLowering.cpp =================================================================== --- lib/Target/SystemZ/SystemZFrameLowering.cpp +++ lib/Target/SystemZ/SystemZFrameLowering.cpp @@ -48,7 +48,8 @@ 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) Index: lib/Target/SystemZ/SystemZISelLowering.cpp =================================================================== --- lib/Target/SystemZ/SystemZISelLowering.cpp +++ lib/Target/SystemZ/SystemZISelLowering.cpp @@ -2743,17 +2743,37 @@ 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(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); @@ -2764,6 +2784,16 @@ 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); } Index: test/CodeGen/SystemZ/alloca-03.ll =================================================================== --- /dev/null +++ test/CodeGen/SystemZ/alloca-03.ll @@ -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 +} + Index: test/CodeGen/SystemZ/alloca-04.ll =================================================================== --- /dev/null +++ test/CodeGen/SystemZ/alloca-04.ll @@ -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