params.def (PARAM_DSE_MAX_ALIAS_QUERIES_PER_STORE): New param.
2018-05-16 Richard Biener <rguenther@suse.de> * params.def (PARAM_DSE_MAX_ALIAS_QUERIES_PER_STORE): New param. * doc/invoke.texi (dse-max-alias-queries-per-store): Document. * tree-ssa-dse.c: Include tree-ssa-loop.h. (check_name): New callback. (dse_classify_store): Track cycles via a visited bitmap of PHI defs and simplify handling of in-loop and across loop dead stores and properly fail for loop-variant refs. Handle byte-tracking with multiple defs. Use PARAM_DSE_MAX_ALIAS_QUERIES_PER_STORE for limiting the walk. * gcc.dg/tree-ssa/ssa-dse-32.c: New testcase. * gcc.dg/tree-ssa/ssa-dse-33.c: Likewise. * gcc.dg/uninit-pr81897-2.c: Use -fno-tree-dse. From-SVN: r260288
This commit is contained in:
parent
1f3cb66326
commit
311eb8168e
@ -1,3 +1,15 @@
|
||||
2018-05-16 Richard Biener <rguenther@suse.de>
|
||||
|
||||
* params.def (PARAM_DSE_MAX_ALIAS_QUERIES_PER_STORE): New param.
|
||||
* doc/invoke.texi (dse-max-alias-queries-per-store): Document.
|
||||
* tree-ssa-dse.c: Include tree-ssa-loop.h.
|
||||
(check_name): New callback.
|
||||
(dse_classify_store): Track cycles via a visited bitmap of PHI
|
||||
defs and simplify handling of in-loop and across loop dead stores
|
||||
and properly fail for loop-variant refs. Handle byte-tracking with
|
||||
multiple defs. Use PARAM_DSE_MAX_ALIAS_QUERIES_PER_STORE for
|
||||
limiting the walk.
|
||||
|
||||
2018-05-16 Richard Sandiford <richard.sandiford@linaro.org>
|
||||
|
||||
* tree-vectorizer.h (vect_get_vector_types_for_stmt): Declare.
|
||||
|
@ -10439,6 +10439,11 @@ Average number of iterations of a loop.
|
||||
Maximum size (in bytes) of objects tracked bytewise by dead store elimination.
|
||||
Larger values may result in larger compilation times.
|
||||
|
||||
@item dse-max-alias-queries-per-store
|
||||
Maximum number of queries into the alias oracle per store.
|
||||
Larger values result in larger compilation times and may result in more
|
||||
removed dead stores.
|
||||
|
||||
@item scev-max-expr-size
|
||||
Bound on size of expressions used in the scalar evolutions analyzer.
|
||||
Large expressions slow the analyzer.
|
||||
|
@ -547,6 +547,11 @@ DEFPARAM(PARAM_DSE_MAX_OBJECT_SIZE,
|
||||
"Maximum size (in bytes) of objects tracked bytewise by dead store elimination.",
|
||||
256, 0, 0)
|
||||
|
||||
DEFPARAM(PARAM_DSE_MAX_ALIAS_QUERIES_PER_STORE,
|
||||
"dse-max-alias-queries-per-store",
|
||||
"Maximum number of queries into the alias oracle per store.",
|
||||
256, 0, 0)
|
||||
|
||||
DEFPARAM(PARAM_SCEV_MAX_EXPR_SIZE,
|
||||
"scev-max-expr-size",
|
||||
"Bound on size of expressions used in the scalar evolutions analyzer.",
|
||||
|
@ -1,3 +1,9 @@
|
||||
2018-05-16 Richard Biener <rguenther@suse.de>
|
||||
|
||||
* gcc.dg/tree-ssa/ssa-dse-32.c: New testcase.
|
||||
* gcc.dg/tree-ssa/ssa-dse-33.c: Likewise.
|
||||
* gcc.dg/uninit-pr81897-2.c: Use -fno-tree-dse.
|
||||
|
||||
2018-05-16 Richard Sandiford <richard.sandiford@linaro.org>
|
||||
|
||||
* gcc.target/aarch64/sve/vcond_10.c: New test.
|
||||
|
13
gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-32.c
Normal file
13
gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-32.c
Normal file
@ -0,0 +1,13 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O -fdump-tree-dse1-details" } */
|
||||
|
||||
void f(int n)
|
||||
{
|
||||
char *p = __builtin_malloc (1);
|
||||
int i;
|
||||
do
|
||||
*p = 0;
|
||||
while (++i < n);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Deleted dead store" 1 "dse1" } } */
|
22
gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-33.c
Normal file
22
gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-33.c
Normal file
@ -0,0 +1,22 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O -fdump-tree-dse1-details" } */
|
||||
|
||||
void f(char *p, int n)
|
||||
{
|
||||
for (int i = 0; i < n; ++i)
|
||||
*p = 0; /* Removed by DSE. */
|
||||
*p = 1;
|
||||
}
|
||||
|
||||
void g(char *p, int n)
|
||||
{
|
||||
int i = 0;
|
||||
do
|
||||
*p = 0; /* Not yet removed by DSE. */
|
||||
while (++i < n);
|
||||
*p = 1;
|
||||
}
|
||||
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Deleted dead store" 2 "dse1" { xfail *-*-* } } } */
|
||||
/* { dg-final { scan-tree-dump-times "Deleted dead store" 1 "dse1" } } */
|
@ -1,5 +1,5 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O1 -fno-tree-ccp -Wmaybe-uninitialized" } */
|
||||
/* { dg-options "-O1 -fno-tree-ccp -fno-tree-dse -Wmaybe-uninitialized" } */
|
||||
|
||||
int oo;
|
||||
|
||||
|
@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "tree-cfgcleanup.h"
|
||||
#include "params.h"
|
||||
#include "alias.h"
|
||||
#include "tree-ssa-loop.h"
|
||||
|
||||
/* This file implements dead store elimination.
|
||||
|
||||
@ -515,6 +516,21 @@ live_bytes_read (ao_ref use_ref, ao_ref *ref, sbitmap live)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Callback for dse_classify_store calling for_each_index. Verify that
|
||||
indices are invariant in the loop with backedge PHI in basic-block DATA. */
|
||||
|
||||
static bool
|
||||
check_name (tree, tree *idx, void *data)
|
||||
{
|
||||
basic_block phi_bb = (basic_block) data;
|
||||
if (TREE_CODE (*idx) == SSA_NAME
|
||||
&& !SSA_NAME_IS_DEFAULT_DEF (*idx)
|
||||
&& dominated_by_p (CDI_DOMINATORS, gimple_bb (SSA_NAME_DEF_STMT (*idx)),
|
||||
phi_bb))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* A helper of dse_optimize_stmt.
|
||||
Given a GIMPLE_ASSIGN in STMT that writes to REF, classify it
|
||||
according to downstream uses and defs. Sets *BY_CLOBBER_P to true
|
||||
@ -527,7 +543,8 @@ dse_classify_store (ao_ref *ref, gimple *stmt,
|
||||
bool *by_clobber_p = NULL)
|
||||
{
|
||||
gimple *temp;
|
||||
unsigned cnt = 0;
|
||||
int cnt = 0;
|
||||
auto_bitmap visited;
|
||||
|
||||
if (by_clobber_p)
|
||||
*by_clobber_p = true;
|
||||
@ -539,58 +556,50 @@ dse_classify_store (ao_ref *ref, gimple *stmt,
|
||||
temp = stmt;
|
||||
do
|
||||
{
|
||||
gimple *use_stmt, *defvar_def;
|
||||
gimple *use_stmt;
|
||||
imm_use_iterator ui;
|
||||
bool fail = false;
|
||||
tree defvar;
|
||||
|
||||
/* Limit stmt walking to be linear in the number of possibly
|
||||
dead stores. */
|
||||
if (++cnt > 256)
|
||||
return DSE_STORE_LIVE;
|
||||
|
||||
if (gimple_code (temp) == GIMPLE_PHI)
|
||||
defvar = PHI_RESULT (temp);
|
||||
{
|
||||
/* If we visit this PHI by following a backedge then we have to
|
||||
make sure ref->ref only refers to SSA names that are invariant
|
||||
with respect to the loop represented by this PHI node. */
|
||||
if (dominated_by_p (CDI_DOMINATORS, gimple_bb (stmt),
|
||||
gimple_bb (temp))
|
||||
&& !for_each_index (ref->ref ? &ref->ref : &ref->base,
|
||||
check_name, gimple_bb (temp)))
|
||||
return DSE_STORE_LIVE;
|
||||
defvar = PHI_RESULT (temp);
|
||||
bitmap_set_bit (visited, SSA_NAME_VERSION (defvar));
|
||||
}
|
||||
else
|
||||
defvar = gimple_vdef (temp);
|
||||
defvar_def = temp;
|
||||
auto_vec<gimple *, 10> defs;
|
||||
FOR_EACH_IMM_USE_STMT (use_stmt, ui, defvar)
|
||||
{
|
||||
cnt++;
|
||||
|
||||
/* If we ever reach our DSE candidate stmt again fail. We
|
||||
cannot handle dead stores in loops. */
|
||||
if (use_stmt == stmt)
|
||||
/* Limit stmt walking. */
|
||||
if (++cnt > PARAM_VALUE (PARAM_DSE_MAX_ALIAS_QUERIES_PER_STORE))
|
||||
{
|
||||
fail = true;
|
||||
BREAK_FROM_IMM_USE_STMT (ui);
|
||||
}
|
||||
|
||||
/* We have visited ourselves already so ignore STMT for the
|
||||
purpose of chaining. */
|
||||
if (use_stmt == stmt)
|
||||
;
|
||||
/* In simple cases we can look through PHI nodes, but we
|
||||
have to be careful with loops and with memory references
|
||||
containing operands that are also operands of PHI nodes.
|
||||
See gcc.c-torture/execute/20051110-*.c. */
|
||||
else if (gimple_code (use_stmt) == GIMPLE_PHI)
|
||||
{
|
||||
/* Make sure we are not in a loop latch block. */
|
||||
if (gimple_bb (stmt) == gimple_bb (use_stmt)
|
||||
|| dominated_by_p (CDI_DOMINATORS,
|
||||
gimple_bb (stmt), gimple_bb (use_stmt))
|
||||
/* We can look through PHIs to regions post-dominating
|
||||
the DSE candidate stmt. */
|
||||
|| !dominated_by_p (CDI_POST_DOMINATORS,
|
||||
gimple_bb (stmt), gimple_bb (use_stmt)))
|
||||
{
|
||||
fail = true;
|
||||
BREAK_FROM_IMM_USE_STMT (ui);
|
||||
}
|
||||
/* Do not consider the PHI as use if it dominates the
|
||||
stmt defining the virtual operand we are processing,
|
||||
we have processed it already in this case. */
|
||||
if (gimple_bb (defvar_def) != gimple_bb (use_stmt)
|
||||
&& !dominated_by_p (CDI_DOMINATORS,
|
||||
gimple_bb (defvar_def),
|
||||
gimple_bb (use_stmt)))
|
||||
/* If we already visited this PHI ignore it for further
|
||||
processing. */
|
||||
if (!bitmap_bit_p (visited,
|
||||
SSA_NAME_VERSION (PHI_RESULT (use_stmt))))
|
||||
defs.safe_push (use_stmt);
|
||||
}
|
||||
/* If the statement is a use the store is not dead. */
|
||||
@ -600,25 +609,20 @@ dse_classify_store (ao_ref *ref, gimple *stmt,
|
||||
structure for USE_STMT and in doing so we find that the
|
||||
references hit non-live bytes and thus can be ignored. */
|
||||
if (byte_tracking_enabled
|
||||
&& (!gimple_vdef (use_stmt) || defs.is_empty ()))
|
||||
&& is_gimple_assign (use_stmt))
|
||||
{
|
||||
if (is_gimple_assign (use_stmt))
|
||||
ao_ref use_ref;
|
||||
ao_ref_init (&use_ref, gimple_assign_rhs1 (use_stmt));
|
||||
if (valid_ao_ref_for_dse (&use_ref)
|
||||
&& use_ref.base == ref->base
|
||||
&& known_eq (use_ref.size, use_ref.max_size)
|
||||
&& !live_bytes_read (use_ref, ref, live_bytes))
|
||||
{
|
||||
/* Other cases were noted as non-aliasing by
|
||||
the call to ref_maybe_used_by_stmt_p. */
|
||||
ao_ref use_ref;
|
||||
ao_ref_init (&use_ref, gimple_assign_rhs1 (use_stmt));
|
||||
if (valid_ao_ref_for_dse (&use_ref)
|
||||
&& use_ref.base == ref->base
|
||||
&& known_eq (use_ref.size, use_ref.max_size)
|
||||
&& !live_bytes_read (use_ref, ref, live_bytes))
|
||||
{
|
||||
/* If this statement has a VDEF, then it is the
|
||||
first store we have seen, so walk through it. */
|
||||
if (gimple_vdef (use_stmt))
|
||||
defs.safe_push (use_stmt);
|
||||
continue;
|
||||
}
|
||||
/* If this is a store, remember it as we possibly
|
||||
need to walk the defs uses. */
|
||||
if (gimple_vdef (use_stmt))
|
||||
defs.safe_push (use_stmt);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user