From 0bc67bf01c72cb9dd2c0802e5bd5def03d808100 Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Tue, 3 Jan 2012 14:46:03 +0000 Subject: 2012-01-03 Richard Guenther Backport from mainline 2011-11-10 Richard Guenther 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. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/gcc-4_6-branch@182848 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 9 +++ gcc/testsuite/ChangeLog | 8 +++ gcc/testsuite/gcc.dg/torture/pr51042.c | 22 +++++++ gcc/tree-ssa-pre.c | 113 ++++++++++++++------------------- 4 files changed, 87 insertions(+), 65 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr51042.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6e4fe5c2c0f..7ad80f14c12 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2012-01-03 Richard Guenther + + Backport from mainline + 2011-11-10 Richard Guenther + + PR tree-optimization/51042 + * tree-ssa-pre.c (phi_translate_1): Avoid recursing on + self-referential expressions. Refactor code to avoid duplication. + 2012-01-03 Richard Guenther PR tree-optimization/51070 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b6ec7b7b1b0..b024311c51c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2012-01-03 Richard Guenther + + Backport from mainline + 2011-11-10 Richard Guenther + + PR tree-optimization/51042 + * gcc.dg/torture/pr51042.c: New testcase. + 2012-01-03 Richard Guenther PR tree-optimization/51070 diff --git a/gcc/testsuite/gcc.dg/torture/pr51042.c b/gcc/testsuite/gcc.dg/torture/pr51042.c new file mode 100644 index 00000000000..05961c4acf5 --- /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 e2a8dc2ec54..2753fd7ada3 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -1545,7 +1545,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; @@ -1554,100 +1554,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); -- cgit v1.2.3