-/* A very simple dead store pass eliminating write only local variables.
- The pass does not require alias information and thus can be run before
- inlining to quickly eliminate artifacts of some common C++ constructs. */
-
-static unsigned int
-execute_simple_dse (void)
-{
- gimple_stmt_iterator gsi;
- basic_block bb;
- bitmap variables_loaded = BITMAP_ALLOC (NULL);
- unsigned int todo = 0;
-
- /* Collect into VARIABLES LOADED all variables that are read in function
- body. */
- FOR_EACH_BB (bb)
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-
- if (gimple_loaded_syms (gsi_stmt (gsi)))
- bitmap_ior_into (variables_loaded,
- gimple_loaded_syms (gsi_stmt (gsi)));
-
- /* Look for statements writing into the write only variables.
- And try to remove them. */
-
- FOR_EACH_BB (bb)
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
- {
- gimple stmt = gsi_stmt (gsi);
- tree op;
- bool removed = false;
- ssa_op_iter iter;
- tree size;
-
- if (is_gimple_assign (stmt)
- && AGGREGATE_TYPE_P (TREE_TYPE (gimple_assign_lhs (stmt)))
- && (size = lang_hooks.expr_size (gimple_assign_lhs (stmt)))
- && integer_zerop (size))
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, " Deleted zero-sized store '");
- print_gimple_stmt (dump_file, stmt, 0, dump_flags);
- fprintf (dump_file, "'\n");
- }
- removed = true;
- gsi_remove (&gsi, true);
- todo |= TODO_cleanup_cfg;
- }
- else if (gimple_stored_syms (stmt)
- && !bitmap_empty_p (gimple_stored_syms (stmt))
- && (is_gimple_assign (stmt)
- || (is_gimple_call (stmt)
- && gimple_call_lhs (stmt)))
- && !bitmap_intersect_p (gimple_stored_syms (stmt),
- variables_loaded))
- {
- unsigned int i;
- bitmap_iterator bi;
- bool dead = true;
-
- /* See if STMT only stores to write-only variables and
- verify that there are no volatile operands. tree-ssa-operands
- sets has_volatile_ops flag for all statements involving
- reads and writes when aliases are not built to prevent passes
- from removing them as dead. The flag thus has no use for us
- and we need to look into all operands. */
-
- EXECUTE_IF_SET_IN_BITMAP (gimple_stored_syms (stmt), 0, i, bi)
- {
- tree var = referenced_var_lookup (i);
- if (TREE_ADDRESSABLE (var)
- || is_global_var (var)
- || TREE_THIS_VOLATILE (var))
- dead = false;
- }
-
- if (dead && gimple_loaded_syms (stmt))
- EXECUTE_IF_SET_IN_BITMAP (gimple_loaded_syms (stmt), 0, i, bi)
- if (TREE_THIS_VOLATILE (referenced_var_lookup (i)))
- dead = false;
-
- if (dead)
- FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_ALL_OPERANDS)
- if (TREE_THIS_VOLATILE (op))
- dead = false;
-
- /* Look for possible occurrence var = indirect_ref (...) where
- indirect_ref itself is volatile. */
-
- if (dead && is_gimple_assign (stmt)
- && TREE_THIS_VOLATILE (gimple_assign_rhs1 (stmt)))
- dead = false;
-
- if (dead)
- {
- /* When LHS of var = call (); is dead, simplify it into
- call (); saving one operand. */
- if (is_gimple_call (stmt)
- && gimple_has_side_effects (stmt))
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Deleted LHS of call: ");
- print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
- fprintf (dump_file, "\n");
- }
- push_stmt_changes (gsi_stmt_ptr (&gsi));
- gimple_call_set_lhs (stmt, NULL);
- pop_stmt_changes (gsi_stmt_ptr (&gsi));
- }
- else
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, " Deleted dead store '");
- print_gimple_stmt (dump_file, stmt, 0, dump_flags);
- fprintf (dump_file, "'\n");
- }
- removed = true;
- gsi_remove (&gsi, true);
- todo |= TODO_cleanup_cfg;
- }
- todo |= TODO_remove_unused_locals | TODO_ggc_collect;
- }
- }
- if (!removed)
- gsi_next (&gsi);
- }
- BITMAP_FREE (variables_loaded);
- return todo;
-}
-
-struct gimple_opt_pass pass_simple_dse =
-{
- {
- GIMPLE_PASS,
- "sdse", /* name */
- NULL, /* gate */
- execute_simple_dse, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- 0, /* tv_id */
- PROP_ssa, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- TODO_dump_func /* todo_flags_finish */
- }
-};