]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/58480 (Use attribute((nonnull)) to optimize callers)
authorMarc Glisse <marc.glisse@inria.fr>
Tue, 8 Oct 2013 10:39:49 +0000 (12:39 +0200)
committerMarc Glisse <glisse@gcc.gnu.org>
Tue, 8 Oct 2013 10:39:49 +0000 (10:39 +0000)
2013-10-08  Marc Glisse  <marc.glisse@inria.fr>

PR tree-optimization/58480
gcc/
* tree-vrp.c (infer_nonnull_range): New function.
(infer_value_range): Call infer_nonnull_range.

gcc/testsuite/
* gcc.dg/tree-ssa/pr58480.c: New file.

From-SVN: r203271

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/pr58480.c [new file with mode: 0644]
gcc/tree-vrp.c

index 80343b91d8baac4c75dc0a99c2e730714022d245..dc1bc7e41b9371e4192594f728988cd2677a7864 100644 (file)
@@ -1,3 +1,9 @@
+2013-10-08  Marc Glisse  <marc.glisse@inria.fr>
+
+       PR tree-optimization/58480
+       * tree-vrp.c (infer_nonnull_range): New function.
+       (infer_value_range): Call infer_nonnull_range.
+
 2013-10-08  Dehao Chen  <dehao@google.com>
 
        PR tree-optimization/58619
index 60242b648f40cf8f572a84628a49b06f82f76838..86fb8eae774da7180fa9b3add64d1a2f07d48f9c 100644 (file)
@@ -1,3 +1,8 @@
+2013-10-08  Marc Glisse  <marc.glisse@inria.fr>
+
+       PR tree-optimization/58480
+       * gcc.dg/tree-ssa/pr58480.c: New file.
+
 2013-10-07  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
 
        * gcc.target/powerpc/pr43154.c: Skip for ppc64 little endian.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr58480.c b/gcc/testsuite/gcc.dg/tree-ssa/pr58480.c
new file mode 100644 (file)
index 0000000..a42edf9
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile { target { ! keeps_null_pointer_checks } } } */
+/* { dg-options "-O2 -fdump-tree-vrp1" } */
+
+extern void eliminate (void);
+extern void* f1 (void *a, void *b) __attribute__((nonnull));
+extern void* f2 (void *a, void *b) __attribute__((nonnull(2)));
+void g1 (void*p, void*q){
+  f1 (q, p);
+  if (p == 0)
+    eliminate ();
+}
+void g2 (void*p, void*q){
+  f2 (q, p);
+  if (p == 0)
+    eliminate ();
+}
+
+/* { dg-final { scan-tree-dump-times "Folding predicate\[^\\n\]*to 0" 2 "vrp1" } } */
+/* { dg-final { cleanup-tree-dump "vrp1" } } */
index cf0f1b1fce56e8701436bdbcbb502c1225dcb086..156a58ff5ca1385a864b97520ee54314ff48dcee 100644 (file)
@@ -4462,6 +4462,56 @@ fp_predicate (gimple stmt)
 }
 
 
+/* If OP can be inferred to be non-zero after STMT executes, return true.  */
+
+static bool
+infer_nonnull_range (gimple stmt, tree op)
+{
+  /* We can only assume that a pointer dereference will yield
+     non-NULL if -fdelete-null-pointer-checks is enabled.  */
+  if (!flag_delete_null_pointer_checks
+      || !POINTER_TYPE_P (TREE_TYPE (op))
+      || gimple_code (stmt) == GIMPLE_ASM)
+    return false;
+
+  unsigned num_uses, num_loads, num_stores;
+
+  count_uses_and_derefs (op, stmt, &num_uses, &num_loads, &num_stores);
+  if (num_loads + num_stores > 0)
+    return true;
+
+  if (gimple_code (stmt) == GIMPLE_CALL)
+    {
+      tree fntype = gimple_call_fntype (stmt);
+      tree attrs = TYPE_ATTRIBUTES (fntype);
+      for (; attrs; attrs = TREE_CHAIN (attrs))
+       {
+         attrs = lookup_attribute ("nonnull", attrs);
+
+         /* If "nonnull" wasn't specified, we know nothing about
+            the argument.  */
+         if (attrs == NULL_TREE)
+           return false;
+
+         /* If "nonnull" applies to all the arguments, then ARG
+            is non-null.  */
+         if (TREE_VALUE (attrs) == NULL_TREE)
+           return true;
+
+         /* Now see if op appears in the nonnull list.  */
+         for (tree t = TREE_VALUE (attrs); t; t = TREE_CHAIN (t))
+           {
+             int idx = TREE_INT_CST_LOW (TREE_VALUE (t)) - 1;
+             tree arg = gimple_call_arg (stmt, idx);
+             if (op == arg)
+               return true;
+           }
+       }
+    }
+
+  return false;
+}
+
 /* If the range of values taken by OP can be inferred after STMT executes,
    return the comparison code (COMP_CODE_P) and value (VAL_P) that
    describes the inferred range.  Return true if a range could be
@@ -4479,7 +4529,7 @@ infer_value_range (gimple stmt, tree op, enum tree_code *comp_code_p, tree *val_
     return false;
 
   /* Similarly, don't infer anything from statements that may throw
-     exceptions.  */
+     exceptions. ??? Relax this requirement?  */
   if (stmt_could_throw_p (stmt))
     return false;
 
@@ -4490,21 +4540,11 @@ infer_value_range (gimple stmt, tree op, enum tree_code *comp_code_p, tree *val_
   if (stmt_ends_bb_p (stmt) && EDGE_COUNT (gimple_bb (stmt)->succs) == 0)
     return false;
 
-  /* We can only assume that a pointer dereference will yield
-     non-NULL if -fdelete-null-pointer-checks is enabled.  */
-  if (flag_delete_null_pointer_checks
-      && POINTER_TYPE_P (TREE_TYPE (op))
-      && gimple_code (stmt) != GIMPLE_ASM)
+  if (infer_nonnull_range (stmt, op))
     {
-      unsigned num_uses, num_loads, num_stores;
-
-      count_uses_and_derefs (op, stmt, &num_uses, &num_loads, &num_stores);
-      if (num_loads + num_stores > 0)
-       {
-         *val_p = build_int_cst (TREE_TYPE (op), 0);
-         *comp_code_p = NE_EXPR;
-         return true;
-       }
+      *val_p = build_int_cst (TREE_TYPE (op), 0);
+      *comp_code_p = NE_EXPR;
+      return true;
     }
 
   return false;