This fixes PR55107 - the way we dealt with fully redundant values found by PRE phi-translation breaks existing SETs, so don't special case it in a hacky way but instead create a simple assignment.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2012-12-10 Richard Biener <rguent...@suse.de> PR tree-optimization/55107 * tree-ssa-pre.c (struct pre_stats): Remove constified field. (bitmap_set_replace_value): Add gcc_unreachable. (do_regular_insertion): Re-write all_same handling. Insert an assignment instead of a PHI in this case. (eliminate_bb): Record availability also for SSA names defined by a constant. (do_pre): Do not record constified events. (execute_fre): Likewise. * gcc.dg/torture/pr55107.c: New testcase. * gcc.dg/tree-ssa/ssa-pre-5.c: Adjust. Index: gcc/tree-ssa-pre.c =================================================================== *** gcc/tree-ssa-pre.c (revision 194345) --- gcc/tree-ssa-pre.c (working copy) *************** static struct *** 446,455 **** /* The number of new PHI nodes added by PRE. */ int phis; - - /* The number of values found constant. */ - int constified; - } pre_stats; static bool do_partial_partial; --- 446,451 ---- *************** bitmap_set_replace_value (bitmap_set_t s *** 867,872 **** --- 863,870 ---- return; } } + + gcc_unreachable (); } /* Return true if two bitmap sets are equal. */ *************** do_regular_insertion (basic_block block, *** 3325,3331 **** FOR_EACH_VEC_ELT (exprs, i, expr) { ! if (expr->kind != NAME) { unsigned int val; bool by_some = false; --- 3323,3330 ---- FOR_EACH_VEC_ELT (exprs, i, expr) { ! if (expr->kind == NARY ! || expr->kind == REFERENCE) { unsigned int val; bool by_some = false; *************** do_regular_insertion (basic_block block, *** 3435,3469 **** /* If all edges produce the same value and that value is an invariant, then the PHI has the same value on all edges. Note this. */ ! else if (!cant_insert && all_same && eprime ! && (edoubleprime->kind == CONSTANT ! || edoubleprime->kind == NAME) ! && !value_id_constant_p (val)) { ! unsigned int j; ! bitmap_iterator bi; ! bitmap exprset = value_expressions[val]; ! ! unsigned int new_val = get_expr_value_id (edoubleprime); ! EXECUTE_IF_SET_IN_BITMAP (exprset, 0, j, bi) ! { ! pre_expr expr = expression_for_id (j); ! if (expr->kind == NAME) ! { ! vn_ssa_aux_t info = VN_INFO (PRE_EXPR_NAME (expr)); ! /* Just reset the value id and valnum so it is ! the same as the constant we have discovered. */ ! if (edoubleprime->kind == CONSTANT) ! { ! info->valnum = PRE_EXPR_CONSTANT (edoubleprime); ! pre_stats.constified++; ! } ! else ! info->valnum = VN_INFO (PRE_EXPR_NAME (edoubleprime))->valnum; ! info->value_id = new_val; ! } ! } } } } --- 3434,3461 ---- /* If all edges produce the same value and that value is an invariant, then the PHI has the same value on all edges. Note this. */ ! else if (!cant_insert && all_same) { ! gcc_assert (edoubleprime->kind == CONSTANT ! || edoubleprime->kind == NAME); ! tree temp = make_temp_ssa_name (get_expr_type (expr), ! NULL, "pretmp"); ! gimple assign = gimple_build_assign (temp, ! edoubleprime->kind == CONSTANT ? PRE_EXPR_CONSTANT (edoubleprime) : PRE_EXPR_NAME (edoubleprime)); ! gimple_stmt_iterator gsi = gsi_after_labels (block); ! gsi_insert_before (&gsi, assign, GSI_NEW_STMT); ! ! gimple_set_plf (assign, NECESSARY, false); ! VN_INFO_GET (temp)->value_id = val; ! VN_INFO (temp)->valnum = sccvn_valnum_from_value_id (val); ! if (VN_INFO (temp)->valnum == NULL_TREE) ! VN_INFO (temp)->valnum = temp; ! bitmap_set_bit (inserted_exprs, SSA_NAME_VERSION (temp)); ! pre_expr newe = get_or_alloc_expr_for_name (temp); ! add_to_value (val, newe); ! bitmap_value_replace_in_set (AVAIL_OUT (block), newe); ! bitmap_insert_into_set (NEW_SETS (block), newe); } } } *************** do_partial_partial_insertion (basic_bloc *** 3495,3501 **** FOR_EACH_VEC_ELT (exprs, i, expr) { ! if (expr->kind != NAME) { unsigned int val; bool by_all = true; --- 3487,3494 ---- FOR_EACH_VEC_ELT (exprs, i, expr) { ! if (expr->kind == NARY ! || expr->kind == REFERENCE) { unsigned int val; bool by_all = true; *************** eliminate_bb (dom_walk_data *, basic_blo *** 4142,4167 **** /* Lookup the RHS of the expression, see if we have an available computation for it. If so, replace the RHS with ! the available computation. ! ! See PR43491. ! We don't replace global register variable when it is a the RHS of ! a single assign. We do replace local register variable since gcc ! does not guarantee local variable will be allocated in register. */ if (gimple_has_lhs (stmt) && TREE_CODE (lhs) == SSA_NAME - && !gimple_assign_ssa_name_copy_p (stmt) - && (!gimple_assign_single_p (stmt) - || (!is_gimple_min_invariant (rhs) - && (gimple_assign_rhs_code (stmt) != VAR_DECL - || !is_global_var (rhs) - || !DECL_HARD_REGISTER (rhs)))) && !gimple_has_volatile_ops (stmt)) { tree sprime; gimple orig_stmt = stmt; sprime = eliminate_avail (lhs); if (!sprime) { /* If there is no existing usable leader but SCCVN thinks --- 4135,4166 ---- /* Lookup the RHS of the expression, see if we have an available computation for it. If so, replace the RHS with ! the available computation. */ if (gimple_has_lhs (stmt) && TREE_CODE (lhs) == SSA_NAME && !gimple_has_volatile_ops (stmt)) { tree sprime; gimple orig_stmt = stmt; sprime = eliminate_avail (lhs); + /* If there is no usable leader mark lhs as leader for its value. */ + if (!sprime) + eliminate_push_avail (lhs); + + /* See PR43491. Do not replace a global register variable when + it is a the RHS of an assignment. Do replace local register + variables since gcc does not guarantee a local variable will + be allocated in register. + Do not perform copy propagation or undo constant propagation. */ + if (gimple_assign_single_p (stmt) + && (TREE_CODE (rhs) == SSA_NAME + || is_gimple_min_invariant (rhs) + || (TREE_CODE (rhs) == VAR_DECL + && is_global_var (rhs) + && DECL_HARD_REGISTER (rhs)))) + continue; + if (!sprime) { /* If there is no existing usable leader but SCCVN thinks *************** eliminate_bb (dom_walk_data *, basic_blo *** 4208,4217 **** continue; } - /* If there is no usable leader mark lhs as leader for its value. */ - if (!sprime) - eliminate_push_avail (lhs); - if (sprime && sprime != lhs && (rhs == NULL_TREE --- 4207,4212 ---- *************** do_pre (void) *** 4742,4748 **** statistics_counter_event (cfun, "PA inserted", pre_stats.pa_insert); statistics_counter_event (cfun, "New PHIs", pre_stats.phis); statistics_counter_event (cfun, "Eliminated", pre_stats.eliminations); - statistics_counter_event (cfun, "Constified", pre_stats.constified); clear_expression_ids (); remove_dead_inserted_code (); --- 4737,4742 ---- *************** execute_fre (void) *** 4823,4829 **** statistics_counter_event (cfun, "Insertions", pre_stats.insertions); statistics_counter_event (cfun, "Eliminated", pre_stats.eliminations); - statistics_counter_event (cfun, "Constified", pre_stats.constified); return todo; } --- 4817,4822 ---- Index: gcc/testsuite/gcc.dg/torture/pr55107.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr55107.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr55107.c (working copy) *************** *** 0 **** --- 1,34 ---- + /* { dg-do compile } */ + + typedef unsigned short uint16_t; + + uint16_t a, b; + + uint16_t f(void) + { + int c, **p; + short d = 2, e = 4; + + for (;; b++) + { + int *j, k = 0; + + for (; *j; j++) + { + for(; c; c++) + for(; k < 1; k++) + { + short *f = &d; + + if(b) + return *f; + } + } + + if(!c) + d *= e; + + ((a = d) ? b = 0 : (**p ? : 1) != (d != 1 ? : (a = 0))) != (k ? a : 0) + < (a *= c = k) && (**p = 0); + } + } Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-5.c =================================================================== *** gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-5.c (revision 194345) --- gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-5.c (working copy) *************** foo (int i) *** 12,16 **** } /* We should detect that a+b is the same along both edges, and replace it with 5 */ ! /* { dg-final { scan-tree-dump-times "Constified: 1" 1 "pre"} } */ /* { dg-final { cleanup-tree-dump "pre" } } */ --- 12,17 ---- } /* We should detect that a+b is the same along both edges, and replace it with 5 */ ! /* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */ ! /* { dg-final { scan-tree-dump-times "Insertions" 0 "pre"} } */ /* { dg-final { cleanup-tree-dump "pre" } } */