From da748f1c3d92f7bd02ee3292f3d9654d4f0f4a45 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Fri, 4 Aug 2017 17:09:11 +0000 Subject: [PATCH] [ArgPromotion] Preserve alignment of byval argument in new alloca The frontend may have requested a higher alignment for any reason, and downstream optimizations may already have taken advantage of it. We should keep the same alignment when moving the allocation from the parameter area to the local variable area. Fixes PR34038 llvm-svn: 310071 --- llvm/lib/Transforms/IPO/ArgumentPromotion.cpp | 2 +- .../Transforms/ArgumentPromotion/byval.ll | 43 ++++++++++++++----- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp index 53223ab44316..72bae203ee94 100644 --- a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp +++ b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -356,7 +356,7 @@ doPromotion(Function *F, SmallPtrSetImpl &ArgsToPromote, // Just add all the struct element types. Type *AgTy = cast(I->getType())->getElementType(); Value *TheAlloca = new AllocaInst(AgTy, DL.getAllocaAddrSpace(), nullptr, - "", InsertPt); + I->getParamAlignment(), "", InsertPt); StructType *STy = cast(AgTy); Value *Idxs[2] = {ConstantInt::get(Type::getInt32Ty(F->getContext()), 0), nullptr}; diff --git a/llvm/test/Transforms/ArgumentPromotion/byval.ll b/llvm/test/Transforms/ArgumentPromotion/byval.ll index 58475fc89607..00542e3ec244 100644 --- a/llvm/test/Transforms/ArgumentPromotion/byval.ll +++ b/llvm/test/Transforms/ArgumentPromotion/byval.ll @@ -6,24 +6,45 @@ target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:1 %struct.ss = type { i32, i64 } define internal void @f(%struct.ss* byval %b) nounwind { -; CHECK-LABEL: define internal void @f(i32 %b.0, i64 %b.1) entry: - %tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0 ; [#uses=2] - %tmp1 = load i32, i32* %tmp, align 4 ; [#uses=1] - %tmp2 = add i32 %tmp1, 1 ; [#uses=1] + %tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0 + %tmp1 = load i32, i32* %tmp, align 4 + %tmp2 = add i32 %tmp1, 1 store i32 %tmp2, i32* %tmp, align 4 ret void } -define i32 @main() nounwind { -; CHECK-LABEL: define i32 @main +; CHECK-LABEL: define internal void @f(i32 %b.0, i64 %b.1) +; CHECK: alloca %struct.ss{{$}} +; CHECK: store i32 %b.0 +; CHECK: store i64 %b.1 + +define internal void @g(%struct.ss* byval align 32 %b) nounwind { entry: - %S = alloca %struct.ss ; <%struct.ss*> [#uses=4] - %tmp1 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 0 ; [#uses=1] + %tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0 + %tmp1 = load i32, i32* %tmp, align 4 + %tmp2 = add i32 %tmp1, 1 + store i32 %tmp2, i32* %tmp, align 4 + ret void +} + +; CHECK-LABEL: define internal void @g(i32 %b.0, i64 %b.1) +; CHECK: alloca %struct.ss, align 32 +; CHECK: store i32 %b.0 +; CHECK: store i64 %b.1 + +define i32 @main() nounwind { +entry: + %S = alloca %struct.ss + %tmp1 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 0 store i32 1, i32* %tmp1, align 8 - %tmp4 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 1 ; [#uses=1] + %tmp4 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 1 store i64 2, i64* %tmp4, align 4 - call void @f( %struct.ss* byval %S ) nounwind -; CHECK: call void @f(i32 %{{.*}}, i64 %{{.*}}) + call void @f(%struct.ss* byval %S) nounwind + call void @g(%struct.ss* byval %S) nounwind ret i32 0 } + +; CHECK-LABEL: define i32 @main +; CHECK: call void @f(i32 %{{.*}}, i64 %{{.*}}) +; CHECK: call void @g(i32 %{{.*}}, i64 %{{.*}})