diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -2602,7 +2602,9 @@ // A Load tagged with nonnull metadata is never null. if (const LoadInst *LI = dyn_cast(V)) - if (Q.IIQ.getMetadata(LI, LLVMContext::MD_nonnull)) + if (Q.IIQ.getMetadata(LI, LLVMContext::MD_nonnull) || + (Q.IIQ.getMetadata(LI, LLVMContext::MD_dereferenceable) && + !NullPointerIsDefined(LI->getFunction(), PtrTy->getAddressSpace()))) return true; if (const auto *Call = dyn_cast(V)) { diff --git a/llvm/test/Transforms/InstSimplify/icmp.ll b/llvm/test/Transforms/InstSimplify/icmp.ll --- a/llvm/test/Transforms/InstSimplify/icmp.ll +++ b/llvm/test/Transforms/InstSimplify/icmp.ll @@ -258,3 +258,23 @@ %cmp = icmp ne i8 %sub, %x ret i1 %cmp } + +define i1 @load_ptr(ptr %p) { +; CHECK-LABEL: @load_ptr( +; CHECK-NEXT: ret i1 true +; + %load_p = load ptr, ptr %p, !dereferenceable !{i64 8} + %r = icmp ne ptr %load_p, null + ret i1 %r +} + +define i1 @load_ptr_null_valid(ptr %p) null_pointer_is_valid { +; CHECK-LABEL: @load_ptr_null_valid( +; CHECK-NEXT: [[LOAD_P:%.*]] = load ptr, ptr [[P:%.*]], align 8, !dereferenceable !0 +; CHECK-NEXT: [[R:%.*]] = icmp ne ptr [[LOAD_P]], null +; CHECK-NEXT: ret i1 [[R]] +; + %load_p = load ptr, ptr %p, !dereferenceable !{i64 8} + %r = icmp ne ptr %load_p, null + ret i1 %r +}