diff options
author | Richard Guenther <rguenther@suse.de> | 2011-11-10 15:28:57 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2011-11-10 15:28:57 +0000 |
commit | 4da80bfb5d2e188674abdf5461876108e77ab881 (patch) | |
tree | 8c7ddc725098e69e509a4775363d0458e154e0d0 | |
parent | c07a8cb3c903f5152e013748f773adecdb82122e (diff) | |
download | gcc-4da80bfb5d2e188674abdf5461876108e77ab881.zip gcc-4da80bfb5d2e188674abdf5461876108e77ab881.tar.gz gcc-4da80bfb5d2e188674abdf5461876108e77ab881.tar.bz2 |
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
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr51042.c | 22 | ||||
-rw-r--r-- | gcc/tree-ssa-pre.c | 113 |
4 files changed, 81 insertions, 65 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ee388f6..404b884 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 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 * tree-loop-distribution.c (generate_builtin): Do not replace the loop with a builtin if the partition contains statements which diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c04d8dc..ecfcdbe 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 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 * gcc.dg/torture/pr51070.c: New testcase. diff --git a/gcc/testsuite/gcc.dg/torture/pr51042.c b/gcc/testsuite/gcc.dg/torture/pr51042.c new file mode 100644 index 0000000..05961c4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr51042.c @@ -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; + } + } +} diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index 60ae35c..557b56a 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -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) - break; - } - changed |= op0 != oldop0; - - if (op1 && TREE_CODE (op1) == SSA_NAME) - { - unsigned int op_val_id = VN_INFO (op1)->value_id; + op_val_id = VN_INFO (op[n])->value_id; leader = find_leader_in_sets (op_val_id, set1, set2); - opresult = phi_translate (leader, set1, set2, pred, phiblock); - if (opresult && opresult != leader) + 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)) { - tree name = get_representative_for (opresult); - if (!name) + opresult = phi_translate (leader, set1, set2, + pred, phiblock); + if (!opresult) break; - op1 = name; + if (opresult != leader) + { + tree name = get_representative_for (opresult); + if (!name) + break; + changed |= name != op[n]; + op[n] = 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) + if (n != 3) { - 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; + if (newoperands) + VEC_free (vn_reference_op_s, heap, newoperands); + return NULL; } - /* 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); |