diff options
author | Diego Novillo <dnovillo@gcc.gnu.org> | 2005-06-01 22:57:15 -0400 |
---|---|---|
committer | Diego Novillo <dnovillo@gcc.gnu.org> | 2005-06-01 22:57:15 -0400 |
commit | 227858d1e9bcc3c9c6f3a8f6ea1ef7ba43dec2ac (patch) | |
tree | ae1c65c21b373e1f2c501ae1c46755f0fb072bda /gcc/testsuite/gcc.dg/tree-ssa | |
parent | 292a398fb78ca6012b17481992ffa220a62d2b96 (diff) | |
download | gcc-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')
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; +} |