diff --git a/lib/Transforms/Scalar/SROA.cpp b/lib/Transforms/Scalar/SROA.cpp index 7d33259c030..67d90a346f2 100644 --- a/lib/Transforms/Scalar/SROA.cpp +++ b/lib/Transforms/Scalar/SROA.cpp @@ -2890,7 +2890,13 @@ private: (void)New; DEBUG(dbgs() << " to: " << *New << "\n"); - return true; + + // Lifetime intrinsics are only promotable if they cover the whole alloca. + // (In theory, intrinsics which partially cover an alloca could be + // promoted, but PromoteMemToReg doesn't handle that case.) + bool IsWholeAlloca = NewBeginOffset == NewAllocaBeginOffset && + NewEndOffset == NewAllocaEndOffset; + return IsWholeAlloca; } bool visitPHINode(PHINode &PN) { diff --git a/test/Transforms/SROA/basictest.ll b/test/Transforms/SROA/basictest.ll index 968669ad4f6..75fe279849d 100644 --- a/test/Transforms/SROA/basictest.ll +++ b/test/Transforms/SROA/basictest.ll @@ -1669,3 +1669,18 @@ entry: } declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind + +define void @PR27999() unnamed_addr { +; CHECK-LABEL: @PR27999( +; CHECK: alloca [2 x i64], align 8 +; CHECK: call void @llvm.lifetime.start(i64 16, +; CHECK: call void @llvm.lifetime.end(i64 8, +entry-block: + %0 = alloca [2 x i64], align 8 + %1 = bitcast [2 x i64]* %0 to i8* + call void @llvm.lifetime.start(i64 16, i8* %1) + %2 = getelementptr inbounds [2 x i64], [2 x i64]* %0, i32 0, i32 1 + %3 = bitcast i64* %2 to i8* + call void @llvm.lifetime.end(i64 8, i8* %3) + ret void +}