aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg/tree-ssa
diff options
context:
space:
mode:
authorDiego Novillo <dnovillo@gcc.gnu.org>2005-06-01 22:57:15 -0400
committerDiego Novillo <dnovillo@gcc.gnu.org>2005-06-01 22:57:15 -0400
commit227858d1e9bcc3c9c6f3a8f6ea1ef7ba43dec2ac (patch)
treeae1c65c21b373e1f2c501ae1c46755f0fb072bda /gcc/testsuite/gcc.dg/tree-ssa
parent292a398fb78ca6012b17481992ffa220a62d2b96 (diff)
downloadgcc-227858d1e9bcc3c9c6f3a8f6ea1ef7ba43dec2ac.zip
gcc-227858d1e9bcc3c9c6f3a8f6ea1ef7ba43dec2ac.tar.gz
gcc-227858d1e9bcc3c9c6f3a8f6ea1ef7ba43dec2ac.tar.bz2
[multiple changes]
2005-06-01 Diego Novillo <dnovillo@redhat.com> PR 14341, PR 21332, PR 20701, PR 21029, PR 21086, PR 21090 PR 21289, PR 21348, PR 21367, PR 21368, PR 21458. * fold-const.c (invert_tree_comparison): Make extern. * tree-flow.h (enum value_range_type): Move to tree-ssa-propagate. (struct value_range_def): Limewise. (get_value_range): Remove. (dump_value_range): Remove. (dump_all_value_ranges): Remove. (debug_all_value_ranges): Remove. (vrp_evaluate_conditional): Declare. * tree-ssa-propagate.c (struct prop_stats_d): Add field num_pred_folded. (substitute_and_fold): Add argument use_ranges_p. Update all callers. If use_ranges_p is true, call fold_predicate_in to fold predicates using range information. Ignore ASSERT_EXPRs. Change debugging output to only show statements that have been folded. (replace_phi_args_in): Move debugging output code from substitute and fold. (fold_predicate_in): New local function. * tree-ssa-propagate.h (enum value_range_type): Move from tree-flow.h. (struct value_range_d): Likewise. Add field 'equiv'. (value_range_t): Rename from value_range. * tree-vrp.c (found_in_subgraph): Rename from found. (get_opposite_operand): Remove. (struct assert_locus_d): Declare. (assert_locus_t): Declare. (need_assert_for): Declare. (asserts_for): Declare. (blocks_visited): Declare. (vr_value): Declare. (set_value_range): Add argument 'equiv'. Don't drop to VARYING ranges that cover all values in the type. Make deep copy of equivalence set 'equiv'. (copy_value_range): New local function. (set_value_range_to_undefined): New local function. (compare_values): Return -2 if either value has overflowed. (range_includes_zero_p): New local function. (extract_range_from_assert): Flip the predicate code if the name being asserted is on the RHS of the predicate. Avoid creating unnecessary symbolic ranges if the comparison includes another name with a known numeric range. Update the equivalnce set of the new range when asserting EQ_EXPR predicates. (extract_range_from_ssa_name): Update the equivalence set of the new range with VAR. (extract_range_from_binary_expr): Also handle TRUTH_*_EXPR. If -fwrapv is used, set the resulting range to VARYING if the operation overflows. Otherwise, use TYPE_MIN_VALUE and TYPE_MAX_VALUE to represent -INF and +INF. Fix handling of *_DIV_EXPR. (extract_range_from_unary_expr): Handle MINUS_EXPR and ABS_EXPR properly by switching the range around if necessary. (extract_range_from_comparison): New local function. (extract_range_from_expr): Call it. (adjust_range_with_scev): Do not adjust the range if using wrapping arithmetic (-fwrapv). (dump_value_range): Also show equivalence set. Show -INF and +INF for TYPE_MIN_VALUE and TYPE_MAX_VALUE. (build_assert_expr_for): Also build ASSERT_EXPR for EQ_EXPR. (infer_value_range): Change return value to bool. Add arguments 'comp_code_p' and 'val_p'. Do not attempt to infer ranges from statements that may throw. Store the comparison code in comp_code_p. Store the other operand to be used in the predicate in val_p. (dump_asserts_for): New. (debug_asserts_for): New. (dump_all_asserts): New. (debug_all_asserts): New. (register_new_assert_for): New. (register_edge_assert_for): New. (find_conditional_asserts): New. (find_assert_locations): New. (process_assert_insertions_for): New. (process_assert_insertions): New. (insert_range_assertions): Initialize found_in_subgraph, blocks_visited, need_assert_for and asserts_for. Call find_assert_locations and process_assert_insertions. (remove_range_assertions): Add more documentation. (vrp_initialize): Change return type to void. Do not try to guess if running VRP is worth it. (compare_name_with_value): New. (compare_names): New. (vrp_evaluate_conditional): Add argument 'use_equiv_p'. If use_equiv_p is true, call compare_names and compare_name_with_value to compare all the ranges for every name in the equivalence set of the predicate operands. Update all callers. (vrp_meet): Try harder not to derive a VARYING range. If two values meet, the resulting equivalence set is the intersection of the two equivalence sets. (vrp_visit_phi_node): Call copy_value_range to get the current range information of the LHS. (vrp_finalize): Create a value vector representing all the names that ended up with exactly one value in their range. Call substitute_and_fold. (execute_vrp): Document equivalence sets in ranges. * tree.h (SSA_NAME_VALUE_RANGE): Remove. (struct tree_ssa_name): Remove field value_range. (invert_tree_comparison): Declare. testsuite/ChangeLog 2005-06-01 Diego Novillo <dnovillo@redhat.com> PR 14341, PR 21332, PR 20701, PR 21086, PR 21090 PR 21289, PR 21348, PR 21367, PR 21368, PR 21458. * gcc.dg/tree-ssa/pr14341.c: New test. * gcc.dg/tree-ssa/pr14841.c: New test. * gcc.dg/tree-ssa/pr20701.c: New test. * gcc.dg/tree-ssa/pr21086.c: New test. * gcc.dg/tree-ssa/pr21090.c: New test. * gcc.dg/tree-ssa/pr21332.c: New test. * gcc.dg/tree-ssa/pr21458.c: New test. * gcc.dg/tree-ssa/pr21658.c: New test. * gcc.dg/tree-ssa/vrp01.c: New test. * gcc.dg/tree-ssa/vrp02.c: New test. * gcc.dg/tree-ssa/vrp03.c: New test. * gcc.dg/tree-ssa/vrp04.c: New test. * gcc.dg/tree-ssa/vrp05.c: New test. * gcc.dg/tree-ssa/vrp06.c: New test. * gcc.dg/tree-ssa/vrp07.c: New test. * gcc.dg/tree-ssa/vrp08.c: New test. * gcc.dg/tree-ssa/vrp09.c: New test. * gcc.dg/tree-ssa/vrp10.c: New test. * gcc.dg/tree-ssa/vrp11.c: New test. * gcc.dg/tree-ssa/vrp12.c: New test. * gcc.dg/tree-ssa/vrp13.c: New test. 2005-06-01 Alexandre Oliva <aoliva@redhat.com> PR 21029 * gcc.dg/tree-ssa/pr21029.c: New test. From-SVN: r100478
Diffstat (limited to 'gcc/testsuite/gcc.dg/tree-ssa')
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr14341.c16
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr14841.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr20701.c30
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr21029.c118
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr21086.c19
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr21090.c23
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr21332.c28
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr21458.c20
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr21658.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp01.c28
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp02.c24
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp03.c35
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp04.c13
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp05.c20
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp06.c31
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp07.c36
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp08.c23
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp09.c31
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp10.c25
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp11.c20
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp12.c23
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp13.c139
22 files changed, 704 insertions, 2 deletions
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr14341.c b/gcc/testsuite/gcc.dg/tree-ssa/pr14341.c
new file mode 100644
index 0000000..07f51b7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr14341.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp" } */
+
+void fn_call (int);
+int h(int, int);
+void t()
+{
+ int i;
+ int x;
+ for( i = 0; i < 100000000; i++ ){
+ fn_call (i < 100000000);
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "fn_call \\(1\\)" 1 "vrp" } } */
+/* { dg-final { cleanup-tree-dump "vrp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr14841.c b/gcc/testsuite/gcc.dg/tree-ssa/pr14841.c
index 4acc6ce..4f9c759 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr14841.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr14841.c
@@ -25,5 +25,5 @@ foo (void)
link_error ();
}
-/* { dg-final { scan-tree-dump-times "with if \\(0\\)" 1 "store_ccp"} } */
+/* { dg-final { scan-tree-dump-times "Folded statement: if " 1 "store_ccp"} } */
/* { dg-final { cleanup-tree-dump "store_ccp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr20701.c b/gcc/testsuite/gcc.dg/tree-ssa/pr20701.c
new file mode 100644
index 0000000..a02c317
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr20701.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp" } */
+
+typedef struct {
+ int code;
+} *rtx;
+
+int
+can_combine_p (rtx insn, rtx elt)
+{
+ rtx set;
+
+ set = 0;
+ if (insn->code == 3)
+ set = insn;
+ else
+ {
+ set = elt;
+ if (set == 0)
+ return 0;
+ }
+
+ if (set == 0)
+ return 1;
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "Folding predicate.*to 0" 1 "vrp" } } */
+/* { dg-final { cleanup-tree-dump "vrp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21029.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21029.c
new file mode 100644
index 0000000..de2595a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21029.c
@@ -0,0 +1,118 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fwrapv" } */
+
+/* PR tree-optimization/21029
+
+ f() used to get optimized to an infinite loop by tree-vrp, because
+ j is assumed to be non-negative. Even though the conversion from
+ unsigned to signed has unspecified results if the expression value
+ is not representable in the signed type, the compiler itself (e.g.,
+ the Ada front end) depends on wrap-around behavior. */
+
+unsigned int f(void) {
+ unsigned char i = 123;
+ signed char j;
+
+ do
+ if ((j = (signed char) i) < 0)
+ break;
+ else
+ i++;
+ while (1);
+
+ return i;
+}
+
+/* Now let's torture it a bit further. Narrowing conversions need
+ similar treatment. */
+
+unsigned int f1 (void) {
+ unsigned short i = 123;
+ signed char j;
+
+ do
+ if ((j = (signed char) i) < 0)
+ break;
+ else
+ i++;
+ while (1);
+
+ return i;
+}
+
+/* And so do widening conversions. */
+
+unsigned int f2 (void) {
+ unsigned char i = 123;
+ signed short j;
+
+ do
+ if ((j = (signed short) (signed char) i) < 0)
+ break;
+ else
+ i++;
+ while (1);
+
+ return i;
+}
+
+/* Check same-sign truncations with an increment that turns into
+ decrements. */
+
+unsigned int f3 (void) {
+ signed short i = 5;
+ signed char j;
+
+ do
+ if ((j = (signed char) i) < 0)
+ break;
+ else
+ i += 255;
+ while (1);
+
+ return i;
+}
+
+/* Check that the truncation above doesn't confuse the result of the
+ test after a widening conversion. */
+
+unsigned int f4 (void) {
+ signed short i = -123;
+ signed int j;
+
+ do
+ if ((j = (signed int) (signed char) i) > 0)
+ break;
+ else
+ i += 255;
+ while (1);
+
+ return i;
+}
+
+/* Even if we omit the widening truncation, the narrowing truncation
+ is implementation-defined. */
+
+unsigned int f5 (void) {
+ signed long i = -123;
+ signed char j;
+
+ do
+ if ((j = (signed char) i) > 0)
+ break;
+ else
+ i += 255;
+ while (1);
+
+ return i;
+}
+
+int main (void) {
+ f ();
+ f1 ();
+ f2 ();
+ f3 ();
+ f4 ();
+ f5 ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21086.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21086.c
new file mode 100644
index 0000000..547d1c8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21086.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp" } */
+
+int
+foo (int *p)
+{
+ int a = *p;
+ int b = p != 0;
+
+ *p = b;
+
+ if (b)
+ return a;
+ else
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "Folding predicate " 2 "vrp" } } */
+/* { dg-final { cleanup-tree-dump "vrp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21090.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21090.c
new file mode 100644
index 0000000..e6b3c88
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21090.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp" } */
+
+int g, h;
+
+int
+foo (int a)
+{
+ int *p;
+
+ if (a)
+ p = &g;
+ else
+ p = &h;
+
+ if (p != 0)
+ return 1;
+ else
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "Folding predicate.*to 1" 1 "vrp" } } */
+/* { dg-final { cleanup-tree-dump "vrp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21332.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21332.c
new file mode 100644
index 0000000..8dd75cc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21332.c
@@ -0,0 +1,28 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+// this testcase fails also on amd64:
+
+extern void abort (void);
+
+int f ()
+{
+ return -1;
+}
+
+int main ()
+{
+ int b, c, i;
+
+ b = 0;
+ c = f ();
+ if (c <= 0)
+ {
+ c = -c;
+ for (i = 0; i < c; i++)
+ b = 1;
+ if (!b)
+ abort ();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21458.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21458.c
new file mode 100644
index 0000000..0222e7a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21458.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp" } */
+
+extern void g (void);
+extern void bar (int);
+
+int
+foo (int a)
+{
+ int i;
+
+ for (i = 1; i < 100; i++)
+ {
+ if (i)
+ g ();
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "Folding predicate.*to 1" 1 "vrp" } } */
+/* { dg-final { cleanup-tree-dump "vrp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21658.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21658.c
index 993b493..2fa45b4 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr21658.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21658.c
@@ -17,5 +17,5 @@ f (void)
link_error ();
}
-/* { dg-final { scan-tree-dump-times "with if \\(0\\)" 1 "ccp"} } */
+/* { dg-final { scan-tree-dump-times "Folded statement: if " 1 "ccp"} } */
/* { dg-final { cleanup-tree-dump "ccp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp01.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp01.c
new file mode 100644
index 0000000..1edda29
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp01.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp" } */
+
+foo (int *p, int i)
+{
+ int x;
+
+ if (i > 10)
+ {
+ if (p)
+ {
+ x = *p;
+ p = 0;
+ }
+ }
+ else
+ p = 0;
+
+ /* This should be folded to if (1), but only if we insert an
+ assertion on the ELSE edge from the inner 'if (p)'. */
+ if (p == 0)
+ return x + 1;
+
+ return i;
+}
+
+/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 1" 1 "vrp" } } */
+/* { dg-final { cleanup-tree-dump "vrp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp02.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp02.c
new file mode 100644
index 0000000..61cb308
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp02.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp" } */
+
+struct A
+{
+ int a;
+ int b;
+};
+
+foo (struct A *p, struct A *q)
+{
+ int x = p->a;
+ if (p == q)
+ return q->a;
+
+ /* We should fold this to 'if (1)' but the assertion for 'p == q'
+ was overwriting the assertion 'p != 0' from the first dereference
+ of 'p'. */
+ if (p)
+ return x + p->b;
+}
+
+/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 1" 1 "vrp" } } */
+/* { dg-final { cleanup-tree-dump "vrp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp03.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp03.c
new file mode 100644
index 0000000..20fcb91
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp03.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp" } */
+
+struct A
+{
+ int a;
+ int b;
+};
+
+foo (struct A *p, struct A *q)
+{
+ int *r = 0;
+
+ if (p)
+ {
+ if (p == q)
+ {
+ /* This should be folded to 'if (1)' because q is [p, p]
+ and p is ~[0, 0]. */
+ if (q)
+ r = &q->a;
+
+ /* This should be folded to 'if (1)' because q should be
+ ~[0, 0] and thus &q->a should be ~[0, 0]. */
+ if (r)
+ return 5;
+ }
+ }
+
+ return q->a;
+}
+
+/* { dg-final { scan-tree-dump-times "Folding predicate q_.*to 1" 1 "vrp" } } */
+/* { dg-final { scan-tree-dump-times "Folding predicate r_.*to 1" 1 "vrp" } } */
+/* { dg-final { cleanup-tree-dump "vrp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp04.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp04.c
new file mode 100644
index 0000000..2632248
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp04.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp" } */
+
+foo (int a, int b)
+{
+ if (a == b)
+ /* This should be folded to if (1) */
+ if (a == b)
+ return a + b;
+}
+
+/* { dg-final { scan-tree-dump-times "Folding predicate a_.*to 1" 1 "vrp" } } */
+/* { dg-final { cleanup-tree-dump "vrp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp05.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp05.c
new file mode 100644
index 0000000..767d3e1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp05.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp" } */
+
+foo (int k, int j)
+{
+ if (k >= 10)
+ {
+ if (j > k)
+ {
+ /* We should fold this to if (1). */
+ if (j > 0)
+ return j;
+ }
+ }
+
+ return j;
+}
+
+/* { dg-final { scan-tree-dump-times "Folding predicate j_.*to 1" 1 "vrp" } } */
+/* { dg-final { cleanup-tree-dump "vrp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp06.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp06.c
new file mode 100644
index 0000000..a92db95
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp06.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp" } */
+
+foo (int i, int j, int a)
+{
+ if (i >= 10)
+ if (i <= 30)
+ if (i == j)
+ {
+ a--;
+
+ /* This should fold to 'if (0)'. */
+ if (i < 0)
+ i = baz ();
+
+ /* This should fold to 'if (1)'. */
+ if (j > 0)
+ a--;
+
+ /* This should fold to 'if (0)'. */
+ if (i != j)
+ return 0;
+ }
+
+ return i + a + j;
+}
+
+/* { dg-final { scan-tree-dump-times "Folding predicate i_.*to 0" 1 "vrp" } } */
+/* { dg-final { scan-tree-dump-times "Folding predicate j_.*to 1" 1 "vrp" } } */
+/* { dg-final { scan-tree-dump-times "Folding predicate i_.*to 0" 1 "vrp" } } */
+/* { dg-final { cleanup-tree-dump "vrp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp07.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp07.c
new file mode 100644
index 0000000..49df596
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp07.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp-details" } */
+
+foo (int i, int *p)
+{
+ int j;
+
+ if (i > 10)
+ {
+ if (p)
+ {
+ j = *p;
+ /* This should be folded to if (1) because of the parent 'if
+ (p)'. But the dereference of p above does not need an
+ assertion. */
+ if (p)
+ return j + 1;
+ }
+ }
+ else
+ {
+ j = *p - 3;
+ /* This should be folded to if (0), because p has just been
+ dereferenced. But we were not inserting enough ASSERT_EXPRs
+ to figure it out. */
+ if (!p)
+ return j - 4;
+ }
+
+ return i;
+}
+
+/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 1" 1 "vrp" } } */
+/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 0" 1 "vrp" } } */
+/* { dg-final { scan-tree-dump-times "PREDICATE: p_\[0-9\] ne_expr 0B" 2 "vrp" } } */
+/* { dg-final { cleanup-tree-dump "vrp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp08.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp08.c
new file mode 100644
index 0000000..5bf43fe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp08.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-tree-fre -fdump-tree-vrp-details" } */
+
+/* Compile with -fno-tree-fre -O2 to prevent CSEing *p. */
+foo (int a, int *p)
+{
+ int x = *p + 2;
+ int y = *p - 1;
+ int z = *p + 9;
+
+ /* This should be folded to if (1), but only one ASSERT_EXPR should
+ be inserted. */
+ if (p)
+ a = x + y + z;
+ else
+ a = x - y;
+
+ return a;
+}
+
+/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 1" 1 "vrp" } } */
+/* { dg-final { scan-tree-dump-times "PREDICATE: p_. ne_expr 0" 1 "vrp" } } */
+/* { dg-final { cleanup-tree-dump "vrp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp09.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp09.c
new file mode 100644
index 0000000..6a2c983
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp09.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp" } */
+
+foo (int *p)
+{
+ int x = baz ();
+
+ if (p == 0)
+ goto L78;
+ else
+ {
+ x = *p;
+ /* This should be folded to if (1). */
+ if (p)
+ x = x + 1;
+L78:
+ /* This should not be folded to if (1). */
+ if (p)
+ {
+ x = baz (*p);
+ /* This should be folded to if (1). */
+ if (p)
+ return x + 3;
+ }
+
+ return x - 3;
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "Folding predicate p_.. != 0B to 1" 2 "vrp" } } */
+/* { dg-final { cleanup-tree-dump "vrp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp10.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp10.c
new file mode 100644
index 0000000..5a74584
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp10.c
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+extern void abort (void);
+
+foo (int k, int j)
+{
+ if (k >= 10)
+ {
+ if (j > k)
+ {
+ /* We should fold this to if (0). */
+ if (j < 10)
+ abort ();
+ }
+ }
+
+ return j;
+}
+
+main()
+{
+ foo (10, 3);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp11.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp11.c
new file mode 100644
index 0000000..b9e5fca
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp11.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp" } */
+
+foo (int k, int j, int z)
+{
+ if (k > z)
+ {
+ if (j > k)
+ {
+ /* We should fold this to if (1). */
+ if (j > z)
+ return j;
+ }
+ }
+
+ return j;
+}
+
+/* { dg-final { scan-tree-dump-times "Folding predicate.*to 1" 1 "vrp" } } */
+/* { dg-final { cleanup-tree-dump "vrp" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp12.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp12.c
new file mode 100644
index 0000000..1714a56
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp12.c
@@ -0,0 +1,23 @@
+/* { dg-do link } */
+/* { dg-options -O2 } */
+
+foo (int i)
+{
+ int x;
+
+ x = i;
+ if (i < -10)
+ {
+ x = __builtin_abs (i);
+ /* VRP was incorrectly folding this to if (1). */
+ if (x < 0)
+ link_error ();
+ }
+
+ return x;
+}
+
+main()
+{
+ foo (-30);
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp13.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp13.c
new file mode 100644
index 0000000..cfc55d8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp13.c
@@ -0,0 +1,139 @@
+/* { dg-do run } */
+/* { dg-options -O2 } */
+
+extern void abort (void);
+
+foo (int i, int j)
+{
+ int k;
+
+ /* [-INF, -1] / [1, +INF] should not give [-1, -1]. */
+ if (i <= -1)
+ if (j >= 1)
+ {
+ k = i / j;
+ if (k == -1)
+ abort ();
+
+ return k;
+ }
+
+ /* [-20, -10] / [2, 10] should give [-10, -1]. */
+ if (i >= -20)
+ if (i <= -10)
+ if (j >= 2)
+ if (j <= 10)
+ {
+ k = i / j;
+ if (k < -10)
+ link_error ();
+ if (k > -1)
+ link_error ();
+
+ return k;
+ }
+
+ /* [-20, -10] / [-10, -2] should give [1, 10]. */
+ if (i >= -20)
+ if (i <= -10)
+ if (j >= -10)
+ if (j <= -2)
+ {
+ k = i / j;
+ if (k < 1)
+ link_error ();
+ if (k > 10)
+ link_error ();
+
+ return k;
+ }
+
+ /* [-20, 10] / [2, 10] should give [-10, 5]. */
+ if (i >= -20)
+ if (i <= 10)
+ if (j >= 2)
+ if (j <= 10)
+ {
+ k = i / j;
+ if (k < -10)
+ link_error ();
+ if (k > 5)
+ link_error ();
+
+ return k;
+ }
+
+ /* [-20, 10] / [-10, -2] should give [-5, 10]. */
+ if (i >= -20)
+ if (i <= 10)
+ if (j >= -10)
+ if (j <= -2)
+ {
+ k = i / j;
+ if (k < -5)
+ link_error ();
+ if (k > 10)
+ link_error ();
+
+ return k;
+ }
+
+ /* [10, 20] / [2, 10] should give [1, 10]. */
+ if (i >= 10)
+ if (i <= 20)
+ if (j >= 2)
+ if (j <= 10)
+ {
+ k = i / j;
+ if (k < 1)
+ link_error ();
+ if (k > 10)
+ link_error ();
+
+ return k;
+ }
+
+ /* [10, 20] / [-10, -2] should give [-10, -1]. */
+ if (i >= 10)
+ if (i <= 20)
+ if (j >= -10)
+ if (j <= -2)
+ {
+ k = i / j;
+ if (k > -1)
+ link_error ();
+ if (k < -10)
+ link_error ();
+
+ return k;
+ }
+
+ abort ();
+}
+
+
+main()
+{
+ if (foo (-10, 5) != -2)
+ abort ();
+
+ if (foo (-16, 4) != -4)
+ abort ();
+
+ if (foo (-15, -5) != 3)
+ abort ();
+
+ if (foo (8, 2) != 4)
+ abort ();
+
+ if (foo (10, -2) != -5)
+ abort ();
+
+ if (foo (20, 5) != 4)
+ abort ();
+
+ if (foo (15, -3) != -5)
+ abort ();
+
+ return 0;
+}