aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMarc Glisse <marc.glisse@inria.fr>2013-10-08 12:39:49 +0200
committerMarc Glisse <glisse@gcc.gnu.org>2013-10-08 10:39:49 +0000
commit0e6a0e48eb5ead024d12453cb811bdf0ef5c3377 (patch)
treed6b986b5b052a0040274877460393e4e53588b02 /gcc
parentef6179d186ee9a2ebe034d328a17764e703273ca (diff)
downloadgcc-0e6a0e48eb5ead024d12453cb811bdf0ef5c3377.zip
gcc-0e6a0e48eb5ead024d12453cb811bdf0ef5c3377.tar.gz
gcc-0e6a0e48eb5ead024d12453cb811bdf0ef5c3377.tar.bz2
re PR tree-optimization/58480 (Use attribute((nonnull)) to optimize callers)
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr58480.c19
-rw-r--r--gcc/tree-vrp.c70
4 files changed, 85 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 80343b9..dc1bc7e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 60242b6..86fb8ea 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..a42edf9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr58480.c
@@ -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" } } */
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index cf0f1b1..156a58f 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -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;