Stack Alignment: throw error if we can't satisfy the minimal alignment
authorManman Ren <mren@apple.com>
Thu, 10 Jan 2013 01:10:10 +0000 (01:10 +0000)
committerManman Ren <mren@apple.com>
Thu, 10 Jan 2013 01:10:10 +0000 (01:10 +0000)
requirement when creating stack objects in MachineFrameInfo.

Add CreateStackObjectWithMinAlign to throw error when the minimal alignment
can't be achieved and to clamp the alignment when the preferred alignment
can't be achieved. Same is true for CreateVariableSizedObject.
Will not emit error in CreateSpillStackObject or CreateStackObject.

As long as callers of CreateStackObject do not assume the object will be
aligned at the requested alignment, we should not have miscompile since
later optimizations which look at the object's alignment will have the correct
information.

rdar://12713765

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172027 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/MachineFrameInfo.h
lib/CodeGen/MachineFunction.cpp
lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
test/CodeGen/ARM/alloc-no-stack-realign-error.ll [new file with mode: 0644]
test/CodeGen/ARM/alloc-no-stack-realign.ll

index 93d77287d7ca621beab9832d44775c59a6cedc22..0748b9ab24a2810abfef5383fa06e5c94bb31e88 100644 (file)
@@ -493,11 +493,23 @@ public:
     return Objects[ObjectIdx+NumFixedObjects].Size == ~0ULL;
   }
 
+  /// CreateStackObjectWithMinAlign - Create a new statically sized stack
+  /// object, returning a nonnegative identifier to represent it. This function
+  /// takes a preferred alignment and a minimal alignment.
+  ///
+  int CreateStackObjectWithMinAlign(uint64_t Size, unsigned PrefAlignment,
+                        unsigned MinAlignment, bool isSS,
+                        bool MayNeedSP = false, const AllocaInst *Alloca = 0);
+
   /// CreateStackObject - Create a new statically sized stack object, returning
-  /// a nonnegative identifier to represent it.
+  /// a nonnegative identifier to represent it. Will not emit an error when
+  /// Alignment can't be satisfied.
   ///
   int CreateStackObject(uint64_t Size, unsigned Alignment, bool isSS,
-                        bool MayNeedSP = false, const AllocaInst *Alloca = 0);
+                        bool MayNeedSP = false, const AllocaInst *Alloca = 0) {
+    return CreateStackObjectWithMinAlign(Size, Alignment, 0, isSS,
+                                         MayNeedSP, Alloca);
+  }
 
   /// CreateSpillStackObject - Create a new statically sized stack object that
   /// represents a spill slot, returning a nonnegative identifier to represent
@@ -517,7 +529,8 @@ public:
   /// variable sized object is created, whether or not the index returned is
   /// actually used.
   ///
-  int CreateVariableSizedObject(unsigned Alignment);
+  int CreateVariableSizedObject(unsigned PrefAlignment, unsigned MinAlignment,
+                                const AllocaInst *Alloca = 0);
 
   /// getCalleeSavedInfo - Returns a reference to call saved info vector for the
   /// current function.
index 9647e83e24c0366a38612b0e293b6fd7c33326e9..3d7d20d41601f18bf3aad740bcdc3888f0aa3dbd 100644 (file)
@@ -473,24 +473,32 @@ void MachineFrameInfo::ensureMaxAlignment(unsigned Align) {
 }
 
 /// clampStackAlignment - Clamp the alignment if requested and emit a warning.
-static inline unsigned clampStackAlignment(bool ShouldClamp, unsigned Align,
-                                           unsigned StackAlign) {
-  if (!ShouldClamp || Align <= StackAlign)
-    return Align;
-  DEBUG(dbgs() << "Warning: requested alignment " << Align
-               << " exceeds the stack alignment " << StackAlign
-               << " when stack realignment is off" << '\n');
+static inline unsigned clampStackAlignment(bool ShouldClamp, unsigned PrefAlign,
+                         unsigned MinAlign, unsigned StackAlign,
+                         const AllocaInst *Alloca = 0) {
+  if (!ShouldClamp || PrefAlign <= StackAlign)
+    return PrefAlign;
+  if (Alloca && MinAlign > StackAlign)
+    Alloca->getParent()->getContext().emitError(Alloca,
+        "Requested Minimal Alignment exceeds the Stack Alignment!");
+  else
+    assert(MinAlign <= StackAlign &&
+           "Requested Minimal Alignment exceeds the Stack Alignment!");
   return StackAlign;
 }
 
-/// CreateStackObject - Create a new statically sized stack object, returning
-/// a nonnegative identifier to represent it.
+/// CreateStackObjectWithMinAlign - Create a new statically sized stack
+/// object, returning a nonnegative identifier to represent it. This function
+/// takes a preferred alignment and a minimal alignment.
 ///
-int MachineFrameInfo::CreateStackObject(uint64_t Size, unsigned Alignment,
-                      bool isSS, bool MayNeedSP, const AllocaInst *Alloca) {
+int MachineFrameInfo::CreateStackObjectWithMinAlign(uint64_t Size,
+                          unsigned PrefAlignment, unsigned MinAlignment,
+                          bool isSS, bool MayNeedSP, const AllocaInst *Alloca) {
   assert(Size != 0 && "Cannot allocate zero size stack objects!");
-  Alignment = clampStackAlignment(!TFI.isStackRealignable() || !RealignOption,
-                                  Alignment, TFI.getStackAlignment());
+  unsigned Alignment = clampStackAlignment(
+                           !TFI.isStackRealignable() || !RealignOption,
+                           PrefAlignment, MinAlignment,
+                           TFI.getStackAlignment(), Alloca);
   Objects.push_back(StackObject(Size, Alignment, 0, false, isSS, MayNeedSP,
                                 Alloca));
   int Index = (int)Objects.size() - NumFixedObjects - 1;
@@ -506,7 +514,8 @@ int MachineFrameInfo::CreateStackObject(uint64_t Size, unsigned Alignment,
 int MachineFrameInfo::CreateSpillStackObject(uint64_t Size,
                                              unsigned Alignment) {
   Alignment = clampStackAlignment(!TFI.isStackRealignable() || !RealignOption,
-                                  Alignment, TFI.getStackAlignment()); 
+                                  Alignment, 0,
+                                  TFI.getStackAlignment()); 
   CreateStackObject(Size, Alignment, true, false);
   int Index = (int)Objects.size() - NumFixedObjects - 1;
   ensureMaxAlignment(Alignment);
@@ -518,10 +527,13 @@ int MachineFrameInfo::CreateSpillStackObject(uint64_t Size,
 /// variable sized object is created, whether or not the index returned is
 /// actually used.
 ///
-int MachineFrameInfo::CreateVariableSizedObject(unsigned Alignment) {
+int MachineFrameInfo::CreateVariableSizedObject(unsigned PrefAlignment,
+                        unsigned MinAlignment, const AllocaInst *Alloca) {
   HasVarSizedObjects = true;
-  Alignment = clampStackAlignment(!TFI.isStackRealignable() || !RealignOption,
-                                  Alignment, TFI.getStackAlignment()); 
+  unsigned Alignment = clampStackAlignment(
+                           !TFI.isStackRealignable() || !RealignOption,
+                           PrefAlignment, MinAlignment,
+                           TFI.getStackAlignment(), Alloca); 
   Objects.push_back(StackObject(0, Alignment, 0, false, false, true, 0));
   ensureMaxAlignment(Alignment);
   return (int)Objects.size()-NumFixedObjects-1;
@@ -542,7 +554,7 @@ int MachineFrameInfo::CreateFixedObject(uint64_t Size, int64_t SPOffset,
   unsigned StackAlign = TFI.getStackAlignment();
   unsigned Align = MinAlign(SPOffset, StackAlign);
   Align = clampStackAlignment(!TFI.isStackRealignable() || !RealignOption,
-                              Align, TFI.getStackAlignment()); 
+                              Align, 0, TFI.getStackAlignment()); 
   Objects.insert(Objects.begin(), StackObject(Size, Align, SPOffset, Immutable,
                                               /*isSS*/   false,
                                               /*NeedSP*/ false,
index b46edad7a3d4d1df4557669d8e3dbb8655aba7db..229c50be9a1b66590e037fd5027b28ccf9531a04 100644 (file)
@@ -95,7 +95,8 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf) {
            (TySize >= 8 && isa<ArrayType>(Ty) &&
             cast<ArrayType>(Ty)->getElementType()->isIntegerTy(8)));
         StaticAllocaMap[AI] =
-          MF->getFrameInfo()->CreateStackObject(TySize, Align, false,
+          MF->getFrameInfo()->CreateStackObjectWithMinAlign(TySize, Align,
+                                                AI->getAlignment(), false,
                                                 MayNeedSP, AI);
       }
 
index 8c22db35cb1c490e91b5699ab74523fe77561cd3..ee98b00e2b5ff9f86b9171c13abf3e9badfc910b 100644 (file)
@@ -3259,7 +3259,8 @@ void SelectionDAGBuilder::visitAlloca(const AllocaInst &I) {
 
   // Inform the Frame Information that we have just allocated a variable-sized
   // object.
-  FuncInfo.MF->getFrameInfo()->CreateVariableSizedObject(Align ? Align : 1);
+  FuncInfo.MF->getFrameInfo()->CreateVariableSizedObject(Align ? Align : 1,
+                                 I.getAlignment(), &I);
 }
 
 void SelectionDAGBuilder::visitLoad(const LoadInst &I) {
diff --git a/test/CodeGen/ARM/alloc-no-stack-realign-error.ll b/test/CodeGen/ARM/alloc-no-stack-realign-error.ll
new file mode 100644 (file)
index 0000000..96c0017
--- /dev/null
@@ -0,0 +1,19 @@
+; RUN: llc < %s -mtriple=armv7-apple-ios -O0 -realign-stack=0 2>&1 | FileCheck %s
+
+; rdar://12713765
+@T3_retval = common global <16 x float> zeroinitializer, align 16
+
+; If alignment for alloc is smaller than or equal to stack alignment, but the 
+; preferred type alignment is bigger, the alignment will be clamped.
+; If alignment for alloca is bigger than stack alignment, the compiler
+; will emit an error.
+define void @test(<16 x float>* noalias sret %agg.result) nounwind ssp {
+entry:
+; CHECK: Requested Minimal Alignment exceeds the Stack Alignment!
+ %retval = alloca <16 x float>, align 16
+ %0 = load <16 x float>* @T3_retval, align 16
+ store <16 x float> %0, <16 x float>* %retval
+ %1 = load <16 x float>* %retval
+ store <16 x float> %1, <16 x float>* %agg.result, align 16
+ ret void
+}
index 273041dee34e08b4b3665b1b94e930f2938142c5..94adc9c67de539bf0be52a03c7681603681f7410 100644 (file)
@@ -39,7 +39,7 @@ entry:
 ; NO-REALIGN: add [[R2:r[0-9]+]], [[R1:r[0-9]+]], #16
 ; NO-REALIGN: vst1.64
 ; NO-REALIGN: vst1.64
- %retval = alloca <16 x float>, align 16
+ %retval = alloca <16 x float>, align 4
  %0 = load <16 x float>* @T3_retval, align 16
  store <16 x float> %0, <16 x float>* %retval
  %1 = load <16 x float>* %retval