re PR tree-optimization/51042 (endless recursion in phi_translate)
2011-11-10 Richard Guenther <rguenther@suse.de> PR tree-optimization/51042 * tree-ssa-pre.c (phi_translate_1): Avoid recursing on self-referential expressions. Refactor code to avoid duplication. * gcc.dg/torture/pr51042.c: New testcase. From-SVN: r181256
This commit is contained in:
parent
c07a8cb3c9
commit
4da80bfb5d
4 changed files with 84 additions and 68 deletions
|
@ -1,3 +1,9 @@
|
|||
2011-11-10 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/51042
|
||||
* tree-ssa-pre.c (phi_translate_1): Avoid recursing on
|
||||
self-referential expressions. Refactor code to avoid duplication.
|
||||
|
||||
2011-11-10 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/51070
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2011-11-10 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/51042
|
||||
* gcc.dg/torture/pr51042.c: New testcase.
|
||||
|
||||
2011-11-10 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/51070
|
||||
|
|
22
gcc/testsuite/gcc.dg/torture/pr51042.c
Normal file
22
gcc/testsuite/gcc.dg/torture/pr51042.c
Normal file
|
@ -0,0 +1,22 @@
|
|||
/* { dg-do compile } */
|
||||
|
||||
int a, b;
|
||||
|
||||
void
|
||||
foo (int x)
|
||||
{
|
||||
int e[2];
|
||||
int d;
|
||||
while (x)
|
||||
{
|
||||
for (d = 0; d <= 1; d = 1)
|
||||
if (e[a])
|
||||
break;
|
||||
for (b = 0; b <= 0; b = 1)
|
||||
{
|
||||
e[a] = a;
|
||||
if (a)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1527,7 +1527,7 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
|
|||
tree newvuse = vuse;
|
||||
VEC (vn_reference_op_s, heap) *newoperands = NULL;
|
||||
bool changed = false, same_valid = true;
|
||||
unsigned int i, j;
|
||||
unsigned int i, j, n;
|
||||
vn_reference_op_t operand;
|
||||
vn_reference_t newref;
|
||||
|
||||
|
@ -1536,100 +1536,83 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
|
|||
{
|
||||
pre_expr opresult;
|
||||
pre_expr leader;
|
||||
tree oldop0 = operand->op0;
|
||||
tree oldop1 = operand->op1;
|
||||
tree oldop2 = operand->op2;
|
||||
tree op0 = oldop0;
|
||||
tree op1 = oldop1;
|
||||
tree op2 = oldop2;
|
||||
tree op[3];
|
||||
tree type = operand->type;
|
||||
vn_reference_op_s newop = *operand;
|
||||
|
||||
if (op0 && TREE_CODE (op0) == SSA_NAME)
|
||||
op[0] = operand->op0;
|
||||
op[1] = operand->op1;
|
||||
op[2] = operand->op2;
|
||||
for (n = 0; n < 3; ++n)
|
||||
{
|
||||
unsigned int op_val_id = VN_INFO (op0)->value_id;
|
||||
leader = find_leader_in_sets (op_val_id, set1, set2);
|
||||
opresult = phi_translate (leader, set1, set2, pred, phiblock);
|
||||
if (opresult && opresult != leader)
|
||||
unsigned int op_val_id;
|
||||
if (!op[n])
|
||||
continue;
|
||||
if (TREE_CODE (op[n]) != SSA_NAME)
|
||||
{
|
||||
tree name = get_representative_for (opresult);
|
||||
if (!name)
|
||||
/* We can't possibly insert these. */
|
||||
if (n != 0
|
||||
&& !is_gimple_min_invariant (op[n]))
|
||||
break;
|
||||
op0 = name;
|
||||
continue;
|
||||
}
|
||||
else if (!opresult)
|
||||
op_val_id = VN_INFO (op[n])->value_id;
|
||||
leader = find_leader_in_sets (op_val_id, set1, set2);
|
||||
if (!leader)
|
||||
break;
|
||||
/* Make sure we do not recursively translate ourselves
|
||||
like for translating a[n_1] with the leader for
|
||||
n_1 being a[n_1]. */
|
||||
if (get_expression_id (leader) != get_expression_id (expr))
|
||||
{
|
||||
opresult = phi_translate (leader, set1, set2,
|
||||
pred, phiblock);
|
||||
if (!opresult)
|
||||
break;
|
||||
if (opresult != leader)
|
||||
{
|
||||
tree name = get_representative_for (opresult);
|
||||
if (!name)
|
||||
break;
|
||||
changed |= name != op[n];
|
||||
op[n] = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
changed |= op0 != oldop0;
|
||||
|
||||
if (op1 && TREE_CODE (op1) == SSA_NAME)
|
||||
if (n != 3)
|
||||
{
|
||||
unsigned int op_val_id = VN_INFO (op1)->value_id;
|
||||
leader = find_leader_in_sets (op_val_id, set1, set2);
|
||||
opresult = phi_translate (leader, set1, set2, pred, phiblock);
|
||||
if (opresult && opresult != leader)
|
||||
{
|
||||
tree name = get_representative_for (opresult);
|
||||
if (!name)
|
||||
break;
|
||||
op1 = name;
|
||||
}
|
||||
else if (!opresult)
|
||||
break;
|
||||
if (newoperands)
|
||||
VEC_free (vn_reference_op_s, heap, newoperands);
|
||||
return NULL;
|
||||
}
|
||||
/* We can't possibly insert these. */
|
||||
else if (op1 && !is_gimple_min_invariant (op1))
|
||||
break;
|
||||
changed |= op1 != oldop1;
|
||||
if (op2 && TREE_CODE (op2) == SSA_NAME)
|
||||
{
|
||||
unsigned int op_val_id = VN_INFO (op2)->value_id;
|
||||
leader = find_leader_in_sets (op_val_id, set1, set2);
|
||||
opresult = phi_translate (leader, set1, set2, pred, phiblock);
|
||||
if (opresult && opresult != leader)
|
||||
{
|
||||
tree name = get_representative_for (opresult);
|
||||
if (!name)
|
||||
break;
|
||||
op2 = name;
|
||||
}
|
||||
else if (!opresult)
|
||||
break;
|
||||
}
|
||||
/* We can't possibly insert these. */
|
||||
else if (op2 && !is_gimple_min_invariant (op2))
|
||||
break;
|
||||
changed |= op2 != oldop2;
|
||||
|
||||
if (!newoperands)
|
||||
newoperands = VEC_copy (vn_reference_op_s, heap, operands);
|
||||
/* We may have changed from an SSA_NAME to a constant */
|
||||
if (newop.opcode == SSA_NAME && TREE_CODE (op0) != SSA_NAME)
|
||||
newop.opcode = TREE_CODE (op0);
|
||||
if (newop.opcode == SSA_NAME && TREE_CODE (op[0]) != SSA_NAME)
|
||||
newop.opcode = TREE_CODE (op[0]);
|
||||
newop.type = type;
|
||||
newop.op0 = op0;
|
||||
newop.op1 = op1;
|
||||
newop.op2 = op2;
|
||||
newop.op0 = op[0];
|
||||
newop.op1 = op[1];
|
||||
newop.op2 = op[2];
|
||||
/* If it transforms a non-constant ARRAY_REF into a constant
|
||||
one, adjust the constant offset. */
|
||||
if (newop.opcode == ARRAY_REF
|
||||
&& newop.off == -1
|
||||
&& TREE_CODE (op0) == INTEGER_CST
|
||||
&& TREE_CODE (op1) == INTEGER_CST
|
||||
&& TREE_CODE (op2) == INTEGER_CST)
|
||||
&& TREE_CODE (op[0]) == INTEGER_CST
|
||||
&& TREE_CODE (op[1]) == INTEGER_CST
|
||||
&& TREE_CODE (op[2]) == INTEGER_CST)
|
||||
{
|
||||
double_int off = tree_to_double_int (op0);
|
||||
double_int off = tree_to_double_int (op[0]);
|
||||
off = double_int_add (off,
|
||||
double_int_neg
|
||||
(tree_to_double_int (op1)));
|
||||
off = double_int_mul (off, tree_to_double_int (op2));
|
||||
(tree_to_double_int (op[1])));
|
||||
off = double_int_mul (off, tree_to_double_int (op[2]));
|
||||
if (double_int_fits_in_shwi_p (off))
|
||||
newop.off = off.low;
|
||||
}
|
||||
VEC_replace (vn_reference_op_s, newoperands, j, &newop);
|
||||
/* If it transforms from an SSA_NAME to an address, fold with
|
||||
a preceding indirect reference. */
|
||||
if (j > 0 && op0 && TREE_CODE (op0) == ADDR_EXPR
|
||||
if (j > 0 && op[0] && TREE_CODE (op[0]) == ADDR_EXPR
|
||||
&& VEC_index (vn_reference_op_s,
|
||||
newoperands, j - 1)->opcode == MEM_REF)
|
||||
vn_reference_fold_indirect (&newoperands, &j);
|
||||
|
|
Loading…
Add table
Reference in a new issue