diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp --- a/llvm/lib/Transforms/Scalar/SROA.cpp +++ b/llvm/lib/Transforms/Scalar/SROA.cpp @@ -1983,6 +1983,15 @@ uint64_t RelBegin = S.beginOffset() - AllocBeginOffset; uint64_t RelEnd = S.endOffset() - AllocBeginOffset; + // Lifetime intrinsics operate over the whole alloca whose sizes are usually + // larger than other load/store slices (RelEnd > Size). But lifetime are + // always promotable and should not impact other slices' promotability of the + // partition. + if (IntrinsicInst *II = dyn_cast(S.getUse()->getUser())) { + if (II->isLifetimeStartOrEnd()) + return true; + } + // We can't reasonably handle cases where the load or store extends past // the end of the alloca's type and into its padding. if (RelEnd > Size) diff --git a/llvm/test/Transforms/SROA/lifetime-intrinsic.ll b/llvm/test/Transforms/SROA/lifetime-intrinsic.ll --- a/llvm/test/Transforms/SROA/lifetime-intrinsic.ll +++ b/llvm/test/Transforms/SROA/lifetime-intrinsic.ll @@ -14,11 +12,9 @@ define i16 @with_lifetime(i32 %a, i32 %b) #0 { ; CHECK-LABEL: @with_lifetime( -; CHECK-NEXT: [[ARR_SROA_0_SROA_0_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[A:%.*]] to i16 -; CHECK-NEXT: [[ARR_SROA_0_SROA_4_0_EXTRACT_SHIFT:%.*]] = lshr i32 [[A]], 16 -; CHECK-NEXT: [[ARR_SROA_0_SROA_4_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[ARR_SROA_0_SROA_4_0_EXTRACT_SHIFT]] to i16 +; CHECK-NEXT: [[ARR_SROA_0_0_EXTRACT_TRUNC:%.*]] = trunc i32 [[A:%.*]] to i16 ; CHECK-NEXT: [[ARR_SROA_4_4_EXTRACT_TRUNC:%.*]] = trunc i32 [[B:%.*]] to i16 -; CHECK-NEXT: [[RET:%.*]] = add i16 [[ARR_SROA_0_SROA_0_0_EXTRACT_TRUNC]], [[ARR_SROA_4_4_EXTRACT_TRUNC]] +; CHECK-NEXT: [[RET:%.*]] = add i16 [[ARR_SROA_0_0_EXTRACT_TRUNC]], [[ARR_SROA_4_4_EXTRACT_TRUNC]] ; CHECK-NEXT: ret i16 [[RET]] ; %arr = alloca %i32x2, align 4