diff options
-rw-r--r-- | lib/Transforms/Scalar/SROA.cpp | 16 | ||||
-rw-r--r-- | test/Transforms/SROA/alignment.ll | 23 |
2 files changed, 35 insertions, 4 deletions
diff --git a/lib/Transforms/Scalar/SROA.cpp b/lib/Transforms/Scalar/SROA.cpp index cf12cfca18..a8dc0533bf 100644 --- a/lib/Transforms/Scalar/SROA.cpp +++ b/lib/Transforms/Scalar/SROA.cpp @@ -3002,9 +3002,19 @@ bool SROA::rewriteAllocaPartition(AllocaInst &AI, assert(PI == P.begin() && "Begin offset is zero on later partition"); NewAI = &AI; } else { - // FIXME: The alignment here is overly conservative -- we could in many - // cases get away with much weaker alignment constraints. - NewAI = new AllocaInst(AllocaTy, 0, AI.getAlignment(), + unsigned Alignment = AI.getAlignment(); + if (!Alignment) { + // The minimum alignment which users can rely on when the explicit + // alignment is omitted or zero is that required by the ABI for this + // type. + Alignment = TD->getABITypeAlignment(AI.getAllocatedType()); + } + Alignment = MinAlign(Alignment, PI->BeginOffset); + // If we will get at least this much alignment from the type alone, leave + // the alloca's alignment unconstrained. + if (Alignment <= TD->getABITypeAlignment(AllocaTy)) + Alignment = 0; + NewAI = new AllocaInst(AllocaTy, 0, Alignment, AI.getName() + ".sroa." + Twine(PI - P.begin()), &AI); ++NumNewAllocas; diff --git a/test/Transforms/SROA/alignment.ll b/test/Transforms/SROA/alignment.ll index 953f5118ab..02a67551a3 100644 --- a/test/Transforms/SROA/alignment.ll +++ b/test/Transforms/SROA/alignment.ll @@ -30,7 +30,7 @@ entry: define void @test2() { ; CHECK: @test2 -; CHECK: alloca i16, align 2 +; CHECK: alloca i16 ; CHECK: load i8* %{{.*}}, align 1 ; CHECK: store i8 42, i8* %{{.*}}, align 1 ; CHECK: ret void @@ -62,3 +62,24 @@ entry: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %bptr, i8* %aaptr, i32 16, i32 2, i1 false) ret void } + +define void @test3(i8* %x) { +; Test that when we promote an alloca to a type with lower ABI alignment, we +; provide the needed explicit alignment that code using the alloca may be +; expecting. However, also check that any offset within an alloca can in turn +; reduce the alignment. +; CHECK: @test3 +; CHECK: alloca [22 x i8], align 8 +; CHECK: alloca [18 x i8], align 2 +; CHECK: ret void + +entry: + %a = alloca { i8*, i8*, i8* } + %b = alloca { i8*, i8*, i8* } + %a_raw = bitcast { i8*, i8*, i8* }* %a to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* %a_raw, i8* %x, i32 22, i32 8, i1 false) + %b_raw = bitcast { i8*, i8*, i8* }* %b to i8* + %b_gep = getelementptr i8* %b_raw, i32 6 + call void @llvm.memcpy.p0i8.p0i8.i32(i8* %b_gep, i8* %x, i32 18, i32 2, i1 false) + ret void +} |