for gcc/ChangeLog from Alexandre Oliva * tree-ssa-loop-ivopts.c (get_phi_with_result): Remove. (remove_statement): Likewise. (rewrite_use_nonlinear_expr): Adjust. (remove_unused_ivs): Collect SSA NAMEs to remove and call... * tree-ssa.c (release_defs_bitset): ... this. New. * tree-flow.h (release_defs_bitset): Declare. Index: gcc/tree-ssa-loop-ivopts.c =================================================================== --- gcc/tree-ssa-loop-ivopts.c.orig 2009-09-07 19:00:52.000000000 -0300 +++ gcc/tree-ssa-loop-ivopts.c 2009-09-07 19:15:39.000000000 -0300 @@ -5038,42 +5038,6 @@ create_new_ivs (struct ivopts_data *data } } -/* Returns the phi-node in BB with result RESULT. */ - -static gimple -get_phi_with_result (basic_block bb, tree result) -{ - gimple_stmt_iterator i = gsi_start_phis (bb); - - for (; !gsi_end_p (i); gsi_next (&i)) - if (gimple_phi_result (gsi_stmt (i)) == result) - return gsi_stmt (i); - - gcc_unreachable (); - return NULL; -} - - -/* Removes statement STMT (real or a phi node). If INCLUDING_DEFINED_NAME - is true, remove also the ssa name defined by the statement. */ - -static void -remove_statement (gimple stmt, bool including_defined_name) -{ - if (gimple_code (stmt) == GIMPLE_PHI) - { - gimple bb_phi = get_phi_with_result (gimple_bb (stmt), - gimple_phi_result (stmt)); - gimple_stmt_iterator bsi = gsi_for_stmt (bb_phi); - remove_phi_node (&bsi, including_defined_name); - } - else - { - gimple_stmt_iterator bsi = gsi_for_stmt (stmt); - gsi_remove (&bsi, true); - release_defs (stmt); - } -} /* Rewrites USE (definition of iv used in a nonlinear expression) using candidate CAND. */ @@ -5176,7 +5140,9 @@ rewrite_use_nonlinear_expr (struct ivopt { ass = gimple_build_assign (tgt, op); gsi_insert_before (&bsi, ass, GSI_SAME_STMT); - remove_statement (use->stmt, false); + + bsi = gsi_for_stmt (use->stmt); + remove_phi_node (&bsi, false); } else { @@ -5414,7 +5380,11 @@ remove_unused_ivs (struct ivopts_data *d { unsigned j; bitmap_iterator bi; + bitmap toremove = BITMAP_ALLOC (NULL); + /* Figure out an order in which to release SSA DEFs so that we don't + release something that we'd have to propagate into a debug stmt + afterwards. */ EXECUTE_IF_SET_IN_BITMAP (data->relevant, 0, j, bi) { struct version_info *info; @@ -5425,25 +5395,12 @@ remove_unused_ivs (struct ivopts_data *d && !info->inv_id && !info->iv->have_use_for && !info->preserve_biv) - { - if (MAY_HAVE_DEBUG_STMTS) - { - gimple stmt; - imm_use_iterator iter; - - FOR_EACH_IMM_USE_STMT (stmt, iter, info->iv->ssa_name) - { - if (!gimple_debug_bind_p (stmt)) - continue; - - /* ??? We can probably do better than this. */ - gimple_debug_bind_reset_value (stmt); - update_stmt (stmt); - } - } - remove_statement (SSA_NAME_DEF_STMT (info->iv->ssa_name), true); - } + bitmap_set_bit (toremove, SSA_NAME_VERSION (info->iv->ssa_name)); } + + release_defs_bitset (toremove); + + BITMAP_FREE (toremove); } /* Frees data allocated by the optimization of a single loop. */ Index: gcc/tree-flow.h =================================================================== --- gcc/tree-flow.h.orig 2009-07-12 08:19:36.000000000 -0300 +++ gcc/tree-flow.h 2009-09-07 19:15:39.000000000 -0300 @@ -586,9 +586,10 @@ typedef struct (VAR) = next_referenced_var (&(ITER))) void propagate_defs_into_debug_stmts (gimple, basic_block, - const gimple_stmt_iterator *); + const gimple_stmt_iterator *); void propagate_var_def_into_debug_stmts (tree, basic_block, - const gimple_stmt_iterator *); + const gimple_stmt_iterator *); +void release_defs_bitset (bitmap toremove); typedef struct { Index: gcc/tree-ssa.c =================================================================== --- gcc/tree-ssa.c.orig 2009-09-01 16:16:04.000000000 -0300 +++ gcc/tree-ssa.c 2009-09-07 19:15:39.000000000 -0300 @@ -440,6 +440,74 @@ propagate_defs_into_debug_stmts (gimple } } +/* Delete SSA DEFs for SSA versions in the TOREMOVE bitmap, removing + dominated stmts before their dominators, so that release_ssa_defs + stands a chance of propagating DEFs into debug bind stmts. */ + +void +release_defs_bitset (bitmap toremove) +{ + unsigned j; + bitmap_iterator bi; + + /* Performing a topological sort is probably overkill, this will + most likely run in slightly superlinear time, rather than the + pathological quadratic worst case. */ + while (!bitmap_empty_p (toremove)) + EXECUTE_IF_SET_IN_BITMAP (toremove, 0, j, bi) + { + bool remove_now = true; + tree var = ssa_name (j); + gimple stmt; + imm_use_iterator uit; + + FOR_EACH_IMM_USE_STMT (stmt, uit, var) + { + ssa_op_iter dit; + def_operand_p def_p; + + /* We can't propagate PHI nodes into debug stmts. */ + if (gimple_code (stmt) == GIMPLE_PHI + || is_gimple_debug (stmt)) + continue; + + /* If we find another definition to remove that uses + the one we're looking at, defer the removal of this + one, so that it can be propagated into debug stmts + after the other is. */ + FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, dit, SSA_OP_DEF) + { + tree odef = DEF_FROM_PTR (def_p); + + if (bitmap_bit_p (toremove, SSA_NAME_VERSION (odef))) + { + remove_now = false; + break; + } + } + + if (!remove_now) + BREAK_FROM_IMM_USE_STMT (uit); + } + + if (remove_now) + { + gimple def = SSA_NAME_DEF_STMT (var); + gimple_stmt_iterator gsi = gsi_for_stmt (def); + + if (gimple_code (def) == GIMPLE_PHI) + remove_phi_node (&gsi, true); + else + { + gsi_remove (&gsi, true); + release_defs (def); + } + + bitmap_clear_bit (toremove, j); + } + } +} + /* Return true if SSA_NAME is malformed and mark it visited. IS_VIRTUAL is true if this SSA_NAME was found inside a virtual