/* Dead store elimination
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
It may help to think of this as first moving the earlier store to
the point immediately before the later store. Again, the single
- use of the virtual defintion and the post-dominance relationship
+ use of the virtual definition and the post-dominance relationship
ensure that such movement would be safe. Clearly if there are
back to back stores, then the second is redundant.
static void dse_record_phis (struct dom_walk_data *, basic_block);
static void dse_finalize_block (struct dom_walk_data *, basic_block);
static void fix_phi_uses (tree, tree);
-static void fix_stmt_vdefs (tree, tree);
+static void fix_stmt_v_may_defs (tree, tree);
static void record_voperand_set (bitmap, bitmap *, unsigned int);
+static unsigned max_stmt_uid; /* Maximal uid of a statement. Uids to phi
+ nodes are assigned using the versions of
+ ssa names they define. */
+
+/* Returns uid of statement STMT. */
+
+static unsigned
+get_stmt_uid (tree stmt)
+{
+ if (TREE_CODE (stmt) == PHI_NODE)
+ return SSA_NAME_VERSION (PHI_RESULT (stmt)) + max_stmt_uid;
+
+ return stmt_ann (stmt)->uid;
+}
+
/* Function indicating whether we ought to include information for 'var'
when calculating immediate uses. For this pass we only want use
information for virtual variables. */
}
-/* Replace uses in PHI which match VDEF_RESULTs in STMT with the
- corresponding VDEF_OP in STMT. */
+/* Replace uses in PHI which match V_MAY_DEF_RESULTs in STMT with the
+ corresponding V_MAY_DEF_OP in STMT. */
static void
fix_phi_uses (tree phi, tree stmt)
{
- stmt_ann_t ann = stmt_ann (stmt);
- vdef_optype vdefs;
- unsigned int i;
- int j;
+ use_operand_p use_p;
+ def_operand_p def_p;
+ ssa_op_iter iter;
+ int i;
get_stmt_operands (stmt);
- vdefs = VDEF_OPS (ann);
- /* Walk each VDEF in STMT. */
- for (i = 0; i < NUM_VDEFS (vdefs); i++)
+ FOR_EACH_SSA_MAYDEF_OPERAND (def_p, use_p, stmt, iter)
{
- tree vdef = VDEF_RESULT (vdefs, i);
-
- /* Find any uses in the PHI which match VDEF and replace
- them with the appropriate VDEF_OP. */
- for (j = 0; j < PHI_NUM_ARGS (phi); j++)
- if (vdef == PHI_ARG_DEF (phi, j))
- PHI_ARG_DEF (phi, j) = VDEF_OP (vdefs, i);
+ tree v_may_def = DEF_FROM_PTR (def_p);
+ tree v_may_use = USE_FROM_PTR (use_p);
+
+ /* Find any uses in the PHI which match V_MAY_DEF and replace
+ them with the appropriate V_MAY_DEF_OP. */
+ for (i = 0; i < PHI_NUM_ARGS (phi); i++)
+ if (v_may_def == PHI_ARG_DEF (phi, i))
+ SET_PHI_ARG_DEF (phi, i, v_may_use);
}
}
-/* Replace the VDEF_OPs in STMT1 which match VDEF_RESULTs in STMT2 with
- the appropriate VDEF_OPs from STMT2. */
+/* Replace the V_MAY_DEF_OPs in STMT1 which match V_MAY_DEF_RESULTs
+ in STMT2 with the appropriate V_MAY_DEF_OPs from STMT2. */
static void
-fix_stmt_vdefs (tree stmt1, tree stmt2)
+fix_stmt_v_may_defs (tree stmt1, tree stmt2)
{
- stmt_ann_t ann1 = stmt_ann (stmt1);
- stmt_ann_t ann2 = stmt_ann (stmt2);
- vdef_optype vdefs1;
- vdef_optype vdefs2;
- unsigned int i, j;
+ bool found = false;
+ ssa_op_iter iter1;
+ ssa_op_iter iter2;
+ use_operand_p use1_p, use2_p;
+ def_operand_p def1_p, def2_p;
get_stmt_operands (stmt1);
get_stmt_operands (stmt2);
- vdefs1 = VDEF_OPS (ann1);
- vdefs2 = VDEF_OPS (ann2);
- /* Walk each VDEF_OP in stmt1. */
- for (i = 0; i < NUM_VDEFS (vdefs1); i++)
+ /* Walk each V_MAY_DEF_OP in stmt1. */
+ FOR_EACH_SSA_MAYDEF_OPERAND (def1_p, use1_p, stmt1, iter1)
{
- tree vdef1 = VDEF_OP (vdefs1, i);
+ tree use = USE_FROM_PTR (use1_p);
- /* Find the appropriate VDEF_RESULT in STMT2. */
- for (j = 0; j < NUM_VDEFS (vdefs2); j++)
+ /* Find the appropriate V_MAY_DEF_RESULT in STMT2. */
+ FOR_EACH_SSA_MAYDEF_OPERAND (def2_p, use2_p, stmt2, iter2)
{
- if (vdef1 == VDEF_RESULT (vdefs2, j))
+ tree def = DEF_FROM_PTR (def2_p);
+ if (use == def)
{
/* Update. */
- *VDEF_OP_PTR (vdefs1, i) = VDEF_OP (vdefs2, j);
- break;
- }
+ SET_USE (use1_p, USE_FROM_PTR (use2_p));
+ found = true;
+ break;
+ }
}
-#ifdef ENABLE_CHECKING
- /* If we did not find a corresponding VDEF_RESULT, then something
- has gone terribly wrong. */
- if (j == NUM_VDEFS (vdefs2))
- abort ();
-#endif
-
+ /* If we did not find a corresponding V_MAY_DEF_RESULT,
+ then something has gone terribly wrong. */
+ gcc_assert (found);
}
}
struct dse_global_data *dse_gd = walk_data->global_data;
tree stmt = bsi_stmt (bsi);
stmt_ann_t ann = stmt_ann (stmt);
- vdef_optype vdefs;
+ v_may_def_optype v_may_defs;
get_stmt_operands (stmt);
- vdefs = VDEF_OPS (ann);
+ v_may_defs = V_MAY_DEF_OPS (ann);
/* If this statement has no virtual uses, then there is nothing
to do. */
- if (NUM_VDEFS (vdefs) == 0)
+ if (NUM_V_MAY_DEFS (v_may_defs) == 0)
+ return;
+
+ /* We know we have virtual definitions. If this is a MODIFY_EXPR that's
+ not also a function call, then record it into our table. */
+ if (get_call_expr_in (stmt))
+ return;
+
+ if (ann->has_volatile_ops)
return;
- /* We know we have virtual definitions. If this is a MODIFY_EXPR, then
- record it into our table. */
- if (TREE_CODE (stmt) == MODIFY_EXPR
- && TREE_CODE (TREE_OPERAND (stmt, 1)) != CALL_EXPR)
+ if (TREE_CODE (stmt) == MODIFY_EXPR)
{
dataflow_t df = get_immediate_uses (stmt);
unsigned int num_uses = num_immediate_uses (df);
tree use;
tree skipped_phi;
-
/* If there are no uses then there is nothing left to do. */
if (num_uses == 0)
{
represents the only use of this store.
Note this does not handle the case where the store has
- multiple VDEFs which all reach a set of PHI nodes in the
+ multiple V_MAY_DEFs which all reach a set of PHI nodes in the
same block. */
while (num_uses == 1
&& TREE_CODE (use) == PHI_NODE
- && bitmap_bit_p (dse_gd->stores, stmt_ann (use)->uid))
+ && bitmap_bit_p (dse_gd->stores, get_stmt_uid (use)))
{
/* Record the first PHI we skip so that we can fix its
uses if we find that STMT is a dead store. */
/* If we have precisely one immediate use at this point, then we may
have found redundant store. */
if (num_uses == 1
- && bitmap_bit_p (dse_gd->stores, stmt_ann (use)->uid)
+ && bitmap_bit_p (dse_gd->stores, get_stmt_uid (use))
&& operand_equal_p (TREE_OPERAND (stmt, 0),
TREE_OPERAND (use, 0), 0))
{
if (skipped_phi)
fix_phi_uses (skipped_phi, stmt);
else
- fix_stmt_vdefs (use, stmt);
+ fix_stmt_v_may_defs (use, stmt);
if (dump_file && (dump_flags & TDF_DETAILS))
{
This allows us to cascade dead stores. */
redirect_immediate_uses (stmt, skipped_phi ? skipped_phi : use);
+ /* Be sure to remove any dataflow information attached to
+ this statement. */
+ free_df_for_stmt (stmt);
+
+ /* And release any SSA_NAMEs set in this statement back to the
+ SSA_NAME manager. */
+ release_defs (stmt);
+
/* Finally remove the dead store. */
bsi_remove (&bsi);
}
struct dse_global_data *dse_gd = walk_data->global_data;
tree phi;
- for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
+ for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
if (need_imm_uses_for (PHI_RESULT (phi)))
record_voperand_set (dse_gd->stores,
&bd->stores,
- get_stmt_ann (phi)->uid);
+ get_stmt_uid (phi));
}
static void
struct dse_global_data *dse_gd = walk_data->global_data;
bitmap stores = dse_gd->stores;
unsigned int i;
+ bitmap_iterator bi;
/* Unwind the stores noted in this basic block. */
if (bd->stores)
- EXECUTE_IF_SET_IN_BITMAP (bd->stores, 0, i, bitmap_clear_bit (stores, i););
+ EXECUTE_IF_SET_IN_BITMAP (bd->stores, 0, i, bi)
+ {
+ bitmap_clear_bit (stores, i);
+ }
}
static void
{
struct dom_walk_data walk_data;
struct dse_global_data dse_gd;
- unsigned int uid = 0;
basic_block bb;
/* Create a UID for each statement in the function. Ordering of the
UIDs is not important for this pass. */
+ max_stmt_uid = 0;
FOR_EACH_BB (bb)
{
block_stmt_iterator bsi;
- tree phi;
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
- stmt_ann (bsi_stmt (bsi))->uid = uid++;
-
- for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
- stmt_ann (phi)->uid = uid++;
+ stmt_ann (bsi_stmt (bsi))->uid = max_stmt_uid++;
}
/* We might consider making this a property of each pass so that it
NULL, /* next */
0, /* static_pass_number */
TV_TREE_DSE, /* tv_id */
- PROP_cfg | PROP_ssa, /* properties_required */
+ PROP_cfg | PROP_ssa
+ | PROP_alias, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_func | TODO_ggc_collect /* todo_flags_finish */
- | TODO_verify_ssa
+ | TODO_verify_ssa,
+ 0 /* letter */
};