Index: lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCalls.cpp +++ lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1102,6 +1102,31 @@ return EraseInstFromFunction(*II); } + // assume( (load addr) != null ) -> add 'nonnull' metadata to load + if (ICmpInst* ICmp = dyn_cast(IIOperand)) { + Value *LHS = ICmp->getOperand(0); + Value *RHS = ICmp->getOperand(1); + // We can only update a load if the ICmp post dominates the load - there + // can't be a path by which the load might be null and not reach the + // assume. Rather than solve the general case, we handle only a ICmp in + // the same basic block as the Load since that's trivially post + // dominated. We could try to be fancier here, but it's not clear that + // doing so is worthwhile. + if (ICmpInst::ICMP_NE == ICmp->getPredicate() && + isa(LHS) && + cast(LHS)->getParent() == ICmp->getParent() && + isa(RHS) && + RHS->getType()->isPointerTy() && + cast(RHS)->isNullValue()) { + LoadInst* LI = cast(LHS); + MDNode* MD = MDNode::get(II->getContext(), ArrayRef()); + LI->setMetadata(LLVMContext::MD_nonnull, MD); + // No longer needed + return EraseInstFromFunction(*II); + } + // TODO: apply nonnull return attributes to calls and invokes + // TODO: apply range metadata for range check patterns? + } // If there is a dominating assume with the same condition as this one, // then this one is redundant, and should be removed. APInt KnownZero(1, 0), KnownOne(1, 0); Index: test/Transforms/InstCombine/assume.ll =================================================================== --- test/Transforms/InstCombine/assume.ll +++ test/Transforms/InstCombine/assume.ll @@ -186,6 +186,43 @@ ; CHECK: ret i32 0 } +declare void @escape(i32* %a) + +; Do we canonicalize a nonnull assumption on a load into +; metadata form? +define i1 @nonnull1(i32** %a) { +entry: + %load = load i32** %a + %cmp = icmp ne i32* %load, null + tail call void @llvm.assume(i1 %cmp) + tail call void @escape(i32* %load) + %rval = icmp eq i32* %load, null + ret i1 %rval + +; CHECK-LABEL: @nonnull1 +; CHECK: !nonnull +; CHECK-NOT: call void @llvm.assume +; CHECK: ret i1 false +} + +; Make sure the above canonicalization applies only +; to pointer types. Doing otherwise would be illegal. +define i1 @nonnull2(i32* %a) { +entry: + %load = load i32* %a + %cmp = icmp ne i32 %load, 0 + tail call void @llvm.assume(i1 %cmp) + %rval = icmp eq i32 %load, 0 + ret i1 %rval + +; CHECK-LABEL: @nonnull2 +; CHECK-NOT: !nonnull +; CHECK: call void @llvm.assume +} + + + + attributes #0 = { nounwind uwtable } attributes #1 = { nounwind }