InstCombine: propagate nonNull through assume
authorRamkumar Ramachandra <artagnon@gmail.com>
Mon, 9 Feb 2015 01:13:13 +0000 (01:13 +0000)
committerRamkumar Ramachandra <artagnon@gmail.com>
Mon, 9 Feb 2015 01:13:13 +0000 (01:13 +0000)
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

lib/Transforms/InstCombine/InstCombineCalls.cpp
test/Transforms/InstCombine/assume.ll

index 87dc8621a95b2c3dace89b9bae05a81dadf25e63..54b8a544ce96c70e21610957f8efba1547b91cce 100644 (file)
@@ -1081,12 +1081,19 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
           cast<Constant>(RHS)->isNullValue()) {
         LoadInst* LI = cast<LoadInst>(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<CallInst>(LIOperand))
+            I->addAttribute(AttributeSet::ReturnIndex, Attribute::NonNull);
+          else if (InvokeInst *I = dyn_cast<InvokeInst>(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,
index 7e45c04622ac74461cc5526b09013a5f87ff6ac9..2c096e736d5ee0429af31722ed478beab5999090 100644 (file)
@@ -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 }