summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>2017-01-13 15:50:11 +0000
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>2017-01-13 15:50:11 +0000
commit339f327dcd95025982c81266921e3a9d98c5f3b0 (patch)
treeadb4b9543c487f0b0c01eb958a60ade732154805
parent56ce87e3fb7b6314a53f102acb1d91ae7767e101 (diff)
downloadgcc-339f327dcd95025982c81266921e3a9d98c5f3b0.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@244444 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/testsuite/ChangeLog2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-25.c16
-rw-r--r--gcc/tree-ssa-dse.c95
4 files changed, 117 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 221aff93d49..20396701673 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index bb9b824b187..3dd5ae1ffea 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..8b7db3a2385
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-25.c
@@ -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" } } */
+
+
diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c
index 83ce29b8670..20cf3b4c7fd 100644
--- a/gcc/tree-ssa-dse.c
+++ b/gcc/tree-ssa-dse.c
@@ -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;
}