diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -530,6 +530,12 @@ return false; } + /// \returns true if GlobalISel should over-align allocas to the preferred + /// alignment. + virtual bool shouldGISelOverAlignAllocas() const { + return false; + } + /// Return true if the following transform is beneficial: /// fold (conv (load x)) -> (load (conv*)x) /// On architectures that don't natively support some vector loads 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,36 @@ // Always allocate at least one byte. Size = std::max(Size, 1u); + auto &ST = MF->getSubtarget(); + const TargetFrameLowering *TFI = ST.getFrameLowering(); + const Align StackAlign = TFI->getStackAlign(); + Align FIAlignment = AI.getAlign(); + if (ST.getTargetLowering()->shouldGISelOverAlignAllocas()) { + // 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/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h @@ -825,6 +825,10 @@ bool isAllActivePredicate(SDValue N) const; + bool shouldGISelOverAlignAllocas() const override { + return true; + } + private: /// Keep a pointer to the AArch64Subtarget around so that we can /// make the right decision when generating code for different targets. 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: