aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-dse.c
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>2017-01-13 08:46:22 -0700
committerJeff Law <law@gcc.gnu.org>2017-01-13 08:46:22 -0700
commit9e59e99a6016420f36eb3a2a8a7912c58ef99a17 (patch)
tree9f6f6ea0036d61c5d838b447db3b895284ec705a /gcc/tree-ssa-dse.c
parentd155c6fef06cba08d6ed48b90092c70fa69f8c79 (diff)
downloadgcc-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.c64
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;