tree-ssa-alias.c (get_continuation_for_phi): Improve looking for the last VUSE which def dominates the PHI.

2017-05-04  Richard Biener  <rguenther@suse.de>

	* tree-ssa-alias.c (get_continuation_for_phi): Improve looking
	for the last VUSE which def dominates the PHI.  Directly call
	maybe_skip_until.
	(get_continuation_for_phi_1): Remove.

	* gcc.dg/tree-ssa/ssa-fre-58.c: New testcase.

From-SVN: r247596
This commit is contained in:
Richard Biener 2017-05-04 13:29:08 +00:00 committed by Richard Biener
parent b655c31048
commit 4d147bca3f
4 changed files with 107 additions and 94 deletions

View File

@ -1,3 +1,10 @@
2017-05-04 Richard Biener <rguenther@suse.de>
* tree-ssa-alias.c (get_continuation_for_phi): Improve looking
for the last VUSE which def dominates the PHI. Directly call
maybe_skip_until.
(get_continuation_for_phi_1): Remove.
2017-05-04 Richard Sandiford <richard.sandiford@linaro.org>
* tree-ssa-loop-manip.c (niter_for_unrolled_loop): Add commentary

View File

@ -1,3 +1,7 @@
2017-05-04 Richard Biener <rguenther@suse.de>
* gcc.dg/tree-ssa/ssa-fre-58.c: New testcase.
2017-05-04 Richard Sandiford <richard.sandiford@linaro.org>
* gcc.dg/vect/vect-profile-1.c: New test.

View File

@ -0,0 +1,37 @@
/* { dg-do run } */
/* { dg-require-effective-target int32plus } */
/* { dg-options "-O2 -fdump-tree-fre1" } */
long long int a = -465274079317386463LL;
int b = 856872806;
int c = -1940894202;
int d = 1718449211;
int e = -392681565;
unsigned long long int f = 13521452247506316486ULL;
int g = -13194608;
__attribute__((noinline, noclone))
void foo ()
{
if (!a - a)
c = b = 0;
else
d = 3UL * a == 0;
if (g / a)
e = 0 < -a + 500849970701012771LL + (unsigned long) -a;
else
f = 4081116982543369LL & a;
}
int
main ()
{
asm volatile ("" : : : "memory");
foo ();
if (f != 2818598057803777LL)
__builtin_abort ();
return 0;
}
/* Should CSE all loads of a. */
/* { dg-final { scan-tree-dump-times " = a;" 1 "fre1" } } */

View File

@ -2663,70 +2663,6 @@ maybe_skip_until (gimple *phi, tree target, ao_ref *ref,
return true;
}
/* For two PHI arguments ARG0 and ARG1 try to skip non-aliasing code
until we hit the phi argument definition that dominates the other one.
Return that, or NULL_TREE if there is no such definition. */
static tree
get_continuation_for_phi_1 (gimple *phi, tree arg0, tree arg1,
ao_ref *ref, unsigned int *cnt,
bitmap *visited, bool abort_on_visited,
void *(*translate)(ao_ref *, tree, void *, bool *),
void *data)
{
gimple *def0 = SSA_NAME_DEF_STMT (arg0);
gimple *def1 = SSA_NAME_DEF_STMT (arg1);
tree common_vuse;
if (arg0 == arg1)
return arg0;
else if (gimple_nop_p (def0)
|| (!gimple_nop_p (def1)
&& dominated_by_p (CDI_DOMINATORS,
gimple_bb (def1), gimple_bb (def0))))
{
if (maybe_skip_until (phi, arg0, ref, arg1, cnt,
visited, abort_on_visited, translate, data))
return arg0;
}
else if (gimple_nop_p (def1)
|| dominated_by_p (CDI_DOMINATORS,
gimple_bb (def0), gimple_bb (def1)))
{
if (maybe_skip_until (phi, arg1, ref, arg0, cnt,
visited, abort_on_visited, translate, data))
return arg1;
}
/* Special case of a diamond:
MEM_1 = ...
goto (cond) ? L1 : L2
L1: store1 = ... #MEM_2 = vuse(MEM_1)
goto L3
L2: store2 = ... #MEM_3 = vuse(MEM_1)
L3: MEM_4 = PHI<MEM_2, MEM_3>
We were called with the PHI at L3, MEM_2 and MEM_3 don't
dominate each other, but still we can easily skip this PHI node
if we recognize that the vuse MEM operand is the same for both,
and that we can skip both statements (they don't clobber us).
This is still linear. Don't use maybe_skip_until, that might
potentially be slow. */
else if ((common_vuse = gimple_vuse (def0))
&& common_vuse == gimple_vuse (def1))
{
bool disambiguate_only = true;
*cnt += 2;
if ((!stmt_may_clobber_ref_p_1 (def0, ref)
|| (translate
&& (*translate) (ref, arg0, data, &disambiguate_only) == NULL))
&& (!stmt_may_clobber_ref_p_1 (def1, ref)
|| (translate
&& (*translate) (ref, arg1, data, &disambiguate_only) == NULL)))
return common_vuse;
}
return NULL_TREE;
}
/* Starting from a PHI node for the virtual operand of the memory reference
REF find a continuation virtual operand that allows to continue walking
@ -2749,46 +2685,75 @@ get_continuation_for_phi (gimple *phi, ao_ref *ref,
/* For two or more arguments try to pairwise skip non-aliasing code
until we hit the phi argument definition that dominates the other one. */
else if (nargs >= 2)
{
basic_block phi_bb = gimple_bb (phi);
tree arg0, arg1;
unsigned i;
/* Find a candidate for the virtual operand which definition
dominates those of all others. */
arg0 = PHI_ARG_DEF (phi, 0);
if (!SSA_NAME_IS_DEFAULT_DEF (arg0))
for (i = 1; i < nargs; ++i)
/* First look if any of the args themselves satisfy this. */
for (i = 0; i < nargs; ++i)
{
arg1 = PHI_ARG_DEF (phi, i);
if (SSA_NAME_IS_DEFAULT_DEF (arg1))
{
arg0 = arg1;
arg0 = PHI_ARG_DEF (phi, i);
if (SSA_NAME_IS_DEFAULT_DEF (arg0))
break;
basic_block def_bb = gimple_bb (SSA_NAME_DEF_STMT (arg0));
if (def_bb != phi_bb
&& dominated_by_p (CDI_DOMINATORS, phi_bb, def_bb))
break;
arg0 = NULL_TREE;
}
/* If not, look if we can reach such candidate by walking defs
of a PHI arg without crossing other PHIs. */
if (! arg0)
for (i = 0; i < nargs; ++i)
{
arg0 = PHI_ARG_DEF (phi, i);
gimple *def = SSA_NAME_DEF_STMT (arg0);
/* Backedges can't work. */
if (dominated_by_p (CDI_DOMINATORS,
gimple_bb (SSA_NAME_DEF_STMT (arg0)),
gimple_bb (SSA_NAME_DEF_STMT (arg1))))
arg0 = arg1;
gimple_bb (def), phi_bb))
continue;
/* See below. */
if (gimple_code (def) == GIMPLE_PHI)
continue;
while (! dominated_by_p (CDI_DOMINATORS,
phi_bb, gimple_bb (def)))
{
arg0 = gimple_vuse (def);
if (SSA_NAME_IS_DEFAULT_DEF (arg0))
break;
def = SSA_NAME_DEF_STMT (arg0);
if (gimple_code (def) == GIMPLE_PHI)
{
/* Do not try to look through arbitrarily complicated
CFGs. For those looking for the first VUSE starting
from the end of the immediate dominator of phi_bb
is likely faster. */
arg0 = NULL_TREE;
goto next;
}
}
break;
next:;
}
if (! arg0)
return NULL_TREE;
/* Then pairwise reduce against the found candidate. */
/* Then check against the found candidate. */
for (i = 0; i < nargs; ++i)
{
arg1 = PHI_ARG_DEF (phi, i);
arg0 = get_continuation_for_phi_1 (phi, arg0, arg1, ref,
cnt, visited, abort_on_visited,
translate, data);
if (!arg0)
if (arg1 == arg0)
;
else if (! maybe_skip_until (phi, arg0, ref, arg1, cnt, visited,
abort_on_visited, translate, data))
return NULL_TREE;
}
return arg0;
}
return NULL_TREE;
}
/* Based on the memory reference REF and its virtual use VUSE call
WALKER for each virtual use that is equivalent to VUSE, including VUSE
itself. That is, for each virtual use for which its defining statement