diff --git a/llvm/lib/Transforms/Scalar/NewGVN.cpp b/llvm/lib/Transforms/Scalar/NewGVN.cpp index 3eb118908959f..0a0ea65a1f036 100644 --- a/llvm/lib/Transforms/Scalar/NewGVN.cpp +++ b/llvm/lib/Transforms/Scalar/NewGVN.cpp @@ -1529,10 +1529,19 @@ NewGVN::performSymbolicLoadCoercion(Type *LoadType, Value *LoadPtr, } } + if (auto *II = dyn_cast(DepInst)) { + auto *LifetimePtr = II->getOperand(1); + if (II->getIntrinsicID() == Intrinsic::lifetime_start && + (LoadPtr == lookupOperandLeader(LifetimePtr) || + AA->isMustAlias(LoadPtr, LifetimePtr))) + return createConstantExpression(UndefValue::get(LoadType)); + } + // All of the below are only true if the loaded pointer is produced // by the dependent instruction. - if (LoadPtr != lookupOperandLeader(DepInst) && - DepInst->getType()->isPointerTy() && !AA->isMustAlias(LoadPtr, DepInst)) + if (!DepInst->getType()->isPointerTy() || + (LoadPtr != lookupOperandLeader(DepInst) && + !AA->isMustAlias(LoadPtr, DepInst))) return nullptr; // If this load really doesn't depend on anything, then we must be loading an // undef value. This can happen when loading for a fresh allocation with no @@ -1540,12 +1549,6 @@ NewGVN::performSymbolicLoadCoercion(Type *LoadType, Value *LoadPtr, // that the result of the allocation is pointer equal to the load ptr. if (isa(DepInst)) { return createConstantExpression(UndefValue::get(LoadType)); - } - // If this load occurs either right after a lifetime begin, - // then the loaded value is undefined. - else if (auto *II = dyn_cast(DepInst)) { - if (II->getIntrinsicID() == Intrinsic::lifetime_start) - return createConstantExpression(UndefValue::get(LoadType)); } else if (auto *InitVal = getInitialValueOfAllocation(DepInst, TLI, LoadType)) return createConstantExpression(InitVal); diff --git a/llvm/test/Transforms/NewGVN/coercion-different-ptr.ll b/llvm/test/Transforms/NewGVN/coercion-different-ptr.ll index 61a6a633788e1..dfd6d7d9f53a5 100644 --- a/llvm/test/Transforms/NewGVN/coercion-different-ptr.ll +++ b/llvm/test/Transforms/NewGVN/coercion-different-ptr.ll @@ -2,7 +2,7 @@ ; RUN: opt -S -passes=newgvn < %s | FileCheck %s -; FIXME: MemorySSA says that load1 depends on the lifetime start. +; MemorySSA says that load1 depends on the lifetime start. ; That's OK since MemorySSA is may-alias; however, NewGVN should ; check whether the lifetime start *actually* defines the loaded pointer ; before simplifying to uninitialized memory. @@ -13,7 +13,8 @@ define void @foo(ptr %arg) { ; CHECK-NEXT: [[ALLOCA:%.*]] = alloca i8, align 16 ; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 1, ptr [[ALLOCA]]) ; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[ARG]], align 8 -; CHECK-NEXT: [[CALL:%.*]] = call ptr undef(ptr [[ALLOCA]]) +; CHECK-NEXT: [[LOAD1:%.*]] = load ptr, ptr [[LOAD]], align 8 +; CHECK-NEXT: [[CALL:%.*]] = call ptr [[LOAD1]](ptr [[ALLOCA]]) ; CHECK-NEXT: ret void ; bb: