tree-ssa-dse.c (decrement_count): New function.
authorJeff Law <law@redhat.com>
Fri, 13 Jan 2017 15:50:11 +0000 (08:50 -0700)
committerJeff Law <law@gcc.gnu.org>
Fri, 13 Jan 2017 15:50:11 +0000 (08:50 -0700)
* tree-ssa-dse.c (decrement_count): New function.
(increment_start_addr, maybe_trim_memstar_call): Likewise.
(dse_dom_walker::optimize_stmt): Call maybe_trim_memstar_call directly
when we know the partially dead statement is a mem* function.

* gcc.dg/tree-ssa/ssa-dse-25.c: New test.

From-SVN: r244444

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-25.c [new file with mode: 0644]
gcc/tree-ssa-dse.c

index 221aff93d49d59cae74e5e852193b49c2eca8ecc..203967016730ff9e5529eea105a770b79d84d9fe 100644 (file)
@@ -1,5 +1,10 @@
 2017-01-13  Jeff Law  <law@redhat.com>
 
+       * tree-ssa-dse.c (decrement_count): New function.
+       (increment_start_addr, maybe_trim_memstar_call): Likewise.
+       (dse_dom_walker::optimize_stmt): Call maybe_trim_memstar_call directly
+       when we know the partially dead statement is a mem* function.
+
        PR tree-optimization/61912
        PR tree-optimization/77485
        * tree-ssa-dse.c: Include expr.h.
index bb9b824b18753bd2bed8615995b85433313ed32b..3dd5ae1ffea70219c499b8660a69bf49b9f215f3 100644 (file)
@@ -1,5 +1,7 @@
 2017-01-13  Jeff Law  <law@redhat.com>
 
+       * gcc.dg/tree-ssa/ssa-dse-25.c: New test.
+
        PR tree-optimization/61912
        PR tree-optimization/77485
        * g++.dg/tree-ssa/ssa-dse-1.C: New test.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-25.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-25.c
new file mode 100644 (file)
index 0000000..8b7db3a
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-dse1-details -w" } */
+
+char z[32];
+
+
+int
+foo(void)
+{
+  memset (z, 0, 16);
+  memset (z+8, 0, 24);
+}
+
+/* { dg-final { scan-tree-dump "memset .&z, 0, 8." "dse1" } } */
+
+
index 83ce29b86701781e8ec6a1c97d825062e5a30a95..20cf3b4c7fd143481f94cd50e316221528bc7659 100644 (file)
@@ -332,6 +332,99 @@ maybe_trim_constructor_store (ao_ref *ref, sbitmap live, gimple *stmt)
     }
 }
 
+/* STMT is a memcpy, memmove or memset.  Decrement the number of bytes
+   copied/set by DECREMENT.  */
+static void
+decrement_count (gimple *stmt, int decrement)
+{
+  tree *countp = gimple_call_arg_ptr (stmt, 2);
+  gcc_assert (TREE_CODE (*countp) == INTEGER_CST);
+  *countp = wide_int_to_tree (TREE_TYPE (*countp), (TREE_INT_CST_LOW (*countp)
+                                                   - decrement));
+
+}
+
+static void
+increment_start_addr (gimple *stmt, tree *where, int increment)
+{
+  if (TREE_CODE (*where) == SSA_NAME)
+    {
+      tree tem = make_ssa_name (TREE_TYPE (*where));
+      gassign *newop
+        = gimple_build_assign (tem, POINTER_PLUS_EXPR, *where,
+                              build_int_cst (sizetype, increment));
+      gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+      gsi_insert_before (&gsi, newop, GSI_SAME_STMT);
+      *where = tem;
+      update_stmt (gsi_stmt (gsi));
+      return;
+    }
+
+  *where = build_fold_addr_expr (fold_build2 (MEM_REF, char_type_node,
+                                             *where,
+                                             build_int_cst (ptr_type_node,
+                                                            increment)));
+}
+
+/* STMT is builtin call that writes bytes in bitmap ORIG, some bytes are dead
+   (ORIG & ~NEW) and need not be stored.  Try to rewrite STMT to reduce
+   the amount of data it actually writes.
+
+   Right now we only support trimming from the head or the tail of the
+   memory region.  In theory we could split the mem* call, but it's
+   likely of marginal value.  */
+
+static void
+maybe_trim_memstar_call (ao_ref *ref, sbitmap live, gimple *stmt)
+{
+  switch (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt)))
+    {
+    case BUILT_IN_MEMCPY:
+    case BUILT_IN_MEMMOVE:
+      {
+       int head_trim, tail_trim;
+       compute_trims (ref, live, &head_trim, &tail_trim);
+
+       /* Tail trimming is easy, we can just reduce the count.  */
+        if (tail_trim)
+         decrement_count (stmt, tail_trim);
+
+       /* Head trimming requires adjusting all the arguments.  */
+        if (head_trim)
+          {
+           tree *dst = gimple_call_arg_ptr (stmt, 0);
+           increment_start_addr (stmt, dst, head_trim);
+           tree *src = gimple_call_arg_ptr (stmt, 1);
+           increment_start_addr (stmt, src, head_trim);
+           decrement_count (stmt, head_trim);
+         }
+        break;
+      }
+
+    case BUILT_IN_MEMSET:
+      {
+       int head_trim, tail_trim;
+       compute_trims (ref, live, &head_trim, &tail_trim);
+
+       /* Tail trimming is easy, we can just reduce the count.  */
+        if (tail_trim)
+         decrement_count (stmt, tail_trim);
+
+       /* Head trimming requires adjusting all the arguments.  */
+        if (head_trim)
+          {
+           tree *dst = gimple_call_arg_ptr (stmt, 0);
+           increment_start_addr (stmt, dst, head_trim);
+           decrement_count (stmt, head_trim);
+         }
+       break;
+      }
+
+      default:
+       break;
+    }
+}
+
 /* 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.
@@ -619,7 +712,7 @@ dse_dom_walker::dse_optimize_stmt (gimple_stmt_iterator *gsi)
 
              if (store_status == DSE_STORE_MAYBE_PARTIAL_DEAD)
                {
-                 maybe_trim_partially_dead_store (&ref, m_live_bytes, stmt);
+                 maybe_trim_memstar_call (&ref, m_live_bytes, stmt);
                  return;
                }