In propagate_tree_value and replace_exp_1 operating on SSA form are the only users of unsave_expr_now where really unsharing matters. Thus, use unshare_expr and remove unsave_expr_now.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied. Richard. 2013-04-09 Richard Biener <rguent...@suse.de> * tree.h (unsave_expr_now): Remove. * tree-inline.c (mark_local_for_remap_r): Remove. (unsave_expr_1): Likewise. (unsave_r): Likewise. (unsave_expr_now): Likewise. * tree-ssa-copy.c (replace_exp_1): Use unshare_expr. (propagate_tree_value): Likewise. Index: gcc/tree.h =================================================================== *** gcc/tree.h (revision 197574) --- gcc/tree.h (working copy) *************** extern void indent_to (FILE *, int); *** 6018,6024 **** extern bool debug_find_tree (tree, tree); /* This is in tree-inline.c since the routine uses data structures from the inliner. */ - extern tree unsave_expr_now (tree); extern tree build_duplicate_type (tree); /* In calls.c */ --- 6018,6023 ---- Index: gcc/tree-inline.c =================================================================== *** gcc/tree-inline.c (revision 197574) --- gcc/tree-inline.c (working copy) *************** eni_weights eni_time_weights; *** 114,122 **** static tree declare_return_variable (copy_body_data *, tree, tree, basic_block); static void remap_block (tree *, copy_body_data *); static void copy_bind_expr (tree *, int *, copy_body_data *); - static tree mark_local_for_remap_r (tree *, int *, void *); - static void unsave_expr_1 (tree); - static tree unsave_r (tree *, int *, void *); static void declare_inline_vars (tree, tree); static void remap_save_expr (tree *, void *, int *); static void prepend_lexical_block (tree current_block, tree new_block); --- 114,119 ---- *************** remap_save_expr (tree *tp, void *st_, in *** 4465,4601 **** *tp = t; } - /* Called via walk_tree. If *TP points to a DECL_STMT for a local label, - copies the declaration and enters it in the splay_tree in DATA (which is - really an `copy_body_data *'). */ - - static tree - mark_local_for_remap_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data) - { - copy_body_data *id = (copy_body_data *) data; - - /* Don't walk into types. */ - if (TYPE_P (*tp)) - *walk_subtrees = 0; - - else if (TREE_CODE (*tp) == LABEL_EXPR) - { - tree decl = TREE_OPERAND (*tp, 0); - - /* Copy the decl and remember the copy. */ - insert_decl_map (id, decl, id->copy_decl (decl, id)); - } - - return NULL_TREE; - } - - /* Perform any modifications to EXPR required when it is unsaved. Does - not recurse into EXPR's subtrees. */ - - static void - unsave_expr_1 (tree expr) - { - switch (TREE_CODE (expr)) - { - case TARGET_EXPR: - /* Don't mess with a TARGET_EXPR that hasn't been expanded. - It's OK for this to happen if it was part of a subtree that - isn't immediately expanded, such as operand 2 of another - TARGET_EXPR. */ - if (TREE_OPERAND (expr, 1)) - break; - - TREE_OPERAND (expr, 1) = TREE_OPERAND (expr, 3); - TREE_OPERAND (expr, 3) = NULL_TREE; - break; - - default: - break; - } - } - - /* Called via walk_tree when an expression is unsaved. Using the - splay_tree pointed to by ST (which is really a `splay_tree'), - remaps all local declarations to appropriate replacements. */ - - static tree - unsave_r (tree *tp, int *walk_subtrees, void *data) - { - copy_body_data *id = (copy_body_data *) data; - struct pointer_map_t *st = id->decl_map; - tree *n; - - /* Only a local declaration (variable or label). */ - if ((TREE_CODE (*tp) == VAR_DECL && !TREE_STATIC (*tp)) - || TREE_CODE (*tp) == LABEL_DECL) - { - /* Lookup the declaration. */ - n = (tree *) pointer_map_contains (st, *tp); - - /* If it's there, remap it. */ - if (n) - *tp = *n; - } - - else if (TREE_CODE (*tp) == STATEMENT_LIST) - gcc_unreachable (); - else if (TREE_CODE (*tp) == BIND_EXPR) - copy_bind_expr (tp, walk_subtrees, id); - else if (TREE_CODE (*tp) == SAVE_EXPR - || TREE_CODE (*tp) == TARGET_EXPR) - remap_save_expr (tp, st, walk_subtrees); - else - { - copy_tree_r (tp, walk_subtrees, NULL); - - /* Do whatever unsaving is required. */ - unsave_expr_1 (*tp); - } - - /* Keep iterating. */ - return NULL_TREE; - } - - /* Copies everything in EXPR and replaces variables, labels - and SAVE_EXPRs local to EXPR. */ - - tree - unsave_expr_now (tree expr) - { - copy_body_data id; - - /* There's nothing to do for NULL_TREE. */ - if (expr == 0) - return expr; - - /* Set up ID. */ - memset (&id, 0, sizeof (id)); - id.src_fn = current_function_decl; - id.dst_fn = current_function_decl; - id.decl_map = pointer_map_create (); - id.debug_map = NULL; - - id.copy_decl = copy_decl_no_change; - id.transform_call_graph_edges = CB_CGE_DUPLICATE; - id.transform_new_cfg = false; - id.transform_return_to_modify = false; - id.transform_lang_insert_block = NULL; - - /* Walk the tree once to find local labels. */ - walk_tree_without_duplicates (&expr, mark_local_for_remap_r, &id); - - /* Walk the tree again, copying, remapping, and unsaving. */ - walk_tree (&expr, unsave_r, &id, NULL); - - /* Clean up. */ - pointer_map_destroy (id.decl_map); - if (id.debug_map) - pointer_map_destroy (id.debug_map); - - return expr; - } - /* Called via walk_gimple_seq. If *GSIP points to a GIMPLE_LABEL for a local label, copies the declaration and enters it in the splay_tree in DATA (which is really a 'copy_body_data *'. */ --- 4466,4471 ---- Index: gcc/tree-ssa-copy.c =================================================================== *** gcc/tree-ssa-copy.c (revision 197574) --- gcc/tree-ssa-copy.c (working copy) *************** replace_exp_1 (use_operand_p op_p, tree *** 163,169 **** if (TREE_CODE (val) == SSA_NAME) SET_USE (op_p, val); else ! SET_USE (op_p, unsave_expr_now (val)); } --- 163,169 ---- if (TREE_CODE (val) == SSA_NAME) SET_USE (op_p, val); else ! SET_USE (op_p, unshare_expr (val)); } *************** propagate_tree_value (tree *op_p, tree v *** 214,220 **** if (TREE_CODE (val) == SSA_NAME) *op_p = val; else ! *op_p = unsave_expr_now (val); } --- 214,220 ---- if (TREE_CODE (val) == SSA_NAME) *op_p = val; else ! *op_p = unshare_expr (val); }