From 0e6a0e48eb5ead024d12453cb811bdf0ef5c3377 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 8 Oct 2013 12:39:49 +0200 Subject: re PR tree-optimization/58480 (Use attribute((nonnull)) to optimize callers) 2013-10-08 Marc Glisse 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 | 6 +++ gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gcc.dg/tree-ssa/pr58480.c | 19 +++++++++ gcc/tree-vrp.c | 70 ++++++++++++++++++++++++++------- 4 files changed, 85 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr58480.c (limited to 'gcc') 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 + + PR tree-optimization/58480 + * tree-vrp.c (infer_nonnull_range): New function. + (infer_value_range): Call infer_nonnull_range. + 2013-10-08 Dehao Chen 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 + + PR tree-optimization/58480 + * gcc.dg/tree-ssa/pr58480.c: New file. + 2013-10-07 Bill Schmidt * 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; -- cgit v1.1