diff options
Diffstat (limited to 'gcc/tree-ssa.c')
-rw-r--r-- | gcc/tree-ssa.c | 315 |
1 files changed, 1 insertions, 314 deletions
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index e23e665..93b5480 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -285,7 +285,7 @@ verify_use (basic_block bb, basic_block def_bb, use_operand_p use_p, { fprintf (stderr, "for SSA_NAME: "); print_generic_expr (stderr, ssa_name, TDF_VOPS); - fprintf (stderr, "in statement:\n"); + fprintf (stderr, " in statement:\n"); print_generic_stmt (stderr, stmt, TDF_VOPS); } @@ -1028,319 +1028,6 @@ walk_use_def_chains (tree var, walk_use_def_chains_fn fn, void *data, } } - -/* Replaces VAR with REPL in memory reference expression *X in - statement STMT at use location USE_P. Return TRUE if Anything was done. */ - -static bool -propagate_into_addr (tree stmt, use_operand_p use_p, tree *x, tree repl) -{ - tree new_var, ass_stmt, addr_var; - basic_block bb; - block_stmt_iterator bsi; - - /* There is nothing special to handle in the other cases. */ - if (TREE_CODE (repl) != ADDR_EXPR) - return false; - addr_var = TREE_OPERAND (repl, 0); - - while (handled_component_p (*x) - || TREE_CODE (*x) == REALPART_EXPR - || TREE_CODE (*x) == IMAGPART_EXPR) - x = &TREE_OPERAND (*x, 0); - - /* Heres a hack but since KRPhinodes is going away soon, Im not going to - sweat it. */ - if (TREE_CODE (*x) != INDIRECT_REF - || &(TREE_OPERAND (*x, 0)) != use_p->use) /* HACK ALERT. */ - return false; - - if (TREE_TYPE (*x) == TREE_TYPE (addr_var)) - { - *x = addr_var; - mark_new_vars_to_rename (stmt, vars_to_rename); - return true; - } - - - /* Frontends sometimes produce expressions like *&a instead of a[0]. - Create a temporary variable to handle this case. */ - ass_stmt = build2 (MODIFY_EXPR, void_type_node, NULL_TREE, repl); - new_var = duplicate_ssa_name (USE_FROM_PTR (use_p), ass_stmt); - TREE_OPERAND (*x, 0) = new_var; - TREE_OPERAND (ass_stmt, 0) = new_var; - - bb = bb_for_stmt (stmt); - tree_block_label (bb); - bsi = bsi_after_labels (bb); - bsi_insert_after (&bsi, ass_stmt, BSI_NEW_STMT); - - mark_new_vars_to_rename (stmt, vars_to_rename); - return true; -} - -/* Replaces immediate uses of VAR by REPL. */ - -static void -replace_immediate_uses (tree var, tree repl) -{ - tree stmt; - bool mark_new_vars; - use_operand_p imm_use; - imm_use_iterator imm_iter; - - FOR_EACH_IMM_USE_SAFE (imm_use, imm_iter, var) - { - stmt = USE_STMT (imm_use); - - if (TREE_CODE (stmt) == PHI_NODE) - { - int index = PHI_ARG_INDEX_FROM_USE (imm_use); -#ifdef ENABLE_CHECKING - gcc_assert (&(PHI_ARG_IMM_USE_NODE (stmt, index)) == imm_use); -#endif - SET_USE (imm_use, repl); - if (TREE_CODE (repl) == SSA_NAME - && PHI_ARG_EDGE (stmt, index)->flags & EDGE_ABNORMAL) - SSA_NAME_OCCURS_IN_ABNORMAL_PHI (repl) = 1; - continue; - } - - gcc_assert (!stmt_modified_p (stmt)); - - mark_new_vars = false; - if (is_gimple_reg (SSA_NAME_VAR (var))) - { - bool propagated = false; - if (TREE_CODE (stmt) == MODIFY_EXPR) - { - if (TREE_CODE (repl) == ADDR_EXPR) - { - propagated = - propagate_into_addr (stmt, imm_use, &TREE_OPERAND (stmt, 0), - repl); - if (!propagated) - propagated = - propagate_into_addr (stmt, imm_use, - &TREE_OPERAND (stmt, 1), repl); - } - } - if (!propagated) - propagate_value (imm_use, repl); - mark_new_vars = POINTER_TYPE_P (TREE_TYPE (repl)); - } - else - propagate_value (imm_use, repl); - - /* FIXME. If REPL is a constant, we need to fold STMT. - However, fold_stmt wants a pointer to the statement, because - it may happen that it needs to replace the whole statement - with a new expression. Since the current def-use machinery - does not return pointers to statements, we call fold_stmt - with the address of a local temporary, if that call changes - the temporary then we fallback on looking for a proper - pointer to STMT by scanning STMT's basic block. - - Note that all this will become unnecessary soon. This - pass is being replaced with a proper copy propagation pass - for 4.1 (dnovillo, 2004-09-17). */ - if (TREE_CODE (repl) != SSA_NAME) - { - tree tmp = stmt; - fold_stmt (&tmp); - mark_new_vars = true; - if (tmp != stmt) - { - block_stmt_iterator si = bsi_for_stmt (stmt); - mark_new_vars_to_rename (tmp, vars_to_rename); - bsi_replace (&si, tmp, true); - stmt = bsi_stmt (si); - } - } - - /* If REPL is a pointer, it may have different memory tags associated - with it. For instance, VAR may have had a name tag while REPL - only had a type tag. In these cases, the virtual operands (if - any) in the statement will refer to different symbols which need - to be renamed. */ - if (mark_new_vars) - mark_new_vars_to_rename (stmt, vars_to_rename); - else - update_stmt (stmt); - } - -} - -/* Gets the value VAR is equivalent to according to EQ_TO. */ - -static tree -get_eq_name (tree *eq_to, tree var) -{ - unsigned ver; - tree val = var; - - while (TREE_CODE (val) == SSA_NAME) - { - ver = SSA_NAME_VERSION (val); - if (!eq_to[ver]) - break; - - val = eq_to[ver]; - } - - while (TREE_CODE (var) == SSA_NAME) - { - ver = SSA_NAME_VERSION (var); - if (!eq_to[ver]) - break; - - var = eq_to[ver]; - eq_to[ver] = val; - } - - return val; -} - -/* Checks whether phi node PHI is redundant and if it is, records the ssa name - its result is redundant to to EQ_TO array. */ - -static void -check_phi_redundancy (tree phi, tree *eq_to) -{ - tree val = NULL_TREE, def, res = PHI_RESULT (phi), stmt; - unsigned i, ver = SSA_NAME_VERSION (res); - imm_use_iterator imm_iter; - use_operand_p use_p; - - /* It is unlikely that such large phi node would be redundant. */ - if (PHI_NUM_ARGS (phi) > 16) - return; - - for (i = 0; i < (unsigned) PHI_NUM_ARGS (phi); i++) - { - def = PHI_ARG_DEF (phi, i); - - if (TREE_CODE (def) == SSA_NAME) - { - def = get_eq_name (eq_to, def); - if (def == res) - continue; - } - - if (val - && !operand_equal_for_phi_arg_p (val, def)) - return; - - val = def; - } - - /* At least one of the arguments should not be equal to the result, or - something strange is happening. */ - gcc_assert (val); - - if (get_eq_name (eq_to, res) == val) - return; - - if (!may_propagate_copy (res, val)) - return; - - eq_to[ver] = val; - - FOR_EACH_IMM_USE_FAST (use_p, imm_iter, res) - { - stmt = USE_STMT (use_p); - if (TREE_CODE (stmt) == PHI_NODE) - check_phi_redundancy (stmt, eq_to); - } -} - -/* Removes redundant phi nodes. - - A redundant PHI node is a PHI node where all of its PHI arguments - are the same value, excluding any PHI arguments which are the same - as the PHI result. - - A redundant PHI node is effectively a copy, so we forward copy propagate - which removes all uses of the destination of the PHI node then - finally we delete the redundant PHI node. - - Note that if we can not copy propagate the PHI node, then the PHI - will not be removed. Thus we do not have to worry about dependencies - between PHIs and the problems serializing PHIs into copies creates. - - The most important effect of this pass is to remove degenerate PHI - nodes created by removing unreachable code. */ - -void -kill_redundant_phi_nodes (void) -{ - tree *eq_to; - unsigned i, old_num_ssa_names; - basic_block bb; - tree phi, repl, stmt; - - /* The EQ_TO[VER] holds the value by that the ssa name VER should be - replaced. If EQ_TO[VER] is ssa name and it is decided to replace it by - other value, it may be necessary to follow the chain till the final value. - We perform path shortening (replacing the entries of the EQ_TO array with - heads of these chains) whenever we access the field to prevent quadratic - complexity (probably would not occur in practice anyway, but let us play - it safe). */ - eq_to = xcalloc (num_ssa_names, sizeof (tree)); - - old_num_ssa_names = num_ssa_names; - - FOR_EACH_BB (bb) - { - for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi)) - check_phi_redundancy (phi, eq_to); - } - - /* Now propagate the values. */ - for (i = 0; i < old_num_ssa_names; i++) - { - if (!ssa_name (i)) - continue; - - repl = get_eq_name (eq_to, ssa_name (i)); - if (repl != ssa_name (i)) - replace_immediate_uses (ssa_name (i), repl); - } - - /* And remove the dead phis. */ - for (i = 0; i < old_num_ssa_names; i++) - { - if (!ssa_name (i)) - continue; - - repl = get_eq_name (eq_to, ssa_name (i)); - if (repl != ssa_name (i)) - { - stmt = SSA_NAME_DEF_STMT (ssa_name (i)); - remove_phi_node (stmt, NULL_TREE); - } - } - - free (eq_to); -} - -struct tree_opt_pass pass_redundant_phi = -{ - "redphi", /* name */ - NULL, /* gate */ - kill_redundant_phi_nodes, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_TREE_REDPHI, /* tv_id */ - PROP_cfg | PROP_ssa | PROP_alias, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - TODO_dump_func | TODO_rename_vars - | TODO_ggc_collect | TODO_verify_ssa, /* todo_flags_finish */ - 0 /* letter */ -}; /* Emit warnings for uninitialized variables. This is done in two passes. |