From: Ramkumar Ramachandra Date: Mon, 9 Feb 2015 01:13:13 +0000 (+0000) Subject: InstCombine: propagate nonNull through assume X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=5439a80dcadb452a27eacc6a6f14b007f04bee5b InstCombine: propagate nonNull through assume Make assume (load (call|invoke) != null) set nonNull return attribute for the call and invoke. Also include tests. Differential Revision: http://reviews.llvm.org/D7107 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228556 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index 87dc8621a95..54b8a544ce9 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1081,12 +1081,19 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { cast(RHS)->isNullValue()) { LoadInst* LI = cast(LHS); if (isValidAssumeForContext(II, LI, DL, DT)) { + // assume( load (call|invoke) != null ) -> add 'nonnull' return + // attribute + Value *LIOperand = LI->getOperand(0); + if (CallInst *I = dyn_cast(LIOperand)) + I->addAttribute(AttributeSet::ReturnIndex, Attribute::NonNull); + else if (InvokeInst *I = dyn_cast(LIOperand)) + I->addAttribute(AttributeSet::ReturnIndex, Attribute::NonNull); + MDNode *MD = MDNode::get(II->getContext(), None); LI->setMetadata(LLVMContext::MD_nonnull, MD); 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, diff --git a/test/Transforms/InstCombine/assume.ll b/test/Transforms/InstCombine/assume.ll index 7e45c04622a..2c096e736d5 100644 --- a/test/Transforms/InstCombine/assume.ll +++ b/test/Transforms/InstCombine/assume.ll @@ -257,8 +257,45 @@ entry: ; CHECK: call void @llvm.assume } +declare i32** @id(i32** %a) +; Check that nonnull return attribute is applied to call +define i1 @nonnull5(i32** %a) { +entry: + %idr = call i32** @id(i32** %a) + %load = load i32** %idr + %cmp = icmp ne i32* %load, null + tail call void @llvm.assume(i1 %cmp) + %rval = icmp eq i32* %load, null + ret i1 %rval + +; CHECK-LABEL: @nonnull5 +; CHECK: call nonnull +; CHECK-NOT: call void @llvm.assume +; CHECK: ret i1 false +} + +declare i32 @__personality0(...) +; Check that nonnull return attribute is applied to invoke +define i1 @nonnull6(i32** %a) { +entry: + %idr = invoke i32** @id(i32** %a) to label %norm unwind label %lpad +norm: + %load = load i32** %idr + %cmp = icmp ne i32* %load, null + tail call void @llvm.assume(i1 %cmp) + %rval = icmp eq i32* %load, null + ret i1 %rval +lpad: + %res = landingpad { i8*, i32 } personality i32 (...)* @__personality0 cleanup + resume { i8*, i32 } undef + +; CHECK-LABEL: @nonnull6 +; CHECK: invoke nonnull +; CHECK-NOT: call void @llvm.assume +; CHECK: ret i1 false +} attributes #0 = { nounwind uwtable } attributes #1 = { nounwind }