diff options
author | Jeff Law <law@redhat.com> | 2017-01-13 08:46:22 -0700 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2017-01-13 08:46:22 -0700 |
commit | 9e59e99a6016420f36eb3a2a8a7912c58ef99a17 (patch) | |
tree | 9f6f6ea0036d61c5d838b447db3b895284ec705a /gcc/tree-ssa-dse.c | |
parent | d155c6fef06cba08d6ed48b90092c70fa69f8c79 (diff) | |
download | gcc-9e59e99a6016420f36eb3a2a8a7912c58ef99a17.zip gcc-9e59e99a6016420f36eb3a2a8a7912c58ef99a17.tar.gz gcc-9e59e99a6016420f36eb3a2a8a7912c58ef99a17.tar.bz2 |
re PR middle-end/61912 (Missed (partial) dead store elimination for structures on GIMPLE)
PR tree-optimization/61912
PR tree-optimization/77485
* tree-ssa-dse.c: Include expr.h.
(maybe_trim_constructor_store): New function.
(maybe_trim_partially_dead_store): Call maybe_trim_constructor_store.
PR tree-optimization/61912
PR tree-optimization/77485
* g++.dg/tree-ssa/ssa-dse-1.C: New test.
* gcc.dg/tree-ssa/pr30375: Adjust expected output.
* gcc.dg/tree-ssa/ssa-dse-24.c: New test.
From-SVN: r244443
Diffstat (limited to 'gcc/tree-ssa-dse.c')
-rw-r--r-- | gcc/tree-ssa-dse.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c index daaa99c..83ce29b 100644 --- a/gcc/tree-ssa-dse.c +++ b/gcc/tree-ssa-dse.c @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see #include "domwalk.h" #include "tree-cfgcleanup.h" #include "params.h" +#include "alias.h" /* This file implements dead store elimination. @@ -271,6 +272,66 @@ maybe_trim_complex_store (ao_ref *ref, sbitmap live, gimple *stmt) are live. We do not try to optimize those cases. */ } +/* STMT initializes an object using a CONSTRUCTOR where one or more of the + bytes written are dead stores. ORIG is the bitmap of bytes stored by + STMT. LIVE is the bitmap of stores that are actually live. + + Attempt to rewrite STMT so that only the real or imaginary part of + the object is actually stored. + + The most common case for getting here is a CONSTRUCTOR with no elements + being used to zero initialize an object. We do not try to handle other + cases as those would force us to fully cover the object with the + CONSTRUCTOR node except for the components that are dead. */ + +static void +maybe_trim_constructor_store (ao_ref *ref, sbitmap live, gimple *stmt) +{ + tree ctor = gimple_assign_rhs1 (stmt); + + /* This is the only case we currently handle. It actually seems to + catch most cases of actual interest. */ + gcc_assert (CONSTRUCTOR_NELTS (ctor) == 0); + + int head_trim = 0; + int tail_trim = 0; + compute_trims (ref, live, &head_trim, &tail_trim); + + /* Now we want to replace the constructor initializer + with memset (object + head_trim, 0, size - head_trim - tail_trim). */ + if (head_trim || tail_trim) + { + /* We want &lhs for the MEM_REF expression. */ + tree lhs_addr = build_fold_addr_expr (gimple_assign_lhs (stmt)); + + if (! is_gimple_min_invariant (lhs_addr)) + return; + + /* The number of bytes for the new constructor. */ + int count = (ref->size / BITS_PER_UNIT) - head_trim - tail_trim; + + /* And the new type for the CONSTRUCTOR. Essentially it's just + a char array large enough to cover the non-trimmed parts of + the original CONSTRUCTOR. Note we want explicit bounds here + so that we know how many bytes to clear when expanding the + CONSTRUCTOR. */ + tree type = build_array_type_nelts (char_type_node, count); + + /* Build a suitable alias type rather than using alias set zero + to avoid pessimizing. */ + tree alias_type = reference_alias_ptr_type (gimple_assign_lhs (stmt)); + + /* Build a MEM_REF representing the whole accessed area, starting + at the first byte not trimmed. */ + tree exp = fold_build2 (MEM_REF, type, lhs_addr, + build_int_cst (alias_type, head_trim)); + + /* Now update STMT with a new RHS and LHS. */ + gimple_assign_set_lhs (stmt, exp); + gimple_assign_set_rhs1 (stmt, build_constructor (type, NULL)); + } +} + /* STMT is a memory write where one or more bytes written are dead stores. ORIG is the bitmap of bytes stored by STMT. LIVE is the bitmap of stores that are actually live. @@ -287,6 +348,9 @@ maybe_trim_partially_dead_store (ao_ref *ref, sbitmap live, gimple *stmt) { switch (gimple_assign_rhs_code (stmt)) { + case CONSTRUCTOR: + maybe_trim_constructor_store (ref, live, stmt); + break; case COMPLEX_CST: maybe_trim_complex_store (ref, live, stmt); break; |