This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Optimize callers using nonnull attribute


Hello,

this patch asserts that when we call a function with the nonnull attribute, the corresponding argument is not zero, just like when we dereference a pointer. Everything is under a check for flag_delete_null_pointer_checks.

Note that this function currently gives up if the statement may throw (because in some languages indirections may throw?), but this could probably be relaxed a bit so my example would still work when compiled with g++, without having to mark f1 and f2 as throw().

Bootstrap (default languages) + testsuite on x86_64-unknown-linux-gnu.

2013-10-08  Marc Glisse  <marc.glisse@inria.fr>

	PR tree-optimization/58480
gcc/
	* tree-vrp.c (infer_value_range): Look for a nonnull attribute.

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

--
Marc Glisse
Index: testsuite/gcc.dg/tree-ssa/pr58480.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/pr58480.c	(revision 0)
+++ testsuite/gcc.dg/tree-ssa/pr58480.c	(working copy)
@@ -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" } } */

Property changes on: testsuite/gcc.dg/tree-ssa/pr58480.c
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision URL
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: tree-vrp.c
===================================================================
--- tree-vrp.c	(revision 203229)
+++ tree-vrp.c	(working copy)
@@ -4493,28 +4493,58 @@ infer_value_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)
     {
       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)
+	goto nonnull;
+
+      if (gimple_code (stmt) == GIMPLE_CALL)
 	{
-	  *val_p = build_int_cst (TREE_TYPE (op), 0);
-	  *comp_code_p = NE_EXPR;
-	  return true;
+	  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)
+		goto nonnull;
+
+	      /* 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)
+		    goto nonnull;
+		}
+	    }
 	}
     }
 
   return false;
+
+nonnull:
+  *val_p = build_int_cst (TREE_TYPE (op), 0);
+  *comp_code_p = NE_EXPR;
+  return true;
 }
 
 
 void dump_asserts_for (FILE *, tree);
 void debug_asserts_for (tree);
 void dump_all_asserts (FILE *);
 void debug_all_asserts (void);
 
 /* Dump all the registered assertions for NAME to FILE.  */
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]