diff options
Diffstat (limited to 'gcc/tree-ssa.c')
-rw-r--r-- | gcc/tree-ssa.c | 161 |
1 files changed, 46 insertions, 115 deletions
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index 8146e1fed1d..ba8045d4702 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -30,10 +30,15 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "function.h" #include "gimple-pretty-print.h" -#include "bitmap.h" #include "pointer-set.h" -#include "tree-ssa.h" #include "gimple.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-manip.h" +#include "tree-into-ssa.h" +#include "tree-ssa.h" #include "tree-inline.h" #include "hashtab.h" #include "tree-pass.h" @@ -231,6 +236,41 @@ flush_pending_stmts (edge e) redirect_edge_var_map_clear (e); } +/* Replace the LHS of STMT, an assignment, either a GIMPLE_ASSIGN or a + GIMPLE_CALL, with NLHS, in preparation for modifying the RHS to an + expression with a different value. + + This will update any annotations (say debug bind stmts) referring + to the original LHS, so that they use the RHS instead. This is + done even if NLHS and LHS are the same, for it is understood that + the RHS will be modified afterwards, and NLHS will not be assigned + an equivalent value. + + Adjusting any non-annotation uses of the LHS, if needed, is a + responsibility of the caller. + + The effect of this call should be pretty much the same as that of + inserting a copy of STMT before STMT, and then removing the + original stmt, at which time gsi_remove() would have update + annotations, but using this function saves all the inserting, + copying and removing. */ + +void +gimple_replace_ssa_lhs (gimple stmt, tree nlhs) +{ + if (MAY_HAVE_DEBUG_STMTS) + { + tree lhs = gimple_get_lhs (stmt); + + gcc_assert (SSA_NAME_DEF_STMT (lhs) == stmt); + + insert_debug_temp_for_var_def (NULL, lhs); + } + + gimple_set_lhs (stmt, nlhs); +} + + /* Given a tree for an expression for which we might want to emit locations or values in debug information (generally a variable, but we might deal with other kinds of trees in the future), return the @@ -1118,8 +1158,8 @@ const pass_data pass_data_init_datastructures = class pass_init_datastructures : public gimple_opt_pass { public: - pass_init_datastructures(gcc::context *ctxt) - : gimple_opt_pass(pass_data_init_datastructures, ctxt) + pass_init_datastructures (gcc::context *ctxt) + : gimple_opt_pass (pass_data_init_datastructures, ctxt) {} /* opt_pass methods: */ @@ -1218,115 +1258,6 @@ ssa_undefined_value_p (tree t) } -/* Internal helper for walk_use_def_chains. VAR, FN and DATA are as - described in walk_use_def_chains. - - VISITED is a pointer set used to mark visited SSA_NAMEs to avoid - infinite loops. We used to have a bitmap for this to just mark - SSA versions we had visited. But non-sparse bitmaps are way too - expensive, while sparse bitmaps may cause quadratic behavior. - - IS_DFS is true if the caller wants to perform a depth-first search - when visiting PHI nodes. A DFS will visit each PHI argument and - call FN after each one. Otherwise, all the arguments are - visited first and then FN is called with each of the visited - arguments in a separate pass. */ - -static bool -walk_use_def_chains_1 (tree var, walk_use_def_chains_fn fn, void *data, - struct pointer_set_t *visited, bool is_dfs) -{ - gimple def_stmt; - - if (pointer_set_insert (visited, var)) - return false; - - def_stmt = SSA_NAME_DEF_STMT (var); - - if (gimple_code (def_stmt) != GIMPLE_PHI) - { - /* If we reached the end of the use-def chain, call FN. */ - return fn (var, def_stmt, data); - } - else - { - size_t i; - - /* When doing a breadth-first search, call FN before following the - use-def links for each argument. */ - if (!is_dfs) - for (i = 0; i < gimple_phi_num_args (def_stmt); i++) - if (fn (gimple_phi_arg_def (def_stmt, i), def_stmt, data)) - return true; - - /* Follow use-def links out of each PHI argument. */ - for (i = 0; i < gimple_phi_num_args (def_stmt); i++) - { - tree arg = gimple_phi_arg_def (def_stmt, i); - - /* ARG may be NULL for newly introduced PHI nodes. */ - if (arg - && TREE_CODE (arg) == SSA_NAME - && walk_use_def_chains_1 (arg, fn, data, visited, is_dfs)) - return true; - } - - /* When doing a depth-first search, call FN after following the - use-def links for each argument. */ - if (is_dfs) - for (i = 0; i < gimple_phi_num_args (def_stmt); i++) - if (fn (gimple_phi_arg_def (def_stmt, i), def_stmt, data)) - return true; - } - - return false; -} - - - -/* Walk use-def chains starting at the SSA variable VAR. Call - function FN at each reaching definition found. FN takes three - arguments: VAR, its defining statement (DEF_STMT) and a generic - pointer to whatever state information that FN may want to maintain - (DATA). FN is able to stop the walk by returning true, otherwise - in order to continue the walk, FN should return false. - - Note, that if DEF_STMT is a PHI node, the semantics are slightly - different. The first argument to FN is no longer the original - variable VAR, but the PHI argument currently being examined. If FN - wants to get at VAR, it should call PHI_RESULT (PHI). - - If IS_DFS is true, this function will: - - 1- walk the use-def chains for all the PHI arguments, and, - 2- call (*FN) (ARG, PHI, DATA) on all the PHI arguments. - - If IS_DFS is false, the two steps above are done in reverse order - (i.e., a breadth-first search). */ - -void -walk_use_def_chains (tree var, walk_use_def_chains_fn fn, void *data, - bool is_dfs) -{ - gimple def_stmt; - - gcc_assert (TREE_CODE (var) == SSA_NAME); - - def_stmt = SSA_NAME_DEF_STMT (var); - - /* We only need to recurse if the reaching definition comes from a PHI - node. */ - if (gimple_code (def_stmt) != GIMPLE_PHI) - (*fn) (var, def_stmt, data); - else - { - struct pointer_set_t *visited = pointer_set_create (); - walk_use_def_chains_1 (var, fn, data, visited, is_dfs); - pointer_set_destroy (visited); - } -} - - /* If necessary, rewrite the base of the reference tree *TP from a MEM_REF to a plain or converted symbol. */ @@ -1758,8 +1689,8 @@ const pass_data pass_data_update_address_taken = class pass_update_address_taken : public gimple_opt_pass { public: - pass_update_address_taken(gcc::context *ctxt) - : gimple_opt_pass(pass_data_update_address_taken, ctxt) + pass_update_address_taken (gcc::context *ctxt) + : gimple_opt_pass (pass_data_update_address_taken, ctxt) {} /* opt_pass methods: */ |