X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree-ssa-dse.c;h=17ed1297affb9b66abd2b6c13a6e2cafa287e465;hb=7c568de5f7d7fb8852c9d1808236f2a8c2d45ecd;hp=4277a3aa7c687d062d0a866f0448c8c1c17e5372;hpb=67ce556b47830dd825524e8370969b814c355216;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c index 4277a3aa7c6..17ed1297aff 100644 --- a/gcc/tree-ssa-dse.c +++ b/gcc/tree-ssa-dse.c @@ -83,8 +83,15 @@ struct dse_block_local_data bitmap stores; }; +/* Basic blocks of the potentially dead store and the following + store, for memory_address_same. */ +struct address_walk_data +{ + basic_block store1_bb, store2_bb; +}; + static bool gate_dse (void); -static void tree_ssa_dse (void); +static unsigned int tree_ssa_dse (void); static void dse_initialize_block_local_data (struct dom_walk_data *, basic_block, bool); @@ -145,6 +152,64 @@ dse_initialize_block_local_data (struct dom_walk_data *walk_data, } } +/* Helper function for memory_address_same via walk_tree. Returns + non-NULL if it finds an SSA_NAME which is part of the address, + such that the definition of the SSA_NAME post-dominates the store + we want to delete but not the store that we believe makes it + redundant. This indicates that the address may change between + the two stores. */ + +static tree +memory_ssa_name_same (tree *expr_p, int *walk_subtrees ATTRIBUTE_UNUSED, + void *data) +{ + struct address_walk_data *walk_data = data; + tree expr = *expr_p; + tree def_stmt; + basic_block def_bb; + + if (TREE_CODE (expr) != SSA_NAME) + return NULL_TREE; + + /* If we've found a default definition, then there's no problem. Both + stores will post-dominate it. And def_bb will be NULL. */ + if (expr == default_def (SSA_NAME_VAR (expr))) + return NULL_TREE; + + def_stmt = SSA_NAME_DEF_STMT (expr); + def_bb = bb_for_stmt (def_stmt); + + /* DEF_STMT must dominate both stores. So if it is in the same + basic block as one, it does not post-dominate that store. */ + if (walk_data->store1_bb != def_bb + && dominated_by_p (CDI_POST_DOMINATORS, walk_data->store1_bb, def_bb)) + { + if (walk_data->store2_bb == def_bb + || !dominated_by_p (CDI_POST_DOMINATORS, walk_data->store2_bb, + def_bb)) + /* Return non-NULL to stop the walk. */ + return def_stmt; + } + + return NULL_TREE; +} + +/* Return TRUE if the destination memory address in STORE1 and STORE2 + might be modified after STORE1, before control reaches STORE2. */ + +static bool +memory_address_same (tree store1, tree store2) +{ + struct address_walk_data walk_data; + + walk_data.store1_bb = bb_for_stmt (store1); + walk_data.store2_bb = bb_for_stmt (store2); + + return (walk_tree (&TREE_OPERAND (store1, 0), memory_ssa_name_same, + &walk_data, NULL) + == NULL); +} + /* Attempt to eliminate dead stores in the statement referenced by BSI. A dead store is a store into a memory location which will later be @@ -244,6 +309,15 @@ dse_optimize_stmt (struct dom_walk_data *walk_data, && TREE_CODE (use_stmt) == PHI_NODE && bitmap_bit_p (dse_gd->stores, get_stmt_uid (use_stmt))) { + /* A PHI node can both define and use the same SSA_NAME if + the PHI is at the top of a loop and the PHI_RESULT is + a loop invariant and copies have not been fully propagated. + + The safe thing to do is exit assuming no optimization is + possible. */ + if (SSA_NAME_DEF_STMT (PHI_RESULT (use_stmt)) == use_stmt) + return; + /* Skip past this PHI and loop again in case we had a PHI chain. */ if (single_imm_use (PHI_RESULT (use_stmt), &use_p, &use_stmt)) @@ -251,20 +325,18 @@ dse_optimize_stmt (struct dom_walk_data *walk_data, } /* If we have precisely one immediate use at this point, then we may - have found redundant store. */ + have found redundant store. Make sure that the stores are to + the same memory location. This includes checking that any + SSA-form variables in the address will have the same values. */ if (use_p != NULL_USE_OPERAND_P && bitmap_bit_p (dse_gd->stores, get_stmt_uid (use_stmt)) && operand_equal_p (TREE_OPERAND (stmt, 0), - TREE_OPERAND (use_stmt, 0), 0)) + TREE_OPERAND (use_stmt, 0), 0) + && memory_address_same (stmt, use_stmt)) { - tree def; - ssa_op_iter iter; - /* Make sure we propagate the ABNORMAL bit setting. */ if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (USE_FROM_PTR (first_use_p))) SSA_NAME_OCCURS_IN_ABNORMAL_PHI (usevar) = 1; - /* Then we need to fix the operand of the consuming stmt. */ - SET_USE (first_use_p, usevar); if (dump_file && (dump_flags & TDF_DETAILS)) { @@ -272,15 +344,14 @@ dse_optimize_stmt (struct dom_walk_data *walk_data, print_generic_expr (dump_file, bsi_stmt (bsi), dump_flags); fprintf (dump_file, "'\n"); } - + /* Then we need to fix the operand of the consuming stmt. */ + FOR_EACH_SSA_MUST_AND_MAY_DEF_OPERAND (var1, var2, stmt, op_iter) + { + single_imm_use (DEF_FROM_PTR (var1), &use_p, &temp); + SET_USE (use_p, USE_FROM_PTR (var2)); + } /* Remove the dead store. */ - bsi_remove (&bsi); - - /* The virtual defs for the dead statement will need to be - updated. Since these names are going to disappear, - FUD chains for uses downstream need to be updated. */ - FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_VIRTUAL_DEFS) - mark_sym_for_renaming (SSA_NAME_VAR (def)); + bsi_remove (&bsi, true); /* And release any SSA_NAMEs set in this statement back to the SSA_NAME manager. */ @@ -327,7 +398,7 @@ dse_finalize_block (struct dom_walk_data *walk_data, } } -static void +static unsigned int tree_ssa_dse (void) { struct dom_walk_data walk_data; @@ -384,6 +455,7 @@ tree_ssa_dse (void) /* For now, just wipe the post-dominator information. */ free_dominance_info (CDI_POST_DOMINATORS); + return 0; } static bool @@ -408,7 +480,6 @@ struct tree_opt_pass pass_dse = { 0, /* todo_flags_start */ TODO_dump_func | TODO_ggc_collect - | TODO_update_ssa | TODO_verify_ssa, /* todo_flags_finish */ 0 /* letter */ };