Index: llvm/trunk/docs/LangRef.rst =================================================================== --- llvm/trunk/docs/LangRef.rst +++ llvm/trunk/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,14 @@ 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 must reference a single +metadata name ```` corresponding to a metadata node with no +entries. The existence of the ``!nonnull`` metadata on the +instruction tells the optimizer that the value loaded is known to +never be null. This is analogous to the ''nonnull'' attribute +on parameters and return values. This metadata can only be applied +to loads of a pointer type. + Semantics: """""""""" Index: llvm/trunk/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/trunk/lib/Analysis/ValueTracking.cpp +++ llvm/trunk/lib/Analysis/ValueTracking.cpp @@ -2622,6 +2622,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: llvm/trunk/test/Transforms/InstSimplify/compare.ll =================================================================== --- llvm/trunk/test/Transforms/InstSimplify/compare.ll +++ llvm/trunk/test/Transforms/InstSimplify/compare.ll @@ -949,6 +949,29 @@ ; CHECK: ret } +define i1 @nonnull_load(i32** %addr) { + %ptr = load i32** %addr, !nonnull !{} + %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 !{} + %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 !{} + %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 {