diff options
author | Jan Hubicka <jh@suse.cz> | 2007-09-07 13:28:35 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2007-09-07 11:28:35 +0000 |
commit | 201b2eadc44a3217be14bed57b979dc4b01a5990 (patch) | |
tree | a9b189174aab2e413f3eb87f3545535fef231f0c | |
parent | f85138bc84767bdbf1e405461578432629df11a7 (diff) | |
download | gcc-201b2eadc44a3217be14bed57b979dc4b01a5990.zip gcc-201b2eadc44a3217be14bed57b979dc4b01a5990.tar.gz gcc-201b2eadc44a3217be14bed57b979dc4b01a5990.tar.bz2 |
passes.c (init_optimization_passes): Add simple dce and addressable passes.
* passes.c (init_optimization_passes): Add simple dce and addressable
passes.
* tree-ssa.c (execute_update_addresses_taken): New function.
(pass_update_address_taken): New.
* tree-ssa-dse.c (execute_simple_dse): New function.
(pass_simple_dse): New.
* tree-pass.h (pass_simple_dse, pass_update_address_taken): Declare.
From-SVN: r128239
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/passes.c | 4 | ||||
-rw-r--r-- | gcc/tree-pass.h | 2 | ||||
-rw-r--r-- | gcc/tree-ssa-dse.c | 134 | ||||
-rw-r--r-- | gcc/tree-ssa.c | 96 |
5 files changed, 246 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bf2bc14..be49cf5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2007-09-07 Jan Hubicka <jh@suse.cz> + + * passes.c (init_optimization_passes): Add simple dce and addressable + passes. + * tree-ssa.c (execute_update_addresses_taken): New function. + (pass_update_address_taken): New. + * tree-ssa-dse.c (execute_simple_dse): New function. + (pass_simple_dse): New. + * tree-pass.h (pass_simple_dse, pass_update_address_taken): Declare. + 2007-09-07 Tobias Burnus <burnus@net-b.de> PR middle-end/33321 diff --git a/gcc/passes.c b/gcc/passes.c index 29ec8e2..1b88414 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -523,10 +523,14 @@ init_optimization_passes (void) NEXT_PASS (pass_rename_ssa_copies); NEXT_PASS (pass_ccp); NEXT_PASS (pass_forwprop); + NEXT_PASS (pass_update_address_taken); + NEXT_PASS (pass_simple_dse); NEXT_PASS (pass_sra_early); NEXT_PASS (pass_copy_prop); NEXT_PASS (pass_merge_phi); NEXT_PASS (pass_dce); + NEXT_PASS (pass_update_address_taken); + NEXT_PASS (pass_simple_dse); NEXT_PASS (pass_tail_recursion); NEXT_PASS (pass_profile); NEXT_PASS (pass_release_ssa_names); diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index a7de717..19bda7c 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -306,6 +306,7 @@ extern struct tree_opt_pass pass_forwprop; extern struct tree_opt_pass pass_phiprop; extern struct tree_opt_pass pass_tree_ifcombine; extern struct tree_opt_pass pass_dse; +extern struct tree_opt_pass pass_simple_dse; extern struct tree_opt_pass pass_nrv; extern struct tree_opt_pass pass_mark_used_blocks; extern struct tree_opt_pass pass_rename_ssa_copies; @@ -445,6 +446,7 @@ extern struct tree_opt_pass pass_early_inline; extern struct tree_opt_pass pass_inline_parameters; extern struct tree_opt_pass pass_apply_inline; extern struct tree_opt_pass pass_all_early_optimizations; +extern struct tree_opt_pass pass_update_address_taken; /* The root of the compilation pass tree, once constructed. */ extern struct tree_opt_pass *all_passes, *all_ipa_passes, *all_lowering_passes; diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c index 68fa445..4416f7d 100644 --- a/gcc/tree-ssa-dse.c +++ b/gcc/tree-ssa-dse.c @@ -918,3 +918,137 @@ struct tree_opt_pass pass_dse = { | TODO_verify_ssa, /* todo_flags_finish */ 0 /* letter */ }; + +/* 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) +{ + block_stmt_iterator bsi; + 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 (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) + if (LOADED_SYMS (bsi_stmt (bsi))) + bitmap_ior_into (variables_loaded, + LOADED_SYMS (bsi_stmt (bsi))); + + /* Look for statements writting into the write only variables. + And try to remove them. */ + + FOR_EACH_BB (bb) + for (bsi = bsi_start (bb); !bsi_end_p (bsi);) + { + tree stmt = bsi_stmt (bsi), op; + bool removed = false; + ssa_op_iter iter; + + if (STORED_SYMS (stmt) && TREE_CODE (stmt) == GIMPLE_MODIFY_STMT + && TREE_CODE (stmt) != RETURN_EXPR + && !bitmap_intersect_p (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 (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 && LOADED_SYMS (stmt)) + EXECUTE_IF_SET_IN_BITMAP (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 occurence var = indirect_ref (...) where + indirect_ref itself is volatile. */ + + if (dead && TREE_THIS_VOLATILE (GIMPLE_STMT_OPERAND (stmt, 1))) + dead = false; + + if (dead) + { + tree call = get_call_expr_in (stmt); + + /* When LHS of var = call (); is dead, simplify it into + call (); saving one operand. */ + if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT + && call + && TREE_SIDE_EFFECTS (call)) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Deleted LHS of call: "); + print_generic_stmt (dump_file, stmt, TDF_SLIM); + fprintf (dump_file, "\n"); + } + push_stmt_changes (bsi_stmt_ptr (bsi)); + TREE_BLOCK (call) = TREE_BLOCK (stmt); + bsi_replace (&bsi, call, false); + maybe_clean_or_replace_eh_stmt (stmt, call); + mark_symbols_for_renaming (call); + pop_stmt_changes (bsi_stmt_ptr (bsi)); + } + else + { + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, " Deleted dead store '"); + print_generic_expr (dump_file, stmt, dump_flags); + fprintf (dump_file, "'\n"); + } + removed = true; + bsi_remove (&bsi, true); + todo |= TODO_cleanup_cfg; + } + todo |= TODO_remove_unused_locals | TODO_ggc_collect; + } + } + if (!removed) + bsi_next (&bsi); + } + BITMAP_FREE (variables_loaded); + return todo; +} + +struct tree_opt_pass pass_simple_dse = +{ + "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 */ + 0 /* letter */ +}; diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index 633e446..9723afb 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -1378,3 +1378,99 @@ struct tree_opt_pass pass_late_warn_uninitialized = 0, /* todo_flags_finish */ 0 /* letter */ }; + +/* Compute TREE_ADDRESSABLE for local variables. */ + +static unsigned int +execute_update_addresses_taken (void) +{ + tree var; + referenced_var_iterator rvi; + block_stmt_iterator bsi; + basic_block bb; + bitmap addresses_taken = BITMAP_ALLOC (NULL); + bitmap vars_updated = BITMAP_ALLOC (NULL); + bool update_vops; + tree phi; + + /* Collect into ADDRESSES_TAKEN all variables whose address is taken within + the function body. */ + FOR_EACH_BB (bb) + { + for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) + { + stmt_ann_t s_ann = stmt_ann (bsi_stmt (bsi)); + + if (s_ann->addresses_taken) + bitmap_ior_into (addresses_taken, s_ann->addresses_taken); + } + for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi)) + { + unsigned i, phi_num_args = PHI_NUM_ARGS (phi); + for (i = 0; i < phi_num_args; i++) + { + tree op = PHI_ARG_DEF (phi, i), var; + if (TREE_CODE (op) == ADDR_EXPR + && (var = get_base_address (TREE_OPERAND (op, 0))) != NULL_TREE + && DECL_P (var)) + bitmap_set_bit (addresses_taken, DECL_UID (var)); + } + } + } + + /* When possible, clear ADDRESSABLE bit and mark variable for conversion into + SSA. */ + FOR_EACH_REFERENCED_VAR (var, rvi) + if (!is_global_var (var) + && TREE_CODE (var) != RESULT_DECL + && TREE_ADDRESSABLE (var) + && !bitmap_bit_p (addresses_taken, DECL_UID (var))) + { + TREE_ADDRESSABLE (var) = 0; + if (is_gimple_reg (var)) + mark_sym_for_renaming (var); + update_vops = true; + bitmap_set_bit (vars_updated, DECL_UID (var)); + if (dump_file) + { + fprintf (dump_file, "No longer having address taken "); + print_generic_expr (dump_file, var, 0); + fprintf (dump_file, "\n"); + } + } + + /* Operand caches needs to be recomputed for operands referencing the updated + variables. */ + if (update_vops) + FOR_EACH_BB (bb) + for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) + { + tree stmt = bsi_stmt (bsi); + + if ((LOADED_SYMS (stmt) + && bitmap_intersect_p (LOADED_SYMS (stmt), vars_updated)) + || (STORED_SYMS (stmt) + && bitmap_intersect_p (STORED_SYMS (stmt), vars_updated))) + update_stmt (stmt); + } + BITMAP_FREE (addresses_taken); + BITMAP_FREE (vars_updated); + return 0; +} + +struct tree_opt_pass pass_update_address_taken = +{ + "addressables", /* name */ + NULL, /* gate */ + execute_update_addresses_taken, /* 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_update_ssa, /* todo_flags_finish */ + 0 /* letter */ +}; |