diff options
-rw-r--r-- | include/llvm/Target/TargetFrameInfo.h | 21 | ||||
-rw-r--r-- | lib/CodeGen/PrologEpilogInserter.cpp | 34 | ||||
-rw-r--r-- | lib/Target/ARM/ARMFrameInfo.h | 2 | ||||
-rw-r--r-- | test/CodeGen/ARM/2009-09-24-spill-align.ll | 17 |
4 files changed, 54 insertions, 20 deletions
diff --git a/include/llvm/Target/TargetFrameInfo.h b/include/llvm/Target/TargetFrameInfo.h index 3e26b9d..afc3fb1 100644 --- a/include/llvm/Target/TargetFrameInfo.h +++ b/include/llvm/Target/TargetFrameInfo.h @@ -34,10 +34,13 @@ public: private: StackDirection StackDir; unsigned StackAlignment; + unsigned TransientStackAlignment; int LocalAreaOffset; public: - TargetFrameInfo(StackDirection D, unsigned StackAl, int LAO) - : StackDir(D), StackAlignment(StackAl), LocalAreaOffset(LAO) {} + TargetFrameInfo(StackDirection D, unsigned StackAl, int LAO, + unsigned TransAl = 1) + : StackDir(D), StackAlignment(StackAl), TransientStackAlignment(TransAl), + LocalAreaOffset(LAO) {} virtual ~TargetFrameInfo(); @@ -48,12 +51,20 @@ public: /// StackDirection getStackGrowthDirection() const { return StackDir; } - /// getStackAlignment - This method returns the number of bytes that the stack - /// pointer must be aligned to. Typically, this is the largest alignment for - /// any data object in the target. + /// getStackAlignment - This method returns the number of bytes to which the + /// stack pointer must be aligned on entry to a function. Typically, this + /// is the largest alignment for any data object in the target. /// unsigned getStackAlignment() const { return StackAlignment; } + /// getTransientStackAlignment - This method returns the number of bytes to + /// which the stack pointer must be aligned at all times, even between + /// calls. + /// + unsigned getTransientStackAlignment() const { + return TransientStackAlignment; + } + /// getOffsetOfLocalArea - This method returns the offset of the local area /// from the stack pointer on entrance to a function. /// diff --git a/lib/CodeGen/PrologEpilogInserter.cpp b/lib/CodeGen/PrologEpilogInserter.cpp index dd39853..2f18319 100644 --- a/lib/CodeGen/PrologEpilogInserter.cpp +++ b/lib/CodeGen/PrologEpilogInserter.cpp @@ -484,7 +484,7 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { // Loop over all of the stack objects, assigning sequential addresses... MachineFrameInfo *FFI = Fn.getFrameInfo(); - unsigned MaxAlign = FFI->getMaxAlignment(); + unsigned MaxAlign = 1; // Start at the beginning of the local area. // The Offset is the distance from the stack top in the direction @@ -586,23 +586,28 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { AdjustStackOffset(FFI, SFI, StackGrowsDown, Offset, MaxAlign); } - // Round up the size to a multiple of the alignment, but only if there are - // calls or alloca's in the function. This ensures that any calls to - // subroutines have their stack frames suitably aligned. - // Also do this if we need runtime alignment of the stack. In this case - // offsets will be relative to SP not FP; round up the stack size so this - // works. - if (!RegInfo->targetHandlesStackFrameRounding() && - (FFI->hasCalls() || FFI->hasVarSizedObjects() || - (RegInfo->needsStackRealignment(Fn) && - FFI->getObjectIndexEnd() != 0))) { + if (!RegInfo->targetHandlesStackFrameRounding()) { // If we have reserved argument space for call sites in the function // immediately on entry to the current function, count it as part of the // overall stack size. - if (RegInfo->hasReservedCallFrame(Fn)) + if (FFI->hasCalls() && RegInfo->hasReservedCallFrame(Fn)) Offset += FFI->getMaxCallFrameSize(); - unsigned AlignMask = std::max(TFI.getStackAlignment(), MaxAlign) - 1; + // Round up the size to a multiple of the alignment. If the function has + // any calls or alloca's, align to the target's StackAlignment value to + // ensure that the callee's frame or the alloca data is suitably aligned; + // otherwise, for leaf functions, align to the TransientStackAlignment + // value. + unsigned StackAlign; + if (FFI->hasCalls() || FFI->hasVarSizedObjects() || + (RegInfo->needsStackRealignment(Fn) && FFI->getObjectIndexEnd() != 0)) + StackAlign = TFI.getStackAlignment(); + else + StackAlign = TFI.getTransientStackAlignment(); + // If the frame pointer is eliminated, all frame offsets will be relative + // to SP not FP; align to MaxAlign so this works. + StackAlign = std::max(StackAlign, MaxAlign); + unsigned AlignMask = StackAlign - 1; Offset = (Offset + AlignMask) & ~uint64_t(AlignMask); } @@ -611,7 +616,8 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { // Remember the required stack alignment in case targets need it to perform // dynamic stack alignment. - FFI->setMaxAlignment(MaxAlign); + if (MaxAlign > FFI->getMaxAlignment()) + FFI->setMaxAlignment(MaxAlign); } diff --git a/lib/Target/ARM/ARMFrameInfo.h b/lib/Target/ARM/ARMFrameInfo.h index d304bc8..d5dae24 100644 --- a/lib/Target/ARM/ARMFrameInfo.h +++ b/lib/Target/ARM/ARMFrameInfo.h @@ -23,7 +23,7 @@ namespace llvm { class ARMFrameInfo : public TargetFrameInfo { public: explicit ARMFrameInfo(const ARMSubtarget &ST) - : TargetFrameInfo(StackGrowsDown, ST.getStackAlignment(), 0) { + : TargetFrameInfo(StackGrowsDown, ST.getStackAlignment(), 0, 4) { } }; diff --git a/test/CodeGen/ARM/2009-09-24-spill-align.ll b/test/CodeGen/ARM/2009-09-24-spill-align.ll new file mode 100644 index 0000000..6281775 --- /dev/null +++ b/test/CodeGen/ARM/2009-09-24-spill-align.ll @@ -0,0 +1,17 @@ +; RUN: llc < %s -march=arm -mattr=+neon | FileCheck %s +; pr4926 + +define arm_apcscc void @test_vget_lanep16() nounwind { +entry: + %arg0_poly16x4_t = alloca <4 x i16> ; <<4 x i16>*> [#uses=1] + %out_poly16_t = alloca i16 ; <i16*> [#uses=1] + %"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0] +; CHECK: fldd + %0 = load <4 x i16>* %arg0_poly16x4_t, align 8 ; <<4 x i16>> [#uses=1] + %1 = extractelement <4 x i16> %0, i32 1 ; <i16> [#uses=1] + store i16 %1, i16* %out_poly16_t, align 2 + br label %return + +return: ; preds = %entry + ret void +} |