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);
}
}
+/* 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
&& 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))
}
/* 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))
{
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. */
}
}
-static void
+static unsigned int
tree_ssa_dse (void)
{
struct dom_walk_data walk_data;
/* For now, just wipe the post-dominator information. */
free_dominance_info (CDI_POST_DOMINATORS);
+ return 0;
}
static bool
0, /* todo_flags_start */
TODO_dump_func
| TODO_ggc_collect
- | TODO_update_ssa
| TODO_verify_ssa, /* todo_flags_finish */
0 /* letter */
};