tree-optimization/100221 - improve DSE a bit
When facing multiple PHI defs and one feeding the other we can postpone processing uses of one and thus can proceed. 2022-05-20 Richard Biener <rguenther@suse.de> PR tree-optimization/100221 * tree-ssa-dse.cc (contains_phi_arg): New function. (dse_classify_store): Postpone PHI defs that feed another PHI in defs. * gcc.dg/tree-ssa/ssa-dse-44.c: New testcase. * gcc.dg/tree-ssa/ssa-dse-45.c: Likewise.
This commit is contained in:
parent
d918faea12
commit
1adf11822b
|
@ -0,0 +1,19 @@
|
|||
/* { dg-do link } */
|
||||
/* { dg-options "-O -fdump-tree-dse1-details" } */
|
||||
|
||||
extern void foo(void);
|
||||
int a, b;
|
||||
static int c;
|
||||
int main()
|
||||
{
|
||||
if (c)
|
||||
foo ();
|
||||
int *g = &c;
|
||||
int **h = &g;
|
||||
int ***h1 = &h;
|
||||
if (a)
|
||||
while (b)
|
||||
b = 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "Deleted dead store: g = &c;" "dse1" } } */
|
|
@ -0,0 +1,24 @@
|
|||
/* { dg-do link } */
|
||||
/* { dg-options "-O" } */
|
||||
|
||||
extern void foo(void);
|
||||
int a, b;
|
||||
static int c;
|
||||
static void f() {
|
||||
while (a)
|
||||
for (; b; b--)
|
||||
;
|
||||
}
|
||||
void i() {
|
||||
if (c)
|
||||
foo();
|
||||
int *g = &c;
|
||||
{
|
||||
int **h[1] = {&g};
|
||||
f();
|
||||
}
|
||||
}
|
||||
int main() {
|
||||
i();
|
||||
return 0;
|
||||
}
|
|
@ -898,6 +898,17 @@ dse_optimize_redundant_stores (gimple *stmt)
|
|||
}
|
||||
}
|
||||
|
||||
/* Return whether PHI contains ARG as an argument. */
|
||||
|
||||
static bool
|
||||
contains_phi_arg (gphi *phi, tree arg)
|
||||
{
|
||||
for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
|
||||
if (gimple_phi_arg_def (phi, i) == arg)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* 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
|
||||
|
@ -949,8 +960,8 @@ dse_classify_store (ao_ref *ref, gimple *stmt,
|
|||
return DSE_STORE_LIVE;
|
||||
|
||||
auto_vec<gimple *, 10> defs;
|
||||
gimple *first_phi_def = NULL;
|
||||
gimple *last_phi_def = NULL;
|
||||
gphi *first_phi_def = NULL;
|
||||
gphi *last_phi_def = NULL;
|
||||
FOR_EACH_IMM_USE_STMT (use_stmt, ui, defvar)
|
||||
{
|
||||
/* Limit stmt walking. */
|
||||
|
@ -973,8 +984,8 @@ dse_classify_store (ao_ref *ref, gimple *stmt,
|
|||
{
|
||||
defs.safe_push (use_stmt);
|
||||
if (!first_phi_def)
|
||||
first_phi_def = use_stmt;
|
||||
last_phi_def = use_stmt;
|
||||
first_phi_def = as_a <gphi *> (use_stmt);
|
||||
last_phi_def = as_a <gphi *> (use_stmt);
|
||||
}
|
||||
}
|
||||
/* If the statement is a use the store is not dead. */
|
||||
|
@ -1046,6 +1057,7 @@ dse_classify_store (ao_ref *ref, gimple *stmt,
|
|||
use_operand_p use_p;
|
||||
tree vdef = (gimple_code (def) == GIMPLE_PHI
|
||||
? gimple_phi_result (def) : gimple_vdef (def));
|
||||
gphi *phi_def;
|
||||
/* If the path to check starts with a kill we do not need to
|
||||
process it further.
|
||||
??? With byte tracking we need only kill the bytes currently
|
||||
|
@ -1079,7 +1091,31 @@ dse_classify_store (ao_ref *ref, gimple *stmt,
|
|||
&& bitmap_bit_p (visited,
|
||||
SSA_NAME_VERSION
|
||||
(PHI_RESULT (use_stmt))))))
|
||||
defs.unordered_remove (i);
|
||||
{
|
||||
defs.unordered_remove (i);
|
||||
if (def == first_phi_def)
|
||||
first_phi_def = NULL;
|
||||
else if (def == last_phi_def)
|
||||
last_phi_def = NULL;
|
||||
}
|
||||
/* If def is a PHI and one of its arguments is another PHI node still
|
||||
in consideration we can defer processing it. */
|
||||
else if ((phi_def = dyn_cast <gphi *> (def))
|
||||
&& ((last_phi_def
|
||||
&& phi_def != last_phi_def
|
||||
&& contains_phi_arg (phi_def,
|
||||
gimple_phi_result (last_phi_def)))
|
||||
|| (first_phi_def
|
||||
&& phi_def != first_phi_def
|
||||
&& contains_phi_arg
|
||||
(phi_def, gimple_phi_result (first_phi_def)))))
|
||||
{
|
||||
defs.unordered_remove (i);
|
||||
if (phi_def == first_phi_def)
|
||||
first_phi_def = NULL;
|
||||
else if (phi_def == last_phi_def)
|
||||
last_phi_def = NULL;
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue