diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 41df9bbcc1b..a9f24216368 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2017-01-27 Richard Biener + + PR tree-optimization/71433 + * tree-vrp.c (register_new_assert_for): Revert earlier changes. + (compare_assert_loc): New function. + (process_assert_insertions): Sort and optimize assert locations + to remove duplicates and push down identical assertions on + edges to their destination block. + 2017-01-27 Richard Biener PR tree-optimization/79244 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 525a7c7f214..2c044f58d9e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-01-27 Richard Biener + + PR tree-optimization/71433 + * gcc.dg/Warray-bounds-21.c: New testcase. + 2017-01-27 Richard Biener PR tree-optimization/79244 diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-21.c b/gcc/testsuite/gcc.dg/Warray-bounds-21.c new file mode 100644 index 00000000000..759944fc00c --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-21.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -Warray-bounds" } */ + +int t[1]; +int a (void); +int fct (int r, long e, int neg) +{ + int d = 0; + if (r == 4) + r = neg ? 3 : 2; + if (__builtin_expect(e < -52, 0)) + d = r == 0 && a () ? 1 : 2; + else + { + int i, n = 53; + if (e < 0) + n += e; + for (i = 1 ; i < n / 64 + 1 ; i++) + d = t[i]; /* { dg-bogus "array bounds" } */ + } + return d; +} diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index e023244577c..5c43e35d89c 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -5032,18 +5032,6 @@ register_new_assert_for (tree name, tree expr, loc->si = si; return; } - /* If we have the same assertion on all incoming edges of a BB - instead insert it at the beginning of it. */ - if (e && loc->e - && e != loc->e - && dest_bb == loc->e->dest - && EDGE_COUNT (dest_bb->preds) == 2) - { - loc->bb = dest_bb; - loc->e = NULL; - loc->si = gsi_none (); - return; - } } /* Update the last node of the list and move to the next one. */ @@ -6473,6 +6461,41 @@ process_assert_insertions_for (tree name, assert_locus *loc) gcc_unreachable (); } +/* Qsort helper for sorting assert locations. */ + +static int +compare_assert_loc (const void *pa, const void *pb) +{ + assert_locus * const a = *(assert_locus * const *)pa; + assert_locus * const b = *(assert_locus * const *)pb; + if (! a->e && b->e) + return 1; + else if (a->e && ! b->e) + return -1; + + /* Sort after destination index. */ + if (! a->e && ! b->e) + ; + else if (a->e->dest->index > b->e->dest->index) + return 1; + else if (a->e->dest->index < b->e->dest->index) + return -1; + + /* Sort after comp_code. */ + if (a->comp_code > b->comp_code) + return 1; + else if (a->comp_code < b->comp_code) + return -1; + + /* Break the tie using hashing and source/bb index. */ + hashval_t ha = iterative_hash_expr (a->expr, iterative_hash_expr (a->val, 0)); + hashval_t hb = iterative_hash_expr (b->expr, iterative_hash_expr (b->val, 0)); + if (ha == hb) + return (a->e && b->e + ? a->e->src->index - b->e->src->index + : a->bb->index - b->bb->index); + return ha - hb; +} /* Process all the insertions registered for every name N_i registered in NEED_ASSERT_FOR. The list of assertions to be inserted are @@ -6494,13 +6517,66 @@ process_assert_insertions (void) assert_locus *loc = asserts_for[i]; gcc_assert (loc); - while (loc) + auto_vec asserts; + for (; loc; loc = loc->next) + asserts.safe_push (loc); + asserts.qsort (compare_assert_loc); + + /* Push down common asserts to successors and remove redundant ones. */ + unsigned ecnt = 0; + assert_locus *common = NULL; + unsigned commonj = 0; + for (unsigned j = 0; j < asserts.length (); ++j) { - assert_locus *next = loc->next; + loc = asserts[j]; + if (! loc->e) + common = NULL; + else if (! common + || loc->e->dest != common->e->dest + || loc->comp_code != common->comp_code + || ! operand_equal_p (loc->val, common->val, 0) + || ! operand_equal_p (loc->expr, common->expr, 0)) + { + commonj = j; + common = loc; + ecnt = 1; + } + else if (loc->e == asserts[j-1]->e) + { + /* Remove duplicate asserts. */ + free (asserts[j-1]); + asserts[j-1] = NULL; + } + else + { + ecnt++; + if (EDGE_COUNT (common->e->dest->preds) == ecnt) + { + /* We have the same assertion on all incoming edges of a BB. + Insert it at the beginning of that block. */ + loc->bb = loc->e->dest; + loc->e = NULL; + loc->si = gsi_none (); + common = NULL; + /* Clear asserts commoned. */ + for (; commonj != j; ++commonj) + if (asserts[commonj]) + { + free (asserts[commonj]); + asserts[commonj] = NULL; + } + } + } + } + + for (unsigned j = 0; j < asserts.length (); ++j) + { + loc = asserts[j]; + if (! loc) + continue; update_edges_p |= process_assert_insertions_for (ssa_name (i), loc); - free (loc); - loc = next; num_asserts++; + free (loc); } }