diff options
author | Richard Biener <rguenther@suse.de> | 2017-01-27 12:30:43 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2017-01-27 12:30:43 +0000 |
commit | b002f3b9e12252f53332575d01cc8765d6fbf59f (patch) | |
tree | 0990a8ec2839c1b7a30c2eb4a0a97dbb5d9c3a8e /gcc/tree-vrp.c | |
parent | 38f50ab65ae67aa9896ca7a18a80d77b4648a0b0 (diff) | |
download | gcc-b002f3b9e12252f53332575d01cc8765d6fbf59f.zip gcc-b002f3b9e12252f53332575d01cc8765d6fbf59f.tar.gz gcc-b002f3b9e12252f53332575d01cc8765d6fbf59f.tar.bz2 |
re PR tree-optimization/71433 (-Warray-bounds false positive with -O2)
2017-01-27 Richard Biener <rguenther@suse.de>
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.
* gcc.dg/Warray-bounds-21.c: New testcase.
From-SVN: r244974
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r-- | gcc/tree-vrp.c | 108 |
1 files changed, 92 insertions, 16 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index e023244..5c43e35 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<assert_locus *, 16> 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) + { + 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) { - assert_locus *next = loc->next; + 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); } } |