From 7c9560a578a06125cb30458a26605f91feb29b0d Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Fri, 13 Jan 2017 08:50:11 -0700 Subject: [PATCH] tree-ssa-dse.c (decrement_count): New function. * 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 | 5 ++ gcc/testsuite/ChangeLog | 2 + gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-25.c | 16 ++++ gcc/tree-ssa-dse.c | 95 +++++++++++++++++++++- 4 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-25.c 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 + * 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 + * 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; } -- 2.30.2