This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] tree-vrp.c: Teach VRP that &p->a is nonzero if p is knownto be nonzero.
- From: Kazu Hirata <kazu at cs dot umass dot edu>
- To: gcc-patches at gcc dot gnu dot org
- Cc: dnovillo at redhat dot com, pinskia at physics dot uc dot edu
- Date: Sun, 01 May 2005 19:08:30 -0400 (EDT)
- Subject: [patch] tree-vrp.c: Teach VRP that &p->a is nonzero if p is knownto be nonzero.
Hi,
Attached is a patch to teach VRP that &p->a is nonzero if p is known
to be nonzero.
While I was playing with FOR_EACH_EDGE, Andrew Pinski told me that VRP
did not know that &p->a is nonnull when p is nonnull.
This patch teaches VRP to pick up nonzeroness while visiting a
statement whose RHS is of the form &p->a.
One question I have is whether it is safe to ignore the wrapping that
might happen to a pointer. If I have the following on a 32-bit system
struct s { int a; int b; } *p;
and p is 0xfffffffc, then &p->b could be 0. Should I worry about such
a case? This case is very pathological, but people throw all kinds of
weird stuff at the compiler anyway. :-) If I have to worry about
wrapping, then I suppose we can still do the optimization for &p->a,
which has offset 0.
Testing on cc1-i files shows that VRP folds 230 predicates with this
patch. Without this patch, VRP folds 215 predicates. With a TCB-like
pass ordering, we should be able to fold more, but I did not try that
this time.
Note that this patch has no reference to
flag_delete_null_pointer_checks. The flag is about dereferencing a
pointer. The proposed optimization has nothing to do with a
dereference although 'p' may be found to be nonnull by a dereference
that happens earlier.
Tested on i686-pc-linux-gnu. OK to apply?
Kazu Hirata
2005-05-01 Kazu Hirata <kazu@cs.umass.edu>
PR tree-optimization/21294
* tree-vrp.c (vrp_expr_computes_nonzero): New.
(extract_range_from_expr): Call vrp_expr_computes_nonzero.
2005-05-01 Kazu Hirata <kazu@cs.umass.edu>
PR tree-optimization/21294
* gcc.dg/tree-ssa/pr21294.c: New.
Index: tree-vrp.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-vrp.c,v
retrieving revision 2.14
diff -u -d -p -r2.14 tree-vrp.c
--- tree-vrp.c 29 Apr 2005 16:22:52 -0000 2.14
+++ tree-vrp.c 1 May 2005 19:15:43 -0000
@@ -717,6 +717,35 @@ extract_range_from_binary_expr (value_ra
}
+/* Like expr_computes_nonzero, but this function uses value ranges
+ obtained so far. */
+
+static bool
+vrp_expr_computes_nonzero (tree expr)
+{
+ if (expr_computes_nonzero (expr))
+ return true;
+
+ /* If we have an expression of the form &X->a, then the expression
+ is nonnull if X is nonnull. */
+ if (TREE_CODE (expr) == ADDR_EXPR)
+ {
+ tree base = get_base_address (TREE_OPERAND (expr, 0));
+
+ if (base != NULL_TREE
+ && TREE_CODE (base) == INDIRECT_REF
+ && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
+ {
+ value_range *vr = get_value_range (TREE_OPERAND (base, 0));
+ if (range_is_nonnull (vr))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
/* Extract range information from a unary expression EXPR based on
the range of its operand and the expression code. */
@@ -833,7 +862,7 @@ extract_range_from_expr (value_range *vr
extract_range_from_binary_expr (vr, expr);
else if (TREE_CODE_CLASS (code) == tcc_unary)
extract_range_from_unary_expr (vr, expr);
- else if (expr_computes_nonzero (expr))
+ else if (vrp_expr_computes_nonzero (expr))
set_value_range_to_nonnull (vr, TREE_TYPE (expr));
else if (TREE_CODE (expr) == INTEGER_CST)
set_value_range (vr, VR_RANGE, expr, expr);
--- /dev/null 2005-04-29 10:25:17.000000000 -0400
+++ testsuite/gcc.dg/tree-ssa/pr21294.c 2005-05-01 15:13:50.000000000 -0400
@@ -0,0 +1,23 @@
+/* PR tree-optimization/21294
+ VRP did not notice that an address of the form &p->i is nonnull
+ when p is known to be nonnull. In this testcase, noticing that
+ allows us to eliminate the second "if" statement. */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-vrp-details" } */
+
+struct f {
+ int i;
+};
+
+int
+foo (struct f *p)
+{
+ if (p != 0)
+ if (&p->i != 0)
+ return 123;
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "Folding predicate" 1 "vrp"} } */
+/* { dg-final { cleanup-tree-dump "vrp" } } */