Index: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -2081,6 +2081,10 @@ if (const GlobalValue *GV = dyn_cast(V)) return !GV->hasExternalWeakLinkage(); + // A Load tagged w/nonnull metadata is never null. + if (const LoadInst *LI = dyn_cast(V)) + return LI->getMetadata("nonnull"); + if (ImmutableCallSite CS = V) if (CS.isReturnNonNull()) return true; Index: test/Transforms/InstSimplify/compare.ll =================================================================== --- test/Transforms/InstSimplify/compare.ll +++ test/Transforms/InstSimplify/compare.ll @@ -917,6 +917,29 @@ ; CHECK: ret } +define i1 @nonnull_load(i32** %addr) { + %ptr = load i32** %addr, !nonnull !{i1 true} + %cmp = icmp eq i32* %ptr, null + ret i1 %cmp +; CHECK-LABEL: @nonnull_load +; CHECK: ret i1 false +} + +define i1 @nonnull_load_as_outer(i32* addrspace(1)* %addr) { + %ptr = load i32* addrspace(1)* %addr, !nonnull !{i1 true} + %cmp = icmp eq i32* %ptr, null + ret i1 %cmp +; CHECK-LABEL: @nonnull_load_as_outer +; CHECK: ret i1 false +} +define i1 @nonnull_load_as_inner(i32 addrspace(1)** %addr) { + %ptr = load i32 addrspace(1)** %addr, !nonnull !{i1 true} + %cmp = icmp eq i32 addrspace(1)* %ptr, null + ret i1 %cmp +; CHECK-LABEL: @nonnull_load_as_inner +; CHECK: ret i1 false +} + ; If a bit is known to be zero for A and known to be one for B, ; then A and B cannot be equal. define i1 @icmp_eq_const(i32 %a) nounwind {