Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -5157,7 +5157,7 @@ :: - = load [volatile] * [, align ][, !nontemporal !][, !invariant.load !] + = load [volatile] * [, align ][, !nontemporal !][, !invariant.load !][, !nonnull !] = load atomic [volatile] * [singlethread] , align ! = !{ i32 1 } @@ -5213,6 +5213,15 @@ execution. The optimizer may then move this load around, for example, by hoisting it out of loops using loop invariant code motion. +The optional ``!nonnull`` metadata tells the optimizer and code +generator that the value loaded is known to never be null. This +can be used to remove null tests on the returned value, but does +not (by itself) imply that the memory pointed to is dereferenceable. +This is analogous to the ''nonnull'' attribute on parameters and +return values. This metadata can only be applied to loads of a +pointer type. The value of the metadata node pointed to by +''(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 @@ -949,6 +949,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 {