[llvm-commits] [llvm] r122234 - in /llvm/trunk: lib/Transforms/Utils/InlineFunction.cpp test/Transforms/Inline/byval.ll

Chris Lattner sabre at nondot.org
Sun Dec 19 23:45:28 PST 2010


Author: lattner
Date: Mon Dec 20 01:45:28 2010
New Revision: 122234

URL: http://llvm.org/viewvc/llvm-project?rev=122234&view=rev
Log:
fix PR8769, a miscompilation by inliner when inlining a function with a byval
argument.  The generated alloca has to have at least the alignment of the
byval, if not, the client may be making assumptions that the new alloca won't
satisfy.

Modified:
    llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp
    llvm/trunk/test/Transforms/Inline/byval.ll

Modified: llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp?rev=122234&r1=122233&r2=122234&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp Mon Dec 20 01:45:28 2010
@@ -252,7 +252,6 @@
       CalledFunc->isDeclaration() || // call, or call to a vararg function!
       CalledFunc->getFunctionType()->isVarArg()) return false;
 
-
   // If the call to the callee is not a tail call, we must clear the 'tail'
   // flags on any calls that we inline.
   bool MustClearTailCallFlags =
@@ -308,14 +307,19 @@
       if (CalledFunc->paramHasAttr(ArgNo+1, Attribute::ByVal) &&
           !CalledFunc->onlyReadsMemory()) {
         const Type *AggTy = cast<PointerType>(I->getType())->getElementType();
-        const Type *VoidPtrTy = 
-            Type::getInt8PtrTy(Context);
+        const Type *VoidPtrTy = Type::getInt8PtrTy(Context);
 
         // Create the alloca.  If we have TargetData, use nice alignment.
         unsigned Align = 1;
-        if (IFI.TD) Align = IFI.TD->getPrefTypeAlignment(AggTy);
-        Value *NewAlloca = new AllocaInst(AggTy, 0, Align, 
-                                          I->getName(), 
+        if (IFI.TD)
+          Align = IFI.TD->getPrefTypeAlignment(AggTy);
+        
+        // If the byval had an alignment specified, we *must* use at least that
+        // alignment, as it is required by the byval argument (and uses of the
+        // pointer inside the callee).
+        Align = std::max(Align, CalledFunc->getParamAlignment(ArgNo+1));
+        
+        Value *NewAlloca = new AllocaInst(AggTy, 0, Align, I->getName(), 
                                           &*Caller->begin()->begin());
         // Emit a memcpy.
         const Type *Tys[3] = {VoidPtrTy, VoidPtrTy, Type::getInt64Ty(Context)};

Modified: llvm/trunk/test/Transforms/Inline/byval.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/byval.ll?rev=122234&r1=122233&r2=122234&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/Inline/byval.ll (original)
+++ llvm/trunk/test/Transforms/Inline/byval.ll Mon Dec 20 01:45:28 2010
@@ -56,3 +56,27 @@
 ; CHECK-NOT: call void @llvm.memcpy
 ; CHECK: ret i32
 }
+
+
+; Inlining a byval with an explicit alignment needs to use *at least* that
+; alignment on the generated alloca.
+; PR8769
+declare void @g3(%struct.ss* %p)
+
+define internal void @f3(%struct.ss* byval align 64 %b) nounwind {
+   call void @g3(%struct.ss* %b)  ;; Could make alignment assumptions!
+   ret void
+}
+
+define void @test3() nounwind  {
+entry:
+	%S = alloca %struct.ss, align 1  ;; May not be aligned.
+	call void @f3( %struct.ss* byval align 64 %S) nounwind 
+	ret void
+; CHECK: @test3()
+; CHECK: %b = alloca %struct.ss, align 64
+; CHECK: %S = alloca %struct.ss
+; CHECK: call void @llvm.memcpy
+; CHECK: call void @g3(%struct.ss* %b)
+; CHECK: ret void
+}





More information about the llvm-commits mailing list