diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index 11b1938216e..d10a276daf2 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -52,6 +52,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-ssa-dce.h" #include "tree-cfgcleanup.h" #include "alias.h" +#include "graph.h" /* Even though this file is called tree-ssa-pre.c, we actually implement a bit more than just PRE here. All of them piggy-back @@ -500,7 +501,6 @@ typedef struct bb_bitmap_sets #define BB_MAY_NOTRETURN(BB) ((bb_value_sets_t) ((BB)->aux))->contains_may_not_return_call #define BB_LIVE_VOP_ON_EXIT(BB) ((bb_value_sets_t) ((BB)->aux))->vop_on_exit - /* This structure is used to keep track of statistics on what optimization PRE was able to perform. */ static struct @@ -2434,6 +2434,25 @@ compute_antic (void) that didn't turn out to be necessary. */ static bitmap inserted_exprs; +struct pre_expr_block_d : nofree_ptr_hash +{ + pre_expr expr; + bitmap blocks; + + /* hash_table support. */ + static inline hashval_t hash(const pre_expr_block_d *x) + { + return pre_expr_d::hash (x->expr); + } + + static inline int equal(const pre_expr_block_d *x1, const pre_expr_block_d *x2) + { + return pre_expr_d::equal (x1->expr, x2->expr); + } +}; + +static hash_table * expr_to_blocks; + /* The actual worker for create_component_ref_by_pieces. */ static tree @@ -3549,6 +3568,15 @@ do_hoist_insertion (basic_block block) continue; } + pre_expr_block_d x; + x.expr = expr; + pre_expr_block_d **slot = expr_to_blocks->find_slot (&x, NO_INSERT); + if (slot) + { + gcc_assert (!bitmap_empty_p ((*slot)->blocks)); + continue; + } + /* OK, we should hoist this value. Perform the transformation. */ pre_stats.hoist_insert++; if (dump_file && (dump_flags & TDF_DETAILS)) @@ -3678,6 +3706,40 @@ insert (void) statistics_histogram_event (cfun, "insert iterations", num_iterations); } +static void +add_expr_to_blocks (pre_expr expr, basic_block block) +{ + pre_expr_block_d x; + x.expr = expr; + + edge e; + edge_iterator ei; + bool loop_exit = false; + + if (single_succ_p (block)) + return; + + FOR_EACH_EDGE (e, ei, block->succs) + if (block->loop_father != e->dest->loop_father) + { + loop_exit = true; + break; + } + + if (!loop_exit) + return; + + pre_expr_block_d **slot = expr_to_blocks->find_slot (&x, INSERT); + if (!*slot) + { + *slot = XNEW (struct pre_expr_block_d); + (*slot)->expr = expr; + (*slot)->blocks = BITMAP_ALLOC (NULL); + } + + + bitmap_set_bit ((*slot)->blocks, block->index); +} /* Compute the AVAIL set for all basic blocks. @@ -3711,6 +3773,7 @@ compute_avail (void) e = get_or_alloc_expr_for_name (name); add_to_value (get_expr_value_id (e), e); + add_expr_to_blocks (e, ENTRY_BLOCK_PTR_FOR_FN (cfun)); bitmap_insert_into_set (TMP_GEN (ENTRY_BLOCK_PTR_FOR_FN (cfun)), e); bitmap_value_insert_into_set (AVAIL_OUT (ENTRY_BLOCK_PTR_FOR_FN (cfun)), e); @@ -3771,6 +3834,7 @@ compute_avail (void) pre_expr e = get_or_alloc_expr_for_name (result); add_to_value (get_expr_value_id (e), e); + add_expr_to_blocks (e, block); bitmap_value_insert_into_set (AVAIL_OUT (block), e); bitmap_insert_into_set (PHI_GEN (block), e); } @@ -3808,6 +3872,7 @@ compute_avail (void) pre_expr e = get_or_alloc_expr_for_name (op); add_to_value (get_expr_value_id (e), e); + add_expr_to_blocks (e, block); bitmap_insert_into_set (TMP_GEN (block), e); bitmap_value_insert_into_set (AVAIL_OUT (block), e); } @@ -3862,6 +3927,7 @@ compute_avail (void) PRE_EXPR_REFERENCE (result) = ref; get_or_alloc_expression_id (result); + add_expr_to_blocks (result, block); add_to_value (get_expr_value_id (result), result); bitmap_value_insert_into_set (EXP_GEN (block), result); } @@ -4019,6 +4085,7 @@ compute_avail (void) get_or_alloc_expression_id (result); add_to_value (get_expr_value_id (result), result); + add_expr_to_blocks (result, block); bitmap_value_insert_into_set (EXP_GEN (block), result); continue; } @@ -4077,6 +4144,7 @@ init_pre (void) bitmap_obstack_initialize (&grand_bitmap_obstack); phi_translate_table = new hash_table (5110); expression_to_id = new hash_table (num_ssa_names * 3); + expr_to_blocks = new hash_table (num_ssa_names * 3); FOR_ALL_BB_FN (bb, cfun) { EXP_GEN (bb) = bitmap_set_new ();