X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree-ssa.c;h=f0bbf3b9823fa6be4f2a03da856c97c31c866884;hb=ad5e18de84e08637208a4820dc5314674f68019e;hp=a40270335df7c7c8e3062f07a46b9a4cde3711a6;hpb=dfe8e806805d4f3b1b396b195f7ecfba089b9b1a;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index a40270335df..f0bbf3b9823 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -1,5 +1,5 @@ /* Miscellaneous SSA utility functions. - Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009 + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of GCC. @@ -24,28 +24,25 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "tree.h" #include "flags.h" -#include "rtl.h" #include "tm_p.h" #include "target.h" #include "ggc.h" #include "langhooks.h" -#include "hard-reg-set.h" #include "basic-block.h" #include "output.h" -#include "expr.h" #include "function.h" -#include "diagnostic.h" +#include "tree-pretty-print.h" +#include "gimple-pretty-print.h" #include "bitmap.h" #include "pointer-set.h" #include "tree-flow.h" #include "gimple.h" #include "tree-inline.h" -#include "varray.h" #include "timevar.h" #include "hashtab.h" #include "tree-dump.h" #include "tree-pass.h" -#include "toplev.h" +#include "diagnostic-core.h" /* Pointer map of variable mappings, keyed by edge. */ static struct pointer_map_t *edge_var_maps; @@ -243,6 +240,372 @@ flush_pending_stmts (edge e) redirect_edge_var_map_clear (e); } +/* 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 + tree that should be used as the variable of a DEBUG_BIND STMT or + VAR_LOCATION INSN or NOTE. Return NULL if VAR is not to be tracked. */ + +tree +target_for_debug_bind (tree var) +{ + if (!MAY_HAVE_DEBUG_STMTS) + return NULL_TREE; + + if (TREE_CODE (var) != VAR_DECL + && TREE_CODE (var) != PARM_DECL) + return NULL_TREE; + + if (DECL_HAS_VALUE_EXPR_P (var)) + return target_for_debug_bind (DECL_VALUE_EXPR (var)); + + if (DECL_IGNORED_P (var)) + return NULL_TREE; + + if (!is_gimple_reg (var)) + return NULL_TREE; + + return var; +} + +/* Called via walk_tree, look for SSA_NAMEs that have already been + released. */ + +static tree +find_released_ssa_name (tree *tp, int *walk_subtrees, void *data_) +{ + struct walk_stmt_info *wi = (struct walk_stmt_info *) data_; + + if (wi && wi->is_lhs) + return NULL_TREE; + + if (TREE_CODE (*tp) == SSA_NAME) + { + if (SSA_NAME_IN_FREE_LIST (*tp)) + return *tp; + + *walk_subtrees = 0; + } + else if (IS_TYPE_OR_DECL_P (*tp)) + *walk_subtrees = 0; + + return NULL_TREE; +} + +/* Insert a DEBUG BIND stmt before the DEF of VAR if VAR is referenced + by other DEBUG stmts, and replace uses of the DEF with the + newly-created debug temp. */ + +void +insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var) +{ + imm_use_iterator imm_iter; + use_operand_p use_p; + gimple stmt; + gimple def_stmt = NULL; + int usecount = 0; + tree value = NULL; + + if (!MAY_HAVE_DEBUG_STMTS) + return; + + /* If this name has already been registered for replacement, do nothing + as anything that uses this name isn't in SSA form. */ + if (name_registered_for_update_p (var)) + return; + + /* Check whether there are debug stmts that reference this variable and, + if there are, decide whether we should use a debug temp. */ + FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var) + { + stmt = USE_STMT (use_p); + + if (!gimple_debug_bind_p (stmt)) + continue; + + if (usecount++) + break; + + if (gimple_debug_bind_get_value (stmt) != var) + { + /* Count this as an additional use, so as to make sure we + use a temp unless VAR's definition has a SINGLE_RHS that + can be shared. */ + usecount++; + break; + } + } + + if (!usecount) + return; + + if (gsi) + def_stmt = gsi_stmt (*gsi); + else + def_stmt = SSA_NAME_DEF_STMT (var); + + /* If we didn't get an insertion point, and the stmt has already + been removed, we won't be able to insert the debug bind stmt, so + we'll have to drop debug information. */ + if (gimple_code (def_stmt) == GIMPLE_PHI) + { + value = degenerate_phi_result (def_stmt); + if (value && walk_tree (&value, find_released_ssa_name, NULL, NULL)) + value = NULL; + /* error_mark_node is what fixup_noreturn_call changes PHI arguments + to. */ + else if (value == error_mark_node) + value = NULL; + } + else if (is_gimple_assign (def_stmt)) + { + bool no_value = false; + + if (!dom_info_available_p (CDI_DOMINATORS)) + { + struct walk_stmt_info wi; + + memset (&wi, 0, sizeof (wi)); + + /* When removing blocks without following reverse dominance + order, we may sometimes encounter SSA_NAMEs that have + already been released, referenced in other SSA_DEFs that + we're about to release. Consider: + + : + v_1 = foo; + + : + w_2 = v_1 + bar; + # DEBUG w => w_2 + + If we deleted BB X first, propagating the value of w_2 + won't do us any good. It's too late to recover their + original definition of v_1: when it was deleted, it was + only referenced in other DEFs, it couldn't possibly know + it should have been retained, and propagating every + single DEF just in case it might have to be propagated + into a DEBUG STMT would probably be too wasteful. + + When dominator information is not readily available, we + check for and accept some loss of debug information. But + if it is available, there's no excuse for us to remove + blocks in the wrong order, so we don't even check for + dead SSA NAMEs. SSA verification shall catch any + errors. */ + if ((!gsi && !gimple_bb (def_stmt)) + || walk_gimple_op (def_stmt, find_released_ssa_name, &wi)) + no_value = true; + } + + if (!no_value) + value = gimple_assign_rhs_to_tree (def_stmt); + } + + if (value) + { + /* If there's a single use of VAR, and VAR is the entire debug + expression (usecount would have been incremented again + otherwise), and the definition involves only constants and + SSA names, then we can propagate VALUE into this single use, + avoiding the temp. + + We can also avoid using a temp if VALUE can be shared and + propagated into all uses, without generating expressions that + wouldn't be valid gimple RHSs. + + Other cases that would require unsharing or non-gimple RHSs + are deferred to a debug temp, although we could avoid temps + at the expense of duplication of expressions. */ + + if (CONSTANT_CLASS_P (value) + || gimple_code (def_stmt) == GIMPLE_PHI + || (usecount == 1 + && (!gimple_assign_single_p (def_stmt) + || is_gimple_min_invariant (value))) + || is_gimple_reg (value)) + value = unshare_expr (value); + else + { + gimple def_temp; + tree vexpr = make_node (DEBUG_EXPR_DECL); + + def_temp = gimple_build_debug_bind (vexpr, + unshare_expr (value), + def_stmt); + + DECL_ARTIFICIAL (vexpr) = 1; + TREE_TYPE (vexpr) = TREE_TYPE (value); + if (DECL_P (value)) + DECL_MODE (vexpr) = DECL_MODE (value); + else + DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (value)); + + if (gsi) + gsi_insert_before (gsi, def_temp, GSI_SAME_STMT); + else + { + gimple_stmt_iterator ngsi = gsi_for_stmt (def_stmt); + gsi_insert_before (&ngsi, def_temp, GSI_SAME_STMT); + } + + value = vexpr; + } + } + + FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var) + { + if (!gimple_debug_bind_p (stmt)) + continue; + + if (value) + { + FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter) + /* unshare_expr is not needed here. vexpr is either a + SINGLE_RHS, that can be safely shared, some other RHS + that was unshared when we found it had a single debug + use, or a DEBUG_EXPR_DECL, that can be safely + shared. */ + SET_USE (use_p, value); + /* If we didn't replace uses with a debug decl fold the + resulting expression. Otherwise we end up with invalid IL. */ + if (TREE_CODE (value) != DEBUG_EXPR_DECL) + fold_stmt_inplace (stmt); + } + else + gimple_debug_bind_reset_value (stmt); + + update_stmt (stmt); + } +} + + +/* Insert a DEBUG BIND stmt before STMT for each DEF referenced by + other DEBUG stmts, and replace uses of the DEF with the + newly-created debug temp. */ + +void +insert_debug_temps_for_defs (gimple_stmt_iterator *gsi) +{ + gimple stmt; + ssa_op_iter op_iter; + def_operand_p def_p; + + if (!MAY_HAVE_DEBUG_STMTS) + return; + + stmt = gsi_stmt (*gsi); + + FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt, op_iter, SSA_OP_DEF) + { + tree var = DEF_FROM_PTR (def_p); + + if (TREE_CODE (var) != SSA_NAME) + continue; + + insert_debug_temp_for_var_def (gsi, var); + } +} + +/* Reset all debug stmts that use SSA_NAME(s) defined in STMT. */ + +void +reset_debug_uses (gimple stmt) +{ + ssa_op_iter op_iter; + def_operand_p def_p; + imm_use_iterator imm_iter; + gimple use_stmt; + + if (!MAY_HAVE_DEBUG_STMTS) + return; + + FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt, op_iter, SSA_OP_DEF) + { + tree var = DEF_FROM_PTR (def_p); + + if (TREE_CODE (var) != SSA_NAME) + continue; + + FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, var) + { + if (!gimple_debug_bind_p (use_stmt)) + continue; + + gimple_debug_bind_reset_value (use_stmt); + update_stmt (use_stmt); + } + } +} + +/* 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 @@ -316,6 +679,13 @@ verify_def (basic_block bb, basic_block *definition_block, tree ssa_name, if (verify_ssa_name (ssa_name, is_virtual)) goto err; + if (TREE_CODE (SSA_NAME_VAR (ssa_name)) == RESULT_DECL + && DECL_BY_REFERENCE (SSA_NAME_VAR (ssa_name))) + { + error ("RESULT_DECL should be read only when DECL_BY_REFERENCE is set"); + goto err; + } + if (definition_block[SSA_NAME_VERSION (ssa_name)]) { error ("SSA_NAME created in two different blocks %i and %i", @@ -404,7 +774,7 @@ verify_use (basic_block bb, basic_block def_bb, use_operand_p use_p, err = true; } - /* Make sure the use is in an appropriate list by checking the previous + /* Make sure the use is in an appropriate list by checking the previous element to make sure it's the same. */ if (use_p->prev == NULL) { @@ -533,7 +903,7 @@ error: /* Verify common invariants in the SSA web. TODO: verify the variable annotations. */ -void +DEBUG_FUNCTION void verify_ssa (bool check_modified_stmt) { size_t i; @@ -546,7 +916,7 @@ verify_ssa (bool check_modified_stmt) gcc_assert (!need_ssa_update_p (cfun)); - verify_stmts (); + verify_gimple_in_cfg (cfun); timevar_push (TV_TREE_SSA_VERIFY); @@ -609,6 +979,8 @@ verify_ssa (bool check_modified_stmt) gimple stmt = gsi_stmt (gsi); use_operand_p use_p; bool has_err; + int count; + unsigned i; if (check_modified_stmt && gimple_modified_p (stmt)) { @@ -636,6 +1008,9 @@ verify_ssa (bool check_modified_stmt) goto err; } } + else if (gimple_debug_bind_p (stmt) + && !gimple_debug_bind_has_value_p (stmt)) + continue; /* Verify the single virtual operand and its constraints. */ has_err = false; @@ -675,6 +1050,7 @@ verify_ssa (bool check_modified_stmt) goto err; } + count = 0; FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE|SSA_OP_DEF) { if (verify_ssa_name (op, false)) @@ -683,6 +1059,19 @@ verify_ssa (bool check_modified_stmt) print_gimple_stmt (stderr, stmt, 0, TDF_VOPS|TDF_MEMSYMS); goto err; } + count++; + } + + for (i = 0; i < gimple_num_ops (stmt); i++) + { + op = gimple_op (stmt, i); + if (op && TREE_CODE (op) == SSA_NAME && --count < 0) + { + error ("number of operands and imm-links don%'t agree" + " in statement"); + print_gimple_stmt (stderr, stmt, 0, TDF_VOPS|TDF_MEMSYMS); + goto err; + } } FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE|SSA_OP_VUSE) @@ -720,7 +1109,7 @@ verify_ssa (bool check_modified_stmt) free_dominance_info (CDI_DOMINATORS); else set_dom_info_availability (CDI_DOMINATORS, orig_dom_state); - + BITMAP_FREE (names_defined_in_bb); timevar_pop (TV_TREE_SSA_VERIFY); return; @@ -789,13 +1178,12 @@ uid_ssaname_map_hash (const void *item) void init_tree_ssa (struct function *fn) { - fn->gimple_df = GGC_CNEW (struct gimple_df); - fn->gimple_df->referenced_vars = htab_create_ggc (20, uid_decl_map_hash, + fn->gimple_df = ggc_alloc_cleared_gimple_df (); + fn->gimple_df->referenced_vars = htab_create_ggc (20, uid_decl_map_hash, uid_decl_map_eq, NULL); - fn->gimple_df->default_defs = htab_create_ggc (20, uid_ssaname_map_hash, + fn->gimple_df->default_defs = htab_create_ggc (20, uid_ssaname_map_hash, uid_ssaname_map_eq, NULL); pt_solution_reset (&fn->gimple_df->escaped); - pt_solution_reset (&fn->gimple_df->callused); init_ssanames (fn, 0); init_phinodes (); } @@ -810,13 +1198,15 @@ delete_tree_ssa (void) tree var; /* Remove annotations from every referenced local variable. */ - FOR_EACH_REFERENCED_VAR (var, rvi) + FOR_EACH_REFERENCED_VAR (cfun, var, rvi) { if (is_global_var (var)) continue; - if (var->base.ann) - ggc_free (var->base.ann); - var->base.ann = NULL; + if (var_ann (var)) + { + ggc_free (var_ann (var)); + *DECL_VAR_ANN_PTR (var) = NULL; + } } htab_delete (gimple_referenced_vars (cfun)); cfun->gimple_df->referenced_vars = NULL; @@ -828,12 +1218,9 @@ delete_tree_ssa (void) if (ssa_operands_active ()) fini_ssa_operands (); - delete_alias_heapvars (); - htab_delete (cfun->gimple_df->default_defs); cfun->gimple_df->default_defs = NULL; pt_solution_reset (&cfun->gimple_df->escaped); - pt_solution_reset (&cfun->gimple_df->callused); if (cfun->gimple_df->decls_to_pointers != NULL) pointer_map_destroy (cfun->gimple_df->decls_to_pointers); cfun->gimple_df->decls_to_pointers = NULL; @@ -874,11 +1261,20 @@ useless_type_conversion_p (tree outer_type, tree inner_type) if (POINTER_TYPE_P (inner_type) && POINTER_TYPE_P (outer_type)) { + /* Do not lose casts between pointers to different address spaces. */ + if (TYPE_ADDR_SPACE (TREE_TYPE (outer_type)) + != TYPE_ADDR_SPACE (TREE_TYPE (inner_type))) + return false; + /* Do not lose casts to restrict qualified pointers. */ if ((TYPE_RESTRICT (outer_type) != TYPE_RESTRICT (inner_type)) && TYPE_RESTRICT (outer_type)) return false; + + /* If the outer type is (void *), the conversion is not necessary. */ + if (VOID_TYPE_P (TREE_TYPE (outer_type))) + return true; } /* From now on qualifiers on value types do not matter. */ @@ -910,6 +1306,13 @@ useless_type_conversion_p (tree outer_type, tree inner_type) || TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type)) return false; + /* Preserve conversions to BOOLEAN_TYPE if it is not of precision + one. */ + if (TREE_CODE (inner_type) != BOOLEAN_TYPE + && TREE_CODE (outer_type) == BOOLEAN_TYPE + && TYPE_PRECISION (outer_type) != 1) + return false; + /* We don't need to preserve changes in the types minimum or maximum value in general as these do not generate code unless the types precisions are different. */ @@ -930,51 +1333,18 @@ useless_type_conversion_p (tree outer_type, tree inner_type) else if (POINTER_TYPE_P (inner_type) && POINTER_TYPE_P (outer_type)) { - /* If the outer type is (void *) or a pointer to an incomplete - record type, then the conversion is not necessary. */ - if (VOID_TYPE_P (TREE_TYPE (outer_type)) - || (AGGREGATE_TYPE_P (TREE_TYPE (outer_type)) - && TREE_CODE (TREE_TYPE (outer_type)) != ARRAY_TYPE - && (TREE_CODE (TREE_TYPE (outer_type)) - == TREE_CODE (TREE_TYPE (inner_type))) - && !COMPLETE_TYPE_P (TREE_TYPE (outer_type)))) - return true; - - /* Don't lose casts between pointers to volatile and non-volatile - qualified types. Doing so would result in changing the semantics - of later accesses. For function types the volatile qualifier - is used to indicate noreturn functions. */ - if (TREE_CODE (TREE_TYPE (outer_type)) != FUNCTION_TYPE - && TREE_CODE (TREE_TYPE (outer_type)) != METHOD_TYPE - && TREE_CODE (TREE_TYPE (inner_type)) != FUNCTION_TYPE - && TREE_CODE (TREE_TYPE (inner_type)) != METHOD_TYPE - && (TYPE_VOLATILE (TREE_TYPE (outer_type)) - != TYPE_VOLATILE (TREE_TYPE (inner_type))) - && TYPE_VOLATILE (TREE_TYPE (outer_type))) - return false; - - /* We require explicit conversions from incomplete target types. */ - if (!COMPLETE_TYPE_P (TREE_TYPE (inner_type)) - && COMPLETE_TYPE_P (TREE_TYPE (outer_type))) - return false; - - /* Do not lose casts between pointers that when dereferenced access - memory with different alias sets. */ - if (get_deref_alias_set (inner_type) != get_deref_alias_set (outer_type)) + /* Do not lose casts to function pointer types. */ + if ((TREE_CODE (TREE_TYPE (outer_type)) == FUNCTION_TYPE + || TREE_CODE (TREE_TYPE (outer_type)) == METHOD_TYPE) + && !(TREE_CODE (TREE_TYPE (inner_type)) == FUNCTION_TYPE + || TREE_CODE (TREE_TYPE (inner_type)) == METHOD_TYPE)) return false; /* We do not care for const qualification of the pointed-to types as const qualification has no semantic value to the middle-end. */ - /* Otherwise pointers/references are equivalent if their pointed - to types are effectively the same. We can strip qualifiers - on pointed-to types for further comparison, which is done in - the callee. Note we have to use true compatibility here - because addresses are subject to propagation into dereferences - and thus might get the original type exposed which is equivalent - to a reverse conversion. */ - return types_compatible_p (TREE_TYPE (outer_type), - TREE_TYPE (inner_type)); + /* Otherwise pointers/references are equivalent. */ + return true; } /* Recurse for complex types. */ @@ -1074,10 +1444,11 @@ useless_type_conversion_p (tree outer_type, tree inner_type) return false; /* A conversion to an unprototyped argument list is ok. */ - if (!TYPE_ARG_TYPES (outer_type)) + if (!prototype_p (outer_type)) return true; - /* If the argument types are compatible the conversion is useless. */ + /* If the unqualified argument types are compatible the conversion + is useless. */ if (TYPE_ARG_TYPES (outer_type) == TYPE_ARG_TYPES (inner_type)) return true; @@ -1086,8 +1457,9 @@ useless_type_conversion_p (tree outer_type, tree inner_type) outer_parm && inner_parm; outer_parm = TREE_CHAIN (outer_parm), inner_parm = TREE_CHAIN (inner_parm)) - if (!useless_type_conversion_p (TREE_VALUE (outer_parm), - TREE_VALUE (inner_parm))) + if (!useless_type_conversion_p + (TYPE_MAIN_VARIANT (TREE_VALUE (outer_parm)), + TYPE_MAIN_VARIANT (TREE_VALUE (inner_parm)))) return false; /* If there is a mismatch in the number of arguments the functions @@ -1097,7 +1469,7 @@ useless_type_conversion_p (tree outer_type, tree inner_type) /* Defer to the target if necessary. */ if (TYPE_ATTRIBUTES (inner_type) || TYPE_ATTRIBUTES (outer_type)) - return targetm.comp_type_attributes (outer_type, inner_type) != 0; + return comp_type_attributes (outer_type, inner_type) != 0; return true; } @@ -1108,7 +1480,7 @@ useless_type_conversion_p (tree outer_type, tree inner_type) else if (AGGREGATE_TYPE_P (inner_type) && TREE_CODE (inner_type) == TREE_CODE (outer_type)) return false; - + return false; } @@ -1158,7 +1530,7 @@ tree_ssa_strip_useless_type_conversions (tree exp) /* 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 @@ -1216,10 +1588,10 @@ walk_use_def_chains_1 (tree var, walk_use_def_chains_fn fn, void *data, 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 @@ -1227,7 +1599,7 @@ walk_use_def_chains_1 (tree var, walk_use_def_chains_fn fn, void *data, 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. + 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 @@ -1265,25 +1637,6 @@ walk_use_def_chains (tree var, walk_use_def_chains_fn fn, void *data, } -/* Return true if T, an SSA_NAME, has an undefined value. */ - -bool -ssa_undefined_value_p (tree t) -{ - tree var = SSA_NAME_VAR (t); - - /* Parameters get their initial value from the function entry. */ - if (TREE_CODE (var) == PARM_DECL) - return false; - - /* Hard register variables get their initial value from the ether. */ - if (TREE_CODE (var) == VAR_DECL && DECL_HARD_REGISTER (var)) - return false; - - /* The value is undefined iff its definition statement is empty. */ - return gimple_nop_p (SSA_NAME_DEF_STMT (t)); -} - /* Emit warnings for uninitialized variables. This is done in two passes. The first pass notices real uses of SSA names with undefined values. @@ -1300,10 +1653,11 @@ ssa_undefined_value_p (tree t) changed conditionally uninitialized to unconditionally uninitialized. */ /* Emit a warning for T, an SSA_NAME, being uninitialized. The exact - warning text is in MSGID and LOCUS may contain a location or be null. */ + warning text is in MSGID and LOCUS may contain a location or be null. + WC is the warning code. */ -static void -warn_uninit (tree t, const char *gmsgid, void *data) +void +warn_uninit (enum opt_code wc, tree t, const char *gmsgid, void *data) { tree var = SSA_NAME_VAR (t); gimple context = (gimple) data; @@ -1321,16 +1675,18 @@ warn_uninit (tree t, const char *gmsgid, void *data) /* Do not warn if it can be initialized outside this module. */ if (is_global_var (var)) return; - + location = (context != NULL && gimple_has_location (context)) ? gimple_location (context) : DECL_SOURCE_LOCATION (var); xloc = expand_location (location); floc = expand_location (DECL_SOURCE_LOCATION (cfun->decl)); - if (warning_at (location, OPT_Wuninitialized, gmsgid, var)) + if (warning_at (location, wc, gmsgid, var)) { TREE_NO_WARNING (var) = 1; + if (location == DECL_SOURCE_LOCATION (var)) + return; if (xloc.file != floc.file || xloc.line < floc.line || xloc.line > LOCATION_LINE (cfun->function_end_locus)) @@ -1357,8 +1713,9 @@ warn_uninitialized_var (tree *tp, int *walk_subtrees, void *data_) /* We do not care about LHS. */ if (wi->is_lhs) { - /* Except for operands of INDIRECT_REF. */ - if (!INDIRECT_REF_P (t)) + /* Except for operands of dereferences. */ + if (!INDIRECT_REF_P (t) + && TREE_CODE (t) != MEM_REF) return NULL_TREE; t = TREE_OPERAND (t, 0); } @@ -1378,7 +1735,7 @@ warn_uninitialized_var (tree *tp, int *walk_subtrees, void *data_) use_operand_p vuse; tree op; - /* If there is not gimple stmt, + /* If there is not gimple stmt, or alias information has not been computed, then we cannot check VUSE ops. */ if (data->stmt == NULL) @@ -1393,7 +1750,7 @@ warn_uninitialized_var (tree *tp, int *walk_subtrees, void *data_) return NULL_TREE; op = USE_FROM_PTR (vuse); - if (t != SSA_NAME_VAR (op) + if (t != SSA_NAME_VAR (op) || !SSA_NAME_IS_DEFAULT_DEF (op)) return NULL_TREE; /* If this is a VUSE of t and it is the default definition, @@ -1406,10 +1763,12 @@ warn_uninitialized_var (tree *tp, int *walk_subtrees, void *data_) /* We only do data flow with SSA_NAMEs, so that's all we can warn about. */ if (data->always_executed) - warn_uninit (t, "%qD is used uninitialized in this function", + warn_uninit (OPT_Wuninitialized, + t, "%qD is used uninitialized in this function", data->stmt); else if (data->warn_possibly_uninitialized) - warn_uninit (t, "%qD may be used uninitialized in this function", + warn_uninit (OPT_Wuninitialized, + t, "%qD may be used uninitialized in this function", data->stmt); *walk_subtrees = 0; break; @@ -1432,28 +1791,7 @@ warn_uninitialized_var (tree *tp, int *walk_subtrees, void *data_) return NULL_TREE; } -/* Look for inputs to PHI that are SSA_NAMEs that have empty definitions - and warn about them. */ - -static void -warn_uninitialized_phi (gimple phi) -{ - size_t i, n = gimple_phi_num_args (phi); - - /* Don't look at memory tags. */ - if (!is_gimple_reg (gimple_phi_result (phi))) - return; - - for (i = 0; i < n; ++i) - { - tree op = gimple_phi_arg_def (phi, i); - if (TREE_CODE (op) == SSA_NAME) - warn_uninit (op, "%qD may be used uninitialized in this function", - NULL); - } -} - -static unsigned int +unsigned int warn_uninitialized_vars (bool warn_possibly_uninitialized) { gimple_stmt_iterator gsi; @@ -1462,7 +1800,6 @@ warn_uninitialized_vars (bool warn_possibly_uninitialized) data.warn_possibly_uninitialized = warn_possibly_uninitialized; - calculate_dominance_info (CDI_POST_DOMINATORS); FOR_EACH_BB (bb) { @@ -1472,16 +1809,14 @@ warn_uninitialized_vars (bool warn_possibly_uninitialized) { struct walk_stmt_info wi; data.stmt = gsi_stmt (gsi); + if (is_gimple_debug (data.stmt)) + continue; memset (&wi, 0, sizeof (wi)); wi.info = &data; walk_gimple_op (gsi_stmt (gsi), warn_uninitialized_var, &wi); } } - /* Post-dominator information can not be reliably updated. Free it - after the use. */ - - free_dominance_info (CDI_POST_DOMINATORS); return 0; } @@ -1494,25 +1829,14 @@ execute_early_warn_uninitialized (void) as possible, thus don't do it here. However, without optimization we need to warn here about "may be uninitialized". */ - warn_uninitialized_vars (/*warn_possibly_uninitialized=*/!optimize); - return 0; -} - -static unsigned int -execute_late_warn_uninitialized (void) -{ - basic_block bb; - gimple_stmt_iterator gsi; + calculate_dominance_info (CDI_POST_DOMINATORS); - /* Re-do the plain uninitialized variable check, as optimization may have - straightened control flow. Do this first so that we don't accidentally - get a "may be" warning when we'd have seen an "is" warning later. */ - warn_uninitialized_vars (/*warn_possibly_uninitialized=*/1); + warn_uninitialized_vars (/*warn_possibly_uninitialized=*/!optimize); - FOR_EACH_BB (bb) - for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - warn_uninitialized_phi (gsi_stmt (gsi)); + /* Post-dominator information can not be reliably updated. Free it + after the use. */ + free_dominance_info (CDI_POST_DOMINATORS); return 0; } @@ -1526,13 +1850,13 @@ struct gimple_opt_pass pass_early_warn_uninitialized = { { GIMPLE_PASS, - NULL, /* name */ + "*early_warn_uninitialized", /* name */ gate_warn_uninitialized, /* gate */ execute_early_warn_uninitialized, /* execute */ NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ - TV_NONE, /* tv_id */ + TV_TREE_UNINIT, /* tv_id */ PROP_ssa, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ @@ -1541,37 +1865,201 @@ struct gimple_opt_pass pass_early_warn_uninitialized = } }; -struct gimple_opt_pass pass_late_warn_uninitialized = + +/* If necessary, rewrite the base of the reference tree *TP from + a MEM_REF to a plain or converted symbol. */ + +static void +maybe_rewrite_mem_ref_base (tree *tp) { - { - GIMPLE_PASS, - NULL, /* name */ - gate_warn_uninitialized, /* gate */ - execute_late_warn_uninitialized, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_NONE, /* tv_id */ - PROP_ssa, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0 /* todo_flags_finish */ - } -}; + tree sym; + + while (handled_component_p (*tp)) + tp = &TREE_OPERAND (*tp, 0); + if (TREE_CODE (*tp) == MEM_REF + && TREE_CODE (TREE_OPERAND (*tp, 0)) == ADDR_EXPR + && (sym = TREE_OPERAND (TREE_OPERAND (*tp, 0), 0)) + && DECL_P (sym) + && !TREE_ADDRESSABLE (sym) + && symbol_marked_for_renaming (sym)) + { + if (TREE_CODE (TREE_TYPE (sym)) == VECTOR_TYPE + && useless_type_conversion_p (TREE_TYPE (*tp), + TREE_TYPE (TREE_TYPE (sym))) + && multiple_of_p (sizetype, TREE_OPERAND (*tp, 1), + TYPE_SIZE_UNIT (TREE_TYPE (*tp)))) + { + *tp = build3 (BIT_FIELD_REF, TREE_TYPE (*tp), sym, + TYPE_SIZE (TREE_TYPE (*tp)), + int_const_binop (MULT_EXPR, + bitsize_int (BITS_PER_UNIT), + TREE_OPERAND (*tp, 1))); + } + else if (TREE_CODE (TREE_TYPE (sym)) == COMPLEX_TYPE + && useless_type_conversion_p (TREE_TYPE (*tp), + TREE_TYPE (TREE_TYPE (sym)))) + { + *tp = build1 (integer_zerop (TREE_OPERAND (*tp, 1)) + ? REALPART_EXPR : IMAGPART_EXPR, + TREE_TYPE (*tp), sym); + } + else if (integer_zerop (TREE_OPERAND (*tp, 1))) + { + if (!useless_type_conversion_p (TREE_TYPE (*tp), + TREE_TYPE (sym))) + *tp = build1 (VIEW_CONVERT_EXPR, + TREE_TYPE (*tp), sym); + else + *tp = sym; + } + } +} + +/* For a tree REF return its base if it is the base of a MEM_REF + that cannot be rewritten into SSA form. Otherwise return NULL_TREE. */ + +static tree +non_rewritable_mem_ref_base (tree ref) +{ + tree base = ref; + + /* A plain decl does not need it set. */ + if (DECL_P (ref)) + return NULL_TREE; + + while (handled_component_p (base)) + base = TREE_OPERAND (base, 0); + + /* But watch out for MEM_REFs we cannot lower to a + VIEW_CONVERT_EXPR or a BIT_FIELD_REF. */ + if (TREE_CODE (base) == MEM_REF + && TREE_CODE (TREE_OPERAND (base, 0)) == ADDR_EXPR) + { + tree decl = TREE_OPERAND (TREE_OPERAND (base, 0), 0); + if ((TREE_CODE (TREE_TYPE (decl)) == VECTOR_TYPE + || TREE_CODE (TREE_TYPE (decl)) == COMPLEX_TYPE) + && useless_type_conversion_p (TREE_TYPE (base), + TREE_TYPE (TREE_TYPE (decl))) + && double_int_fits_in_uhwi_p (mem_ref_offset (base)) + && double_int_ucmp + (tree_to_double_int (TYPE_SIZE_UNIT (TREE_TYPE (decl))), + mem_ref_offset (base)) == 1 + && multiple_of_p (sizetype, TREE_OPERAND (base, 1), + TYPE_SIZE_UNIT (TREE_TYPE (base)))) + return NULL_TREE; + if (DECL_P (decl) + && (!integer_zerop (TREE_OPERAND (base, 1)) + || (DECL_SIZE (decl) + != TYPE_SIZE (TREE_TYPE (base))) + || TREE_THIS_VOLATILE (decl) != TREE_THIS_VOLATILE (base))) + return decl; + } + + return NULL_TREE; +} + +/* For an lvalue tree LHS return true if it cannot be rewritten into SSA form. + Otherwise return true. */ + +static bool +non_rewritable_lvalue_p (tree lhs) +{ + /* A plain decl is always rewritable. */ + if (DECL_P (lhs)) + return false; + + /* A decl that is wrapped inside a MEM-REF that covers + it full is also rewritable. + ??? The following could be relaxed allowing component + references that do not change the access size. */ + if (TREE_CODE (lhs) == MEM_REF + && TREE_CODE (TREE_OPERAND (lhs, 0)) == ADDR_EXPR + && integer_zerop (TREE_OPERAND (lhs, 1))) + { + tree decl = TREE_OPERAND (TREE_OPERAND (lhs, 0), 0); + if (DECL_P (decl) + && DECL_SIZE (decl) == TYPE_SIZE (TREE_TYPE (lhs)) + && (TREE_THIS_VOLATILE (decl) == TREE_THIS_VOLATILE (lhs))) + return false; + } + + return true; +} + +/* When possible, clear TREE_ADDRESSABLE bit or set DECL_GIMPLE_REG_P bit and + mark the variable VAR for conversion into SSA. Return true when updating + stmts is required. */ + +static bool +maybe_optimize_var (tree var, bitmap addresses_taken, bitmap not_reg_needs) +{ + bool update_vops = false; + + /* Global Variables, result decls cannot be changed. */ + if (is_global_var (var) + || TREE_CODE (var) == RESULT_DECL + || bitmap_bit_p (addresses_taken, DECL_UID (var))) + return false; + + /* If the variable is not in the list of referenced vars then we + do not need to touch it nor can we rename it. */ + if (!referenced_var_lookup (cfun, DECL_UID (var))) + return false; + + if (TREE_ADDRESSABLE (var) + /* Do not change TREE_ADDRESSABLE if we need to preserve var as + a non-register. Otherwise we are confused and forget to + add virtual operands for it. */ + && (!is_gimple_reg_type (TREE_TYPE (var)) + || !bitmap_bit_p (not_reg_needs, DECL_UID (var)))) + { + TREE_ADDRESSABLE (var) = 0; + if (is_gimple_reg (var)) + mark_sym_for_renaming (var); + update_vops = true; + if (dump_file) + { + fprintf (dump_file, "No longer having address taken: "); + print_generic_expr (dump_file, var, 0); + fprintf (dump_file, "\n"); + } + } + + if (!DECL_GIMPLE_REG_P (var) + && !bitmap_bit_p (not_reg_needs, DECL_UID (var)) + && (TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE + || TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE) + && !TREE_THIS_VOLATILE (var) + && (TREE_CODE (var) != VAR_DECL || !DECL_HARD_REGISTER (var))) + { + DECL_GIMPLE_REG_P (var) = 1; + mark_sym_for_renaming (var); + update_vops = true; + if (dump_file) + { + fprintf (dump_file, "Now a gimple register: "); + print_generic_expr (dump_file, var, 0); + fprintf (dump_file, "\n"); + } + } + + return update_vops; +} /* Compute TREE_ADDRESSABLE and DECL_GIMPLE_REG_P for local variables. */ void -execute_update_addresses_taken (bool do_optimize) +execute_update_addresses_taken (void) { - tree var; - referenced_var_iterator rvi; gimple_stmt_iterator gsi; basic_block bb; bitmap addresses_taken = BITMAP_ALLOC (NULL); bitmap not_reg_needs = BITMAP_ALLOC (NULL); bool update_vops = false; + tree var; + unsigned i; + + timevar_push (TV_ADDRESS_TAKEN); /* Collect into ADDRESSES_TAKEN all variables whose address is taken within the function body. */ @@ -1581,6 +2069,7 @@ execute_update_addresses_taken (bool do_optimize) { gimple stmt = gsi_stmt (gsi); enum gimple_code code = gimple_code (stmt); + tree decl; /* Note all addresses taken by the stmt. */ gimple_ior_addresses_taken (addresses_taken, stmt); @@ -1590,20 +2079,59 @@ execute_update_addresses_taken (bool do_optimize) if (code == GIMPLE_ASSIGN || code == GIMPLE_CALL) { tree lhs = gimple_get_lhs (stmt); - - /* We may not rewrite TMR_SYMBOL to SSA. */ - if (lhs && TREE_CODE (lhs) == TARGET_MEM_REF - && TMR_SYMBOL (lhs)) - bitmap_set_bit (not_reg_needs, DECL_UID (TMR_SYMBOL (lhs))); - - /* A plain decl does not need it set. */ - else if (lhs && handled_component_p (lhs)) - { - var = get_base_address (lhs); - if (DECL_P (var)) - bitmap_set_bit (not_reg_needs, DECL_UID (var)); + if (lhs + && TREE_CODE (lhs) != SSA_NAME + && non_rewritable_lvalue_p (lhs)) + { + decl = get_base_address (lhs); + if (DECL_P (decl)) + bitmap_set_bit (not_reg_needs, DECL_UID (decl)); } } + + if (gimple_assign_single_p (stmt)) + { + tree rhs = gimple_assign_rhs1 (stmt); + if ((decl = non_rewritable_mem_ref_base (rhs))) + bitmap_set_bit (not_reg_needs, DECL_UID (decl)); + } + + else if (code == GIMPLE_CALL) + { + for (i = 0; i < gimple_call_num_args (stmt); ++i) + { + tree arg = gimple_call_arg (stmt, i); + if ((decl = non_rewritable_mem_ref_base (arg))) + bitmap_set_bit (not_reg_needs, DECL_UID (decl)); + } + } + + else if (code == GIMPLE_ASM) + { + for (i = 0; i < gimple_asm_noutputs (stmt); ++i) + { + tree link = gimple_asm_output_op (stmt, i); + tree lhs = TREE_VALUE (link); + if (TREE_CODE (lhs) != SSA_NAME) + { + decl = get_base_address (lhs); + if (DECL_P (decl) + && (non_rewritable_lvalue_p (lhs) + /* We cannot move required conversions from + the lhs to the rhs in asm statements, so + require we do not need any. */ + || !useless_type_conversion_p + (TREE_TYPE (lhs), TREE_TYPE (decl)))) + bitmap_set_bit (not_reg_needs, DECL_UID (decl)); + } + } + for (i = 0; i < gimple_asm_ninputs (stmt); ++i) + { + tree link = gimple_asm_input_op (stmt, i); + if ((decl = non_rewritable_mem_ref_base (TREE_VALUE (link)))) + bitmap_set_bit (not_reg_needs, DECL_UID (decl)); + } + } } for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) @@ -1622,66 +2150,108 @@ execute_update_addresses_taken (bool do_optimize) } } - /* When possible, clear ADDRESSABLE bit or set the REGISTER bit - and mark variable for conversion into SSA. */ - if (optimize && do_optimize) - FOR_EACH_REFERENCED_VAR (var, rvi) - { - /* Global Variables, result decls cannot be changed. */ - if (is_global_var (var) - || TREE_CODE (var) == RESULT_DECL - || bitmap_bit_p (addresses_taken, DECL_UID (var))) - continue; - - if (TREE_ADDRESSABLE (var) - /* Do not change TREE_ADDRESSABLE if we need to preserve var as - a non-register. Otherwise we are confused and forget to - add virtual operands for it. */ - && (!is_gimple_reg_type (TREE_TYPE (var)) - || !bitmap_bit_p (not_reg_needs, DECL_UID (var)))) + /* We cannot iterate over all referenced vars because that can contain + unused vars from BLOCK trees, which causes code generation differences + for -g vs. -g0. */ + for (var = DECL_ARGUMENTS (cfun->decl); var; var = DECL_CHAIN (var)) + update_vops |= maybe_optimize_var (var, addresses_taken, not_reg_needs); + + FOR_EACH_VEC_ELT (tree, cfun->local_decls, i, var) + update_vops |= maybe_optimize_var (var, addresses_taken, not_reg_needs); + + /* Operand caches need to be recomputed for operands referencing the updated + variables. */ + if (update_vops) + { + FOR_EACH_BB (bb) + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { - TREE_ADDRESSABLE (var) = 0; - if (is_gimple_reg (var)) - mark_sym_for_renaming (var); - update_vops = true; - if (dump_file) + gimple stmt = gsi_stmt (gsi); + + /* Re-write TARGET_MEM_REFs of symbols we want to + rewrite into SSA form. */ + if (gimple_assign_single_p (stmt)) { - fprintf (dump_file, "No longer having address taken "); - print_generic_expr (dump_file, var, 0); - fprintf (dump_file, "\n"); + tree lhs = gimple_assign_lhs (stmt); + tree rhs, *rhsp = gimple_assign_rhs1_ptr (stmt); + tree sym; + + /* We shouldn't have any fancy wrapping of + component-refs on the LHS, but look through + VIEW_CONVERT_EXPRs as that is easy. */ + while (TREE_CODE (lhs) == VIEW_CONVERT_EXPR) + lhs = TREE_OPERAND (lhs, 0); + if (TREE_CODE (lhs) == MEM_REF + && TREE_CODE (TREE_OPERAND (lhs, 0)) == ADDR_EXPR + && integer_zerop (TREE_OPERAND (lhs, 1)) + && (sym = TREE_OPERAND (TREE_OPERAND (lhs, 0), 0)) + && DECL_P (sym) + && !TREE_ADDRESSABLE (sym) + && symbol_marked_for_renaming (sym)) + lhs = sym; + else + lhs = gimple_assign_lhs (stmt); + + /* Rewrite the RHS and make sure the resulting assignment + is validly typed. */ + maybe_rewrite_mem_ref_base (rhsp); + rhs = gimple_assign_rhs1 (stmt); + if (gimple_assign_lhs (stmt) != lhs + && !useless_type_conversion_p (TREE_TYPE (lhs), + TREE_TYPE (rhs))) + rhs = fold_build1 (VIEW_CONVERT_EXPR, + TREE_TYPE (lhs), rhs); + + if (gimple_assign_lhs (stmt) != lhs) + gimple_assign_set_lhs (stmt, lhs); + + if (gimple_assign_rhs1 (stmt) != rhs) + { + gimple_stmt_iterator gsi = gsi_for_stmt (stmt); + gimple_assign_set_rhs_from_tree (&gsi, rhs); + } } - } - if (!DECL_GIMPLE_REG_P (var) - && !bitmap_bit_p (not_reg_needs, DECL_UID (var)) - && (TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE - || TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE) - && !TREE_THIS_VOLATILE (var) - && (TREE_CODE (var) != VAR_DECL || !DECL_HARD_REGISTER (var))) - { - DECL_GIMPLE_REG_P (var) = 1; - mark_sym_for_renaming (var); - update_vops = true; - if (dump_file) + + else if (gimple_code (stmt) == GIMPLE_CALL) { - fprintf (dump_file, "Decl is now a gimple register "); - print_generic_expr (dump_file, var, 0); - fprintf (dump_file, "\n"); + unsigned i; + for (i = 0; i < gimple_call_num_args (stmt); ++i) + { + tree *argp = gimple_call_arg_ptr (stmt, i); + maybe_rewrite_mem_ref_base (argp); + } } - } - } - /* Operand caches needs to be recomputed for operands referencing the updated - variables. */ - if (update_vops) - { - FOR_EACH_BB (bb) - for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - { - gimple stmt = gsi_stmt (gsi); + else if (gimple_code (stmt) == GIMPLE_ASM) + { + unsigned i; + for (i = 0; i < gimple_asm_noutputs (stmt); ++i) + { + tree link = gimple_asm_output_op (stmt, i); + maybe_rewrite_mem_ref_base (&TREE_VALUE (link)); + } + for (i = 0; i < gimple_asm_ninputs (stmt); ++i) + { + tree link = gimple_asm_input_op (stmt, i); + maybe_rewrite_mem_ref_base (&TREE_VALUE (link)); + } + } - if (gimple_references_memory_p (stmt)) - update_stmt (stmt); - } + else if (gimple_debug_bind_p (stmt) + && gimple_debug_bind_has_value_p (stmt)) + { + tree *valuep = gimple_debug_bind_get_value_ptr (stmt); + tree decl; + maybe_rewrite_mem_ref_base (valuep); + decl = non_rewritable_mem_ref_base (*valuep); + if (decl && symbol_marked_for_renaming (decl)) + gimple_debug_bind_reset_value (stmt); + } + + if (gimple_references_memory_p (stmt) + || is_gimple_debug (stmt)) + update_stmt (stmt); + } /* Update SSA form here, we are called as non-pass as well. */ update_ssa (TODO_update_ssa); @@ -1689,6 +2259,7 @@ execute_update_addresses_taken (bool do_optimize) BITMAP_FREE (not_reg_needs); BITMAP_FREE (addresses_taken); + timevar_pop (TV_ADDRESS_TAKEN); } struct gimple_opt_pass pass_update_address_taken = @@ -1701,7 +2272,7 @@ struct gimple_opt_pass pass_update_address_taken = NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ - TV_NONE, /* tv_id */ + TV_ADDRESS_TAKEN, /* tv_id */ PROP_ssa, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */