/* Dead store elimination
- Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation,
+ Inc.
This file is part of GCC.
static void dse_finalize_block (struct dom_walk_data *, basic_block);
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 SSA_NAME_VERSION (PHI_RESULT (stmt)) + gimple_stmt_max_uid (cfun);
- return stmt_ann (stmt)->uid;
+ return gimple_stmt_uid (stmt);
}
/* Set bit UID in bitmaps GLOBAL and *LOCAL, creating *LOCAL as needed. */
}
/* Return true if there is a stmt that kills the lhs of STMT and is in the
- virtual def-use chain of STMT without a use inbetween the kill and STMT.
+ virtual def-use chain of STMT without a use in between the kill and STMT.
Returns false if no such stmt is found.
*FIRST_USE_P is set to the first use of the single virtual def of
STMT. *USE_P is set to the vop killed by *USE_STMT. */
vuse_vec_p vv;
tree defvar = NULL_TREE, temp;
tree prev_defvar = NULL_TREE;
- stmt_ann_t ann = stmt_ann (stmt);
/* We want to verify that each virtual definition in STMT has
precisely one use and that all the virtual definitions are
gcc_assert (*use_p != NULL_USE_OPERAND_P);
*first_use_p = *use_p;
+ /* ??? If we hit a PHI_NODE we could skip to the PHI_RESULT uses.
+ Don't bother to do that for now. */
+ if (TREE_CODE (temp) == PHI_NODE)
+ {
+ fail = true;
+ break;
+ }
+
/* In the case of memory partitions, we may get:
# MPT.764_162 = VDEF <MPT.764_161(D)>
if (fail)
{
- record_voperand_set (dse_gd->stores, &bd->stores, ann->uid);
+ record_voperand_set (dse_gd->stores, &bd->stores, gimple_stmt_uid (stmt));
return false;
}
- /* Skip through any PHI nodes we have already seen if the PHI
- 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 same block. */
- while (*use_p != NULL_USE_OPERAND_P
- && 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 false;
-
- /* Skip past this PHI and loop again in case we had a PHI
- chain. */
- single_imm_use (PHI_RESULT (*use_stmt), use_p, use_stmt);
- }
-
return true;
}
memory location. */
if (!get_kill_of_stmt_lhs (stmt, &first_use_p, &use_p, &use_stmt))
{
- record_voperand_set (dse_gd->stores, &bd->stores, ann->uid);
+ record_voperand_set (dse_gd->stores, &bd->stores, gimple_stmt_uid (stmt));
return;
}
}
vuse_vec_p vv;
tree stmt_lhs;
- if (LOADED_SYMS (use_stmt))
+ /* If use_stmt is or might be a nop assignment, e.g. for
+ struct { ... } S a, b, *p; ...
+ b = a; b = b;
+ or
+ b = a; b = *p; where p might be &b,
+ or
+ *p = a; *p = b; where p might be &b,
+ or
+ *p = *u; *p = *v; where p might be v, then USE_STMT
+ acts as a use as well as definition, so store in STMT
+ is not dead. */
+ if (LOADED_SYMS (use_stmt)
+ && bitmap_intersect_p (LOADED_SYMS (use_stmt),
+ STORED_SYMS (use_stmt)))
{
- tree use_base
- = get_base_address (GIMPLE_STMT_OPERAND (use_stmt, 0));
- /* If use_stmt is or might be a nop assignment, e.g. for
- struct { ... } S a, b, *p; ...
- b = a; b = b;
- or
- b = a; b = *p; where p might be &b, then USE_STMT
- acts as a use as well as definition, so store in STMT
- is not dead. */
- if (TREE_CODE (use_base) == VAR_DECL
- && bitmap_bit_p (LOADED_SYMS (use_stmt),
- DECL_UID (use_base)))
- {
- record_voperand_set (dse_gd->stores, &bd->stores, ann->uid);
- return;
- }
+ record_voperand_set (dse_gd->stores, &bd->stores, ann->uid);
+ return;
}
if (dump_file && (dump_flags & TDF_DETAILS))
release_defs (stmt);
}
- record_voperand_set (dse_gd->stores, &bd->stores, ann->uid);
+ record_voperand_set (dse_gd->stores, &bd->stores, gimple_stmt_uid (stmt));
}
}
{
struct dom_walk_data walk_data;
struct dse_global_data dse_gd;
- 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;
-
- for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
- stmt_ann (bsi_stmt (bsi))->uid = max_stmt_uid++;
- }
+ renumber_gimple_stmt_uids ();
/* We might consider making this a property of each pass so that it
can be [re]computed on an as-needed basis. Particularly since
return flag_tree_dse != 0;
}
-struct tree_opt_pass pass_dse = {
+struct gimple_opt_pass pass_dse =
+{
+ {
+ GIMPLE_PASS,
"dse", /* name */
gate_dse, /* gate */
tree_ssa_dse, /* execute */
0, /* todo_flags_start */
TODO_dump_func
| TODO_ggc_collect
- | TODO_verify_ssa, /* todo_flags_finish */
- 0 /* letter */
+ | TODO_verify_ssa /* todo_flags_finish */
+ }
};
/* A very simple dead store pass eliminating write only local variables.
if (TREE_THIS_VOLATILE (op))
dead = false;
- /* Look for possible occurence var = indirect_ref (...) where
+ /* Look for possible occurrence var = indirect_ref (...) where
indirect_ref itself is volatile. */
if (dead && TREE_THIS_VOLATILE (GIMPLE_STMT_OPERAND (stmt, 1)))
return todo;
}
-struct tree_opt_pass pass_simple_dse =
+struct gimple_opt_pass pass_simple_dse =
{
+ {
+ GIMPLE_PASS,
"sdse", /* name */
NULL, /* gate */
execute_simple_dse, /* execute */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_dump_func, /* todo_flags_finish */
- 0 /* letter */
+ TODO_dump_func /* todo_flags_finish */
+ }
};