diff options
author | Marc Glisse <marc.glisse@inria.fr> | 2014-08-21 11:32:21 +0200 |
---|---|---|
committer | Marc Glisse <glisse@gcc.gnu.org> | 2014-08-21 09:32:21 +0000 |
commit | 8cb65b3725f0c31a3ea5d5b8de37eacba55462f3 (patch) | |
tree | 773cf046c0dfd55437a213c2c0d6c24b378ad71e /gcc/tree-ssa-dse.c | |
parent | 31879c2cc7b5d8f302b5020de41b9439ef764b65 (diff) | |
download | gcc-8cb65b3725f0c31a3ea5d5b8de37eacba55462f3.zip gcc-8cb65b3725f0c31a3ea5d5b8de37eacba55462f3.tar.gz gcc-8cb65b3725f0c31a3ea5d5b8de37eacba55462f3.tar.bz2 |
re PR tree-optimization/62112 (Optimize out malloc when block is unused or write-only)
2014-08-21 Marc Glisse <marc.glisse@inria.fr>
PR tree-optimization/62112
gcc/
* gimple-iterator.c (gsi_replace): Return whether EH cleanup is needed.
* gimple-iterator.h (gsi_replace): Return bool.
* tree-ssa-alias.c (ref_may_alias_global_p_1): New helper, code
moved from ref_may_alias_global_p.
(ref_may_alias_global_p, refs_may_alias_p, ref_maybe_used_by_stmt_p):
New overloads.
(ref_maybe_used_by_call_p): Take ao_ref* instead of tree.
(stmt_kills_ref_p_1): Rename...
(stmt_kills_ref_p): ... to this.
* tree-ssa-alias.h (ref_may_alias_global_p, ref_maybe_used_by_stmt_p,
stmt_kills_ref_p): Declare.
* tree-ssa-dse.c (dse_possible_dead_store_p): New argument, use it.
Move the self-assignment case...
(dse_optimize_stmt): ... here. Handle builtin calls. Remove dead code.
gcc/testsuite/
* gcc.dg/tree-ssa/pr62112-1.c: New file.
* gcc.dg/tree-ssa/pr62112-2.c: Likewise.
* gcc.c-torture/execute/pr35472.c: Add noclone attribute.
* gcc.c-torture/execute/20071219-1.c: Likewise.
From-SVN: r214262
Diffstat (limited to 'gcc/tree-ssa-dse.c')
-rw-r--r-- | gcc/tree-ssa-dse.c | 108 |
1 files changed, 69 insertions, 39 deletions
diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c index c22c8db..6e6204a 100644 --- a/gcc/tree-ssa-dse.c +++ b/gcc/tree-ssa-dse.c @@ -82,25 +82,18 @@ static bitmap need_eh_cleanup; /* A helper of dse_optimize_stmt. - Given a GIMPLE_ASSIGN in STMT, find a candidate statement *USE_STMT that - may prove STMT to be dead. + Given a GIMPLE_ASSIGN in STMT that writes to REF, find a candidate + statement *USE_STMT that may prove STMT to be dead. Return TRUE if the above conditions are met, otherwise FALSE. */ static bool -dse_possible_dead_store_p (gimple stmt, gimple *use_stmt) +dse_possible_dead_store_p (ao_ref *ref, gimple stmt, gimple *use_stmt) { gimple temp; unsigned cnt = 0; *use_stmt = NULL; - /* Self-assignments are zombies. */ - if (operand_equal_p (gimple_assign_rhs1 (stmt), gimple_assign_lhs (stmt), 0)) - { - *use_stmt = stmt; - return true; - } - /* Find the first dominated statement that clobbers (part of) the memory stmt stores to with no intermediate statement that may use part of the memory stmt stores. That is, find a store that may @@ -164,8 +157,7 @@ dse_possible_dead_store_p (gimple stmt, gimple *use_stmt) temp = use_stmt; } /* If the statement is a use the store is not dead. */ - else if (ref_maybe_used_by_stmt_p (use_stmt, - gimple_assign_lhs (stmt))) + else if (ref_maybe_used_by_stmt_p (use_stmt, ref)) { fail = true; BREAK_FROM_IMM_USE_STMT (ui); @@ -191,7 +183,7 @@ dse_possible_dead_store_p (gimple stmt, gimple *use_stmt) just pretend the stmt makes itself dead. Otherwise fail. */ if (!temp) { - if (stmt_may_clobber_global_p (stmt)) + if (ref_may_alias_global_p (ref)) return false; temp = stmt; @@ -199,7 +191,7 @@ dse_possible_dead_store_p (gimple stmt, gimple *use_stmt) } } /* Continue walking until we reach a kill. */ - while (!stmt_kills_ref_p (temp, gimple_assign_lhs (stmt))); + while (!stmt_kills_ref_p (temp, ref)); *use_stmt = temp; @@ -228,23 +220,78 @@ dse_optimize_stmt (gimple_stmt_iterator *gsi) if (!gimple_vdef (stmt)) return; - /* We know we have virtual definitions. If this is a GIMPLE_ASSIGN - that's not also a function call, then record it into our table. */ - if (is_gimple_call (stmt) && gimple_call_fndecl (stmt)) - return; - /* Don't return early on *this_2(D) ={v} {CLOBBER}. */ if (gimple_has_volatile_ops (stmt) && (!gimple_clobber_p (stmt) || TREE_CODE (gimple_assign_lhs (stmt)) != MEM_REF)) return; + /* We know we have virtual definitions. We can handle assignments and + some builtin calls. */ + if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)) + { + switch (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))) + { + case BUILT_IN_MEMCPY: + case BUILT_IN_MEMMOVE: + case BUILT_IN_MEMSET: + { + gimple use_stmt; + ao_ref ref; + tree size = NULL_TREE; + if (gimple_call_num_args (stmt) == 3) + size = gimple_call_arg (stmt, 2); + tree ptr = gimple_call_arg (stmt, 0); + ao_ref_init_from_ptr_and_size (&ref, ptr, size); + if (!dse_possible_dead_store_p (&ref, stmt, &use_stmt)) + return; + + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, " Deleted dead call '"); + print_gimple_stmt (dump_file, gsi_stmt (*gsi), dump_flags, 0); + fprintf (dump_file, "'\n"); + } + + tree lhs = gimple_call_lhs (stmt); + if (lhs) + { + gimple new_stmt = gimple_build_assign (lhs, ptr); + unlink_stmt_vdef (stmt); + if (gsi_replace (gsi, new_stmt, true)) + bitmap_set_bit (need_eh_cleanup, gimple_bb (stmt)->index); + } + else + { + /* Then we need to fix the operand of the consuming stmt. */ + unlink_stmt_vdef (stmt); + + /* Remove the dead store. */ + if (gsi_remove (gsi, true)) + bitmap_set_bit (need_eh_cleanup, gimple_bb (stmt)->index); + } + break; + } + default: + return; + } + } + if (is_gimple_assign (stmt)) { gimple use_stmt; - if (!dse_possible_dead_store_p (stmt, &use_stmt)) - return; + /* Self-assignments are zombies. */ + if (operand_equal_p (gimple_assign_rhs1 (stmt), + gimple_assign_lhs (stmt), 0)) + use_stmt = stmt; + else + { + ao_ref ref; + ao_ref_init (&ref, gimple_assign_lhs (stmt)); + if (!dse_possible_dead_store_p (&ref, stmt, &use_stmt)) + return; + } /* Now we know that use_stmt kills the LHS of stmt. */ @@ -254,23 +301,6 @@ dse_optimize_stmt (gimple_stmt_iterator *gsi) && !gimple_clobber_p (use_stmt)) return; - basic_block bb; - - /* 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 (stmt != use_stmt - && ref_maybe_used_by_stmt_p (use_stmt, gimple_assign_lhs (stmt))) - return; - if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, " Deleted dead store '"); @@ -282,7 +312,7 @@ dse_optimize_stmt (gimple_stmt_iterator *gsi) unlink_stmt_vdef (stmt); /* Remove the dead store. */ - bb = gimple_bb (stmt); + basic_block bb = gimple_bb (stmt); if (gsi_remove (gsi, true)) bitmap_set_bit (need_eh_cleanup, bb->index); |