mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-21 17:21:03 +08:00
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
This commit is contained in:
parent
9e59e99a60
commit
7c9560a578
@ -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.
|
||||
|
@ -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.
|
||||
|
16
gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-25.c
Normal file
16
gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-25.c
Normal file
@ -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" } } */
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user