/* Dead store elimination
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
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. */
static void
fix_phi_uses (tree phi, tree stmt)
{
- stmt_ann_t ann = stmt_ann (stmt);
- v_may_def_optype v_may_defs;
- 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);
- v_may_defs = V_MAY_DEF_OPS (ann);
- /* Walk each V_MAY_DEF in STMT. */
- for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++)
+ FOR_EACH_SSA_MAYDEF_OPERAND (def_p, use_p, stmt, iter)
{
- tree v_may_def = V_MAY_DEF_RESULT (v_may_defs, 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 (j = 0; j < PHI_NUM_ARGS (phi); j++)
- if (v_may_def == PHI_ARG_DEF (phi, j))
- SET_PHI_ARG_DEF (phi, j, V_MAY_DEF_OP (v_may_defs, i));
+ 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);
}
}
static void
fix_stmt_v_may_defs (tree stmt1, tree stmt2)
{
- stmt_ann_t ann1 = stmt_ann (stmt1);
- stmt_ann_t ann2 = stmt_ann (stmt2);
- v_may_def_optype v_may_defs1;
- v_may_def_optype v_may_defs2;
- 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);
- v_may_defs1 = V_MAY_DEF_OPS (ann1);
- v_may_defs2 = V_MAY_DEF_OPS (ann2);
/* Walk each V_MAY_DEF_OP in stmt1. */
- for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs1); i++)
+ FOR_EACH_SSA_MAYDEF_OPERAND (def1_p, use1_p, stmt1, iter1)
{
- tree v_may_def1 = V_MAY_DEF_OP (v_may_defs1, i);
+ tree use = USE_FROM_PTR (use1_p);
/* Find the appropriate V_MAY_DEF_RESULT in STMT2. */
- for (j = 0; j < NUM_V_MAY_DEFS (v_may_defs2); j++)
+ FOR_EACH_SSA_MAYDEF_OPERAND (def2_p, use2_p, stmt2, iter2)
{
- if (v_may_def1 == V_MAY_DEF_RESULT (v_may_defs2, j))
+ tree def = DEF_FROM_PTR (def2_p);
+ if (use == def)
{
/* Update. */
- SET_V_MAY_DEF_OP (v_may_defs1, i, V_MAY_DEF_OP (v_may_defs2, j));
- break;
- }
+ SET_USE (use1_p, USE_FROM_PTR (use2_p));
+ found = true;
+ break;
+ }
}
-#ifdef ENABLE_CHECKING
- /* If we did not find a corresponding V_MAY_DEF_RESULT, then something
- has gone terribly wrong. */
- if (j == NUM_V_MAY_DEFS (v_may_defs2))
- abort ();
-#endif
-
+ /* If we did not find a corresponding V_MAY_DEF_RESULT,
+ then something has gone terribly wrong. */
+ gcc_assert (found);
}
}
not also a function call, then record it into our table. */
if (get_call_expr_in (stmt))
return;
+
+ if (ann->has_volatile_ops)
+ return;
+
if (TREE_CODE (stmt) == MODIFY_EXPR)
{
dataflow_t df = get_immediate_uses (stmt);
tree use;
tree skipped_phi;
-
/* If there are no uses then there is nothing left to do. */
if (num_uses == 0)
{
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))
{
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);
}
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 = PHI_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
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_func | TODO_ggc_collect /* todo_flags_finish */
- | TODO_verify_ssa
+ | TODO_verify_ssa,
+ 0 /* letter */
};