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
This commit is contained in:
parent
38f50ab65a
commit
b002f3b9e1
4 changed files with 128 additions and 16 deletions
|
@ -1,3 +1,12 @@
|
|||
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.
|
||||
|
||||
2017-01-27 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/79244
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2017-01-27 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/71433
|
||||
* gcc.dg/Warray-bounds-21.c: New testcase.
|
||||
|
||||
2017-01-27 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/79244
|
||||
|
|
22
gcc/testsuite/gcc.dg/Warray-bounds-21.c
Normal file
22
gcc/testsuite/gcc.dg/Warray-bounds-21.c
Normal file
|
@ -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;
|
||||
}
|
108
gcc/tree-vrp.c
108
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue