Commit 56b67510 by Xinliang David Li Committed by Xinliang David Li

Fix pr47837

From-SVN: r171008
parent df06baf2
2011-03-15 Xinliang David Li <davidxl@google.com>
PR c/47837
* tree-ssa-uninit.c (pred_chain_length_cmp): New function.
(normalize_preds): New function.
(is_use_properly_guarded): Normalize def predicates.
2011-03-15 Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org>
PR target/46778
......
2011-03-15 Xinliang David Li <davidxl@google.com>
PR c/47837
* gcc.dg/uninit-pred-7_d.c: New test.
* gcc.dg/uninit-pred-8_d.c: New test.
2011-03-15 Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org>
PR target/46788
......
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-Wuninitialized -O2 -mbranch-cost=0" } */
int g;
void bar();
void blah(int);
int foo (int n, int l, int m, int r)
{
int v;
if (n || l)
v = r;
if (m) g++;
else bar();
if ( n && l)
blah(v); /* { dg-bogus "uninitialized" "bogus warning" } */
if ( n )
blah(v); /* { dg-bogus "uninitialized" "bogus warning" } */
if ( l )
blah(v); /* { dg-bogus "uninitialized" "bogus warning" } */
return 0;
}
int foo_2 (int n, int l, int m, int r)
{
int v;
if (n || l)
v = r;
if (m) g++;
else bar();
if ( n && l)
blah(v); /* { dg-bogus "uninitialized" "bogus warning" } */
if ( n )
blah(v); /* { dg-bogus "uninitialized" "bogus warning" } */
if (m || l)
blah (v); /* { dg-warning "uninitialized" "warning" } */
if ( l )
blah(v); /* { dg-bogus "uninitialized" "bogus warning" } */
return 0;
}
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-Wuninitialized -O2 -mbranch-cost=0" } */
int g;
void bar();
void blah(int);
int foo (int n, int l, int m, int r)
{
int v;
if (n || m || r || l)
v = r;
if (m) g++;
else bar();
if ( n || m || r || l)
blah(v); /* { dg-bogus "uninitialized" "bogus warning" } */
if ( n )
blah(v); /* { dg-bogus "uninitialized" "bogus warning" } */
if ( l )
blah(v); /* { dg-bogus "uninitialized" "bogus warning" } */
return 0;
}
int foo_2 (int n, int l, int m, int r)
{
int v;
if (n || m || r )
v = r;
if (m) g++;
else bar();
if ( n || m || r || l)
blah(v); /* { dg-warning "uninitialized" "warning" } */
return 0;
}
......@@ -1605,6 +1605,157 @@ is_superset_of (VEC(use_pred_info_t, heap) **preds1,
return true;
}
/* Comparison function used by qsort. It is used to
sort predicate chains to allow predicate
simplification. */
static int
pred_chain_length_cmp (const void *p1, const void *p2)
{
use_pred_info_t i1, i2;
VEC(use_pred_info_t, heap) * const *chain1
= (VEC(use_pred_info_t, heap) * const *)p1;
VEC(use_pred_info_t, heap) * const *chain2
= (VEC(use_pred_info_t, heap) * const *)p2;
if (VEC_length (use_pred_info_t, *chain1)
!= VEC_length (use_pred_info_t, *chain2))
return (VEC_length (use_pred_info_t, *chain1)
- VEC_length (use_pred_info_t, *chain2));
i1 = VEC_index (use_pred_info_t, *chain1, 0);
i2 = VEC_index (use_pred_info_t, *chain2, 0);
/* Allow predicates with similar prefix come together. */
if (!i1->invert && i2->invert)
return -1;
else if (i1->invert && !i2->invert)
return 1;
return gimple_uid (i1->cond) - gimple_uid (i2->cond);
}
/* x OR (!x AND y) is equivalent to x OR y.
This function normalizes x1 OR (!x1 AND x2) OR (!x1 AND !x2 AND x3)
into x1 OR x2 OR x3. PREDS is the predicate chains, and N is
the number of chains. Returns true if normalization happens. */
static bool
normalize_preds (VEC(use_pred_info_t, heap) **preds, size_t *n)
{
size_t i, j, ll;
VEC(use_pred_info_t, heap) *pred_chain;
VEC(use_pred_info_t, heap) *x = 0;
use_pred_info_t xj = 0, nxj = 0;
if (*n < 2)
return false;
/* First sort the chains in ascending order of lengths. */
qsort (preds, *n, sizeof (void *), pred_chain_length_cmp);
pred_chain = preds[0];
ll = VEC_length (use_pred_info_t, pred_chain);
if (ll != 1)
{
if (ll == 2)
{
use_pred_info_t xx, yy, xx2, nyy;
VEC(use_pred_info_t, heap) *pred_chain2 = preds[1];
if (VEC_length (use_pred_info_t, pred_chain2) != 2)
return false;
/* See if simplification x AND y OR x AND !y is possible. */
xx = VEC_index (use_pred_info_t, pred_chain, 0);
yy = VEC_index (use_pred_info_t, pred_chain, 1);
xx2 = VEC_index (use_pred_info_t, pred_chain2, 0);
nyy = VEC_index (use_pred_info_t, pred_chain2, 1);
if (gimple_cond_lhs (xx->cond) != gimple_cond_lhs (xx2->cond)
|| gimple_cond_rhs (xx->cond) != gimple_cond_rhs (xx2->cond)
|| gimple_cond_code (xx->cond) != gimple_cond_code (xx2->cond)
|| (xx->invert != xx2->invert))
return false;
if (gimple_cond_lhs (yy->cond) != gimple_cond_lhs (nyy->cond)
|| gimple_cond_rhs (yy->cond) != gimple_cond_rhs (nyy->cond)
|| gimple_cond_code (yy->cond) != gimple_cond_code (nyy->cond)
|| (yy->invert == nyy->invert))
return false;
/* Now merge the first two chains. */
free (yy);
free (nyy);
free (xx2);
VEC_free (use_pred_info_t, heap, pred_chain);
VEC_free (use_pred_info_t, heap, pred_chain2);
pred_chain = 0;
VEC_safe_push (use_pred_info_t, heap, pred_chain, xx);
preds[0] = pred_chain;
for (i = 1; i < *n - 1; i++)
preds[i] = preds[i + 1];
preds[*n - 1] = 0;
*n = *n - 1;
}
else
return false;
}
VEC_safe_push (use_pred_info_t, heap, x,
VEC_index (use_pred_info_t, pred_chain, 0));
/* The loop extracts x1, x2, x3, etc from chains
x1 OR (!x1 AND x2) OR (!x1 AND !x2 AND x3) OR ... */
for (i = 1; i < *n; i++)
{
pred_chain = preds[i];
if (VEC_length (use_pred_info_t, pred_chain) != i + 1)
return false;
for (j = 0; j < i; j++)
{
xj = VEC_index (use_pred_info_t, x, j);
nxj = VEC_index (use_pred_info_t, pred_chain, j);
/* Check if nxj is !xj */
if (gimple_cond_lhs (xj->cond) != gimple_cond_lhs (nxj->cond)
|| gimple_cond_rhs (xj->cond) != gimple_cond_rhs (nxj->cond)
|| gimple_cond_code (xj->cond) != gimple_cond_code (nxj->cond)
|| (xj->invert == nxj->invert))
return false;
}
VEC_safe_push (use_pred_info_t, heap, x,
VEC_index (use_pred_info_t, pred_chain, i));
}
/* Now normalize the pred chains using the extraced x1, x2, x3 etc. */
for (j = 0; j < *n; j++)
{
use_pred_info_t t;
xj = VEC_index (use_pred_info_t, x, j);
t = XNEW (struct use_pred_info);
*t = *xj;
VEC_replace (use_pred_info_t, x, j, t);
}
for (i = 0; i < *n; i++)
{
pred_chain = preds[i];
for (j = 0; j < VEC_length (use_pred_info_t, pred_chain); j++)
free (VEC_index (use_pred_info_t, pred_chain, j));
VEC_free (use_pred_info_t, heap, pred_chain);
pred_chain = 0;
/* A new chain. */
VEC_safe_push (use_pred_info_t, heap, pred_chain,
VEC_index (use_pred_info_t, x, i));
preds[i] = pred_chain;
}
return true;
}
/* Computes the predicates that guard the use and checks
if the incoming paths that have empty (or possibly
empty) defintion can be pruned/filtered. The function returns
......@@ -1658,9 +1809,18 @@ is_use_properly_guarded (gimple use_stmt,
if (has_valid_preds)
{
bool normed;
if (dump_file)
dump_predicates (phi, num_def_preds, def_preds,
"Operand defs of phi ");
normed = normalize_preds (def_preds, &num_def_preds);
if (normed && dump_file)
{
fprintf (dump_file, "\nNormalized to\n");
dump_predicates (phi, num_def_preds, def_preds,
"Operand defs of phi ");
}
is_properly_guarded =
is_superset_of (def_preds, num_def_preds,
preds, num_preds);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment