diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -245,8 +245,32 @@ // Always allocate at least one byte. Size = std::max(Size, 1u); + const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering(); + const Align StackAlign = TFI->getStackAlign(); + Align FIAlignment = AI.getAlign(); + // The following code mimics the alignment optimizations done in + // FunctionLoweringInfo for SelectionDAG. + Type *Ty = AI.getAllocatedType(); + Align TyPrefAlign = MF->getDataLayout().getPrefTypeAlign(Ty); + // The "specified" alignment is the alignment written on the alloca, + // or the preferred alignment of the type if none is specified. + Align SpecifiedAlign = AI.getAlign(); + + // If the preferred alignment of the type is higher than the specified + // alignment of the alloca, promote the alignment, as long as it doesn't + // require realigning the stack. + // + // FIXME: Do we really want to second-guess the IR in isel? + Align Alignment = std::max(std::min(TyPrefAlign, StackAlign), SpecifiedAlign); + + // 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 (TFI->isStackRealignable() || (Alignment <= StackAlign)) + FIAlignment = Alignment; + int &FI = FrameIndices[&AI]; - FI = MF->getFrameInfo().CreateStackObject(Size, AI.getAlign(), false, &AI); + FI = MF->getFrameInfo().CreateStackObject(Size, FIAlignment, false, &AI); return FI; } diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll --- a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll @@ -35,7 +35,7 @@ ; CHECK-NEXT: - { id: 0, name: ptr1, type: default, offset: 0, size: 8, alignment: 8, ; CHECK-NEXT: stack-id: default, callee-saved-register: '', callee-saved-restored: true, ; CHECK-NEXT: debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } -; CHECK-NEXT: - { id: 1, name: ptr2, type: default, offset: 0, size: 8, alignment: 1, +; CHECK-NEXT: - { id: 1, name: ptr2, type: default, offset: 0, size: 8, alignment: 8, ; CHECK-NEXT: stack-id: default, callee-saved-register: '', callee-saved-restored: true, ; CHECK-NEXT: debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } ; CHECK-NEXT: - { id: 2, name: ptr3, type: default, offset: 0, size: 128, alignment: 8, @@ -54,6 +54,17 @@ ret void } +define void @alloca_increase_alignment() { +; The alignment of the frame index should be 8 here since it's the preferred alignment. +; CHECK: stack: +; CHECK: - { id: 0, name: ai, type: default, offset: 0, size: 8, alignment: 8, +; CHECK: stack-id: default, callee-saved-register: '', callee-saved-restored: true, +; CHECK: debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + %ai = alloca i8*, align 4 + ret void +} + + ; Tests for br. ; CHECK-LABEL: name: uncondbr ; CHECK: body: