This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR51042
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 10 Nov 2011 16:22:47 +0100 (CET)
- Subject: [PATCH] Fix PR51042
This fixes PR51042.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.
Richard.
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.
Index: gcc/tree-ssa-pre.c
===================================================================
*** gcc/tree-ssa-pre.c (revision 181252)
--- gcc/tree-ssa-pre.c (working copy)
*************** phi_translate_1 (pre_expr expr, bitmap_s
*** 1527,1533 ****
tree newvuse = vuse;
VEC (vn_reference_op_s, heap) *newoperands = NULL;
bool changed = false, same_valid = true;
! unsigned int i, j;
vn_reference_op_t operand;
vn_reference_t newref;
--- 1527,1533 ----
tree newvuse = vuse;
VEC (vn_reference_op_s, heap) *newoperands = NULL;
bool changed = false, same_valid = true;
! unsigned int i, j, n;
vn_reference_op_t operand;
vn_reference_t newref;
*************** phi_translate_1 (pre_expr expr, bitmap_s
*** 1536,1635 ****
{
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 type = operand->type;
vn_reference_op_s newop = *operand;
!
! if (op0 && TREE_CODE (op0) == SSA_NAME)
{
! 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)
{
! tree name = get_representative_for (opresult);
! if (!name)
break;
! op0 = name;
}
! else if (!opresult)
! break;
! }
! changed |= op0 != oldop0;
!
! if (op1 && TREE_CODE (op1) == SSA_NAME)
! {
! 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;
}
! /* 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);
newop.type = type;
! newop.op0 = op0;
! newop.op1 = op1;
! newop.op2 = op2;
/* 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)
{
! double_int off = tree_to_double_int (op0);
off = double_int_add (off,
double_int_neg
! (tree_to_double_int (op1)));
! off = double_int_mul (off, tree_to_double_int (op2));
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
&& VEC_index (vn_reference_op_s,
newoperands, j - 1)->opcode == MEM_REF)
vn_reference_fold_indirect (&newoperands, &j);
--- 1536,1618 ----
{
pre_expr opresult;
pre_expr leader;
! tree op[3];
tree type = operand->type;
vn_reference_op_s newop = *operand;
! op[0] = operand->op0;
! op[1] = operand->op1;
! op[2] = operand->op2;
! for (n = 0; n < 3; ++n)
{
! unsigned int op_val_id;
! if (!op[n])
! continue;
! if (TREE_CODE (op[n]) != SSA_NAME)
{
! /* We can't possibly insert these. */
! if (n != 0
! && !is_gimple_min_invariant (op[n]))
break;
! continue;
}
! 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;
! }
}
}
! if (n != 3)
{
! if (newoperands)
! VEC_free (vn_reference_op_s, heap, newoperands);
! return NULL;
}
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 (op[0]) != SSA_NAME)
! newop.opcode = TREE_CODE (op[0]);
newop.type = type;
! 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 (op[0]) == INTEGER_CST
! && TREE_CODE (op[1]) == INTEGER_CST
! && TREE_CODE (op[2]) == INTEGER_CST)
{
! double_int off = tree_to_double_int (op[0]);
off = double_int_add (off,
double_int_neg
! (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 && 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);
Index: gcc/testsuite/gcc.dg/torture/pr51042.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr51042.c (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr51042.c (revision 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;
+ }
+ }
+ }