From d7621d3c741403a604eab08b66658d71f3452e8d Mon Sep 17 00:00:00 2001 From: Zdenek Dvorak Date: Thu, 17 Jun 2004 19:47:47 +0200 Subject: re PR tree-optimization/15991 (phi nodes with identical arguments still remain at t50.tailc) PR tree-optimization/15991 * tree-cfg.c (tree_block_label): Export. * tree-flow-inline.h (bsi_after_labels): New function. * tree-flow.h (bsi_after_labels, tree_block_label): Declare. * tree-ssa.c (propagate_into_addr): New function. (replace_immediate_uses): Handle propagation of pointer constants. (raise_value): Do not restrict propagation of pointer constants. * tree-ssanames.c (duplicate_ssa_name): New function. * tree.h (duplicate_ssa_name): Declare. From-SVN: r83297 --- gcc/ChangeLog | 12 ++++++++ gcc/tree-cfg.c | 3 +- gcc/tree-flow-inline.h | 47 +++++++++++++++++++++++++++++ gcc/tree-flow.h | 2 ++ gcc/tree-ssa.c | 82 +++++++++++++++++++++++++++++++++++++------------- gcc/tree-ssanames.c | 25 +++++++++++++++ gcc/tree.h | 1 + 7 files changed, 149 insertions(+), 23 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7d206e9..3e237d1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2004-06-17 Zdenek Dvorak + + PR tree-optimization/15991 + * tree-cfg.c (tree_block_label): Export. + * tree-flow-inline.h (bsi_after_labels): New function. + * tree-flow.h (bsi_after_labels, tree_block_label): Declare. + * tree-ssa.c (propagate_into_addr): New function. + (replace_immediate_uses): Handle propagation of pointer constants. + (raise_value): Do not restrict propagation of pointer constants. + * tree-ssanames.c (duplicate_ssa_name): New function. + * tree.h (duplicate_ssa_name): Declare. + 2004-06-17 David Ayers * c-parse.in: Unify Objective-C token names. diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 0624ade..4b3ca40 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -74,7 +74,6 @@ static void free_blocks_annotations (void); static void clear_blocks_annotations (void); static void make_blocks (tree); static void factor_computed_gotos (void); -static tree tree_block_label (basic_block bb); /* Edges. */ static void make_edges (void); @@ -3973,7 +3972,7 @@ thread_jumps (void) /* Return a non-special label in the head of basic block BLOCK. Create one if it doesn't exist. */ -static tree +tree tree_block_label (basic_block bb) { block_stmt_iterator i, s = bsi_start (bb); diff --git a/gcc/tree-flow-inline.h b/gcc/tree-flow-inline.h index 4fe44ef..c47ba09 100644 --- a/gcc/tree-flow-inline.h +++ b/gcc/tree-flow-inline.h @@ -629,6 +629,53 @@ bsi_start (basic_block bb) return bsi; } +/* Return a block statement iterator that points to the last label in + block BB. */ + +static inline block_stmt_iterator +bsi_after_labels (basic_block bb) +{ + block_stmt_iterator bsi; + tree_stmt_iterator next; + + bsi.bb = bb; + + if (!bb->stmt_list) + { +#ifdef ENABLE_CHECKING + if (bb->index >= 0) + abort (); +#endif + bsi.tsi.ptr = NULL; + bsi.tsi.container = NULL; + return bsi; + } + + bsi.tsi = tsi_start (bb->stmt_list); + if (tsi_end_p (bsi.tsi)) + return bsi; + + /* Ensure that there are some labels. The rationale is that we want + to insert after the bsi that is returned, and these insertions should + be placed at the start of the basic block. This would not work if the + first statement was not label; rather fail here than enable the user + proceed in wrong way. */ + if (TREE_CODE (tsi_stmt (bsi.tsi)) != LABEL_EXPR) + abort (); + + next = bsi.tsi; + tsi_next (&next); + + while (!tsi_end_p (next) + && TREE_CODE (tsi_stmt (next)) == LABEL_EXPR) + { + bsi.tsi = next; + tsi_next (&next); + } + + return bsi; +} + /* Return a block statement iterator that points to the end of basic block BB. */ static inline block_stmt_iterator diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index 4f3a4a6..d9d0b1e 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -416,6 +416,7 @@ typedef struct { static inline block_stmt_iterator bsi_start (basic_block); static inline block_stmt_iterator bsi_last (basic_block); +static inline block_stmt_iterator bsi_after_labels (basic_block); static inline bool bsi_end_p (block_stmt_iterator); static inline void bsi_next (block_stmt_iterator *); static inline void bsi_prev (block_stmt_iterator *); @@ -486,6 +487,7 @@ extern void notice_special_calls (tree); extern void clear_special_calls (void); extern void compute_dominance_frontiers (bitmap *); extern void verify_stmts (void); +extern tree tree_block_label (basic_block bb); extern void extract_true_false_edges_from_block (basic_block, edge *, edge *); /* In tree-pretty-print.c. */ diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index 175ce48..7d9e64d 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -705,6 +705,52 @@ 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. */ + +static void +propagate_into_addr (tree stmt, tree var, 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; + addr_var = TREE_OPERAND (repl, 0); + + while (TREE_CODE (*x) == ARRAY_REF + || TREE_CODE (*x) == COMPONENT_REF + || TREE_CODE (*x) == BIT_FIELD_REF) + x = &TREE_OPERAND (*x, 0); + + if (TREE_CODE (*x) != INDIRECT_REF + || TREE_OPERAND (*x, 0) != var) + return; + + modify_stmt (stmt); + if (TREE_TYPE (*x) == TREE_TYPE (addr_var)) + { + *x = addr_var; + mark_new_vars_to_rename (stmt, vars_to_rename); + return; + } + + /* 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 (var, 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); +} /* Replaces immediate uses of VAR by REPL. */ @@ -718,6 +764,7 @@ replace_immediate_uses (tree var, tree repl) dataflow_t df; tree stmt; stmt_ann_t ann; + bool mark_new_vars; df = get_immediate_uses (SSA_NAME_DEF_STMT (var)); n = num_immediate_uses (df); @@ -742,12 +789,22 @@ replace_immediate_uses (tree var, tree repl) } get_stmt_operands (stmt); + mark_new_vars = false; if (is_gimple_reg (SSA_NAME_VAR (var))) { + if (TREE_CODE (stmt) == MODIFY_EXPR) + { + propagate_into_addr (stmt, var, &TREE_OPERAND (stmt, 0), repl); + propagate_into_addr (stmt, var, &TREE_OPERAND (stmt, 1), repl); + } + uses = USE_OPS (ann); for (j = 0; j < (int) NUM_USES (uses); j++) if (USE_OP (uses, j) == var) - propagate_value (USE_OP_PTR (uses, j), repl); + { + propagate_value (USE_OP_PTR (uses, j), repl); + mark_new_vars = POINTER_TYPE_P (TREE_TYPE (repl)); + } } else { @@ -762,15 +819,15 @@ replace_immediate_uses (tree var, tree repl) propagate_value (V_MAY_DEF_OP_PTR (v_may_defs, j), repl); } - modify_stmt (stmt); - /* 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 (POINTER_TYPE_P (TREE_TYPE (repl))) + if (mark_new_vars) mark_new_vars_to_rename (stmt, vars_to_rename); + else + modify_stmt (stmt); } } @@ -788,23 +845,6 @@ raise_value (tree phi, tree val, tree *eq_to) if (eq_to[ver] == var) return; - switch (TREE_CODE (val)) - { - case SSA_NAME: - case REAL_CST: - case COMPLEX_CST: - break; - case INTEGER_CST: - if (TREE_CODE (TREE_TYPE (var)) != POINTER_TYPE) - break; - - default: - /* Do not propagate pointer constants. This might require folding - things like *&foo and rewriting the ssa, which is not worth the - trouble. */ - val = var; - } - if (eq_to[ver]) { if (operand_equal_p (eq_to[ver], val, 0)) diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c index 6a0fda6..d498270 100644 --- a/gcc/tree-ssanames.c +++ b/gcc/tree-ssanames.c @@ -191,4 +191,29 @@ release_ssa_name (tree var) } } +/* Creates a duplicate of a ssa name NAME defined in statement STMT. */ + +tree +duplicate_ssa_name (tree name, tree stmt) +{ + tree new_name = make_ssa_name (SSA_NAME_VAR (name), stmt); + struct ptr_info_def *old_ptr_info = SSA_NAME_PTR_INFO (name); + struct ptr_info_def *new_ptr_info; + + if (!old_ptr_info) + return new_name; + + new_ptr_info = ggc_alloc (sizeof (struct ptr_info_def)); + *new_ptr_info = *old_ptr_info; + + if (old_ptr_info->pt_vars) + { + new_ptr_info->pt_vars = BITMAP_GGC_ALLOC (); + bitmap_copy (new_ptr_info->pt_vars, old_ptr_info->pt_vars); + } + + SSA_NAME_PTR_INFO (new_name) = new_ptr_info; + return new_name; +} + #include "gt-tree-ssanames.h" diff --git a/gcc/tree.h b/gcc/tree.h index db32362..1a0f854 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2537,6 +2537,7 @@ extern void phinodes_print_statistics (void); extern void init_ssanames (void); extern void fini_ssanames (void); extern tree make_ssa_name (tree, tree); +extern tree duplicate_ssa_name (tree, tree); extern void release_ssa_name (tree); #ifdef GATHER_STATISTICS extern void ssanames_print_statistics (void); -- cgit v1.1