[PATCH] D28204: [ValueTracking] use nonnull argument attribute to eliminate null checks

Sanjay Patel via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sat Dec 31 12:06:15 PST 2016


spatel created this revision.
spatel added reviewers: chandlerc, majnemer, reames, mkuper, davide.
spatel added a subscriber: llvm-commits.
Herald added a subscriber: mcrosier.

Enhancing value tracking's analysis of null-ness was suggested in https://reviews.llvm.org/D27855, so here's a first attempt at that.

Irony: the ultimate motivation for this change is to make LLVM itself faster by improving the IR for dyn_cast, but we can't do that without adding analysis and transforms that will likely slow us down even more until we have all of the pieces in place.

Ie, this won't solve PR28430 alone:
https://llvm.org/bugs/show_bug.cgi?id=28430


https://reviews.llvm.org/D28204

Files:
  include/llvm/Analysis/ValueTracking.h
  lib/Analysis/ValueTracking.cpp
  test/Analysis/ValueTracking/known-nonnull-at.ll


Index: test/Analysis/ValueTracking/known-nonnull-at.ll
===================================================================
--- test/Analysis/ValueTracking/known-nonnull-at.ll
+++ test/Analysis/ValueTracking/known-nonnull-at.ll
@@ -8,8 +8,7 @@
 define i1 @caller1(i8* %x, i8* %y) {
 ; CHECK-LABEL: @caller1(
 ; CHECK-NEXT:    call void @bar(i8* %x, i8* %y)
-; CHECK-NEXT:    [[NULL_CHECK:%.*]] = icmp eq i8* %y, null
-; CHECK-NEXT:    ret i1 [[NULL_CHECK]]
+; CHECK-NEXT:    ret i1 false
 ;
   call void @bar(i8* %x, i8* %y)
   %null_check = icmp eq i8* %y, null
@@ -34,8 +33,7 @@
 define i1 @caller3(i8* %x, i8* %y) {
 ; CHECK-LABEL: @caller3(
 ; CHECK-NEXT:    call void @bar(i8* %x, i8* %y)
-; CHECK-NEXT:    [[NULL_CHECK:%.*]] = icmp ne i8* %y, null
-; CHECK-NEXT:    ret i1 [[NULL_CHECK]]
+; CHECK-NEXT:    ret i1 true
 ;
   call void @bar(i8* %x, i8* %y)
   %null_check = icmp ne i8* %y, null
Index: lib/Analysis/ValueTracking.cpp
===================================================================
--- lib/Analysis/ValueTracking.cpp
+++ lib/Analysis/ValueTracking.cpp
@@ -1785,10 +1785,12 @@
   return true;
 }
 
-/// Return true if the given value is known to be non-zero when defined.
-/// For vectors return true if every element is known to be non-zero when
-/// defined. Supports values with integer or pointer type and vectors of
-/// integers.
+/// Return true if the given value is known to be non-zero when defined. For
+/// vectors, return true if every element is known to be non-zero when
+/// defined. For pointers, if the context instruction and dominator tree are
+/// specified, perform context-sensitive analysis and return true if the
+/// pointer couldn't possibly be null at the specified instruction.
+/// Supports values with integer or pointer type and vectors of integers.
 bool isKnownNonZero(const Value *V, unsigned Depth, const Query &Q) {
   if (auto *C = dyn_cast<Constant>(V)) {
     if (C->isNullValue())
@@ -1831,7 +1833,7 @@
 
   // Check for pointer simplifications.
   if (V->getType()->isPointerTy()) {
-    if (isKnownNonNull(V))
+    if (isKnownNonNullAt(V, Q.CxtI, Q.DT))
       return true;
     if (const GEPOperator *GEP = dyn_cast<GEPOperator>(V))
       if (isGEPKnownNonNull(GEP, Depth, Q))
@@ -3377,6 +3379,16 @@
     if (NumUsesExplored >= DomConditionsMaxUses)
       break;
     NumUsesExplored++;
+
+    // If the value is used as an argument to a function call, then argument
+    // attributes may provide an answer about null-ness.
+    if (auto *Call = dyn_cast<CallInst>(U))
+      if (auto *CalledFunc = Call->getCalledFunction())
+        for (Argument &Arg : CalledFunc->args())
+          if (Call->getArgOperand(Arg.getArgNo()) == V &&
+              Arg.hasNonNullAttr() && DT->dominates(Call, CtxI))
+            return true;
+
     // Consider only compare instructions uniquely controlling a branch
     CmpInst::Predicate Pred;
     if (!match(const_cast<User *>(U),
Index: include/llvm/Analysis/ValueTracking.h
===================================================================
--- include/llvm/Analysis/ValueTracking.h
+++ include/llvm/Analysis/ValueTracking.h
@@ -86,8 +86,10 @@
 
   /// Return true if the given value is known to be non-zero when defined. For
   /// vectors, return true if every element is known to be non-zero when
-  /// defined. Supports values with integer or pointer type and vectors of
-  /// integers.
+  /// defined. For pointers, if the context instruction and dominator tree are
+  /// specified, perform context-sensitive analysis and return true if the
+  /// pointer couldn't possibly be null at the specified instruction.
+  /// Supports values with integer or pointer type and vectors of integers.
   bool isKnownNonZero(const Value *V, const DataLayout &DL, unsigned Depth = 0,
                       AssumptionCache *AC = nullptr,
                       const Instruction *CxtI = nullptr,


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D28204.82777.patch
Type: text/x-patch
Size: 3901 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20161231/d1b9fef8/attachment.bin>


More information about the llvm-commits mailing list