aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Target/TargetFrameInfo.h21
-rw-r--r--lib/CodeGen/PrologEpilogInserter.cpp34
-rw-r--r--lib/Target/ARM/ARMFrameInfo.h2
-rw-r--r--test/CodeGen/ARM/2009-09-24-spill-align.ll17
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
+}