From 4d147bca3f0f1fadac32d4306a654e975b364341 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 4 May 2017 13:29:08 +0000 Subject: [PATCH] tree-ssa-alias.c (get_continuation_for_phi): Improve looking for the last VUSE which def dominates the PHI. 2017-05-04 Richard Biener * 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 --- gcc/ChangeLog | 7 + gcc/testsuite/ChangeLog | 4 + gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-58.c | 37 +++++ gcc/tree-ssa-alias.c | 153 ++++++++------------- 4 files changed, 107 insertions(+), 94 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-58.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 85488453796..b87dc25a4c5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2017-05-04 Richard Biener + + * 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 * tree-ssa-loop-manip.c (niter_for_unrolled_loop): Add commentary diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 39fc9284da3..edf2247543a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2017-05-04 Richard Biener + + * gcc.dg/tree-ssa/ssa-fre-58.c: New testcase. + 2017-05-04 Richard Sandiford * gcc.dg/vect/vect-profile-1.c: New test. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-58.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-58.c new file mode 100644 index 00000000000..7f30ad41728 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-58.c @@ -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" } } */ diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index dc54533e48b..74ee2b0a0cc 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -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 - 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,44 +2685,73 @@ 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. */ + /* First look if any of the args themselves satisfy this. */ + for (i = 0; i < nargs; ++i) { - 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) + 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 (def), phi_bb)) + continue; + /* See below. */ + if (gimple_code (def) == GIMPLE_PHI) + continue; + while (! dominated_by_p (CDI_DOMINATORS, + phi_bb, gimple_bb (def))) { - arg1 = PHI_ARG_DEF (phi, i); - if (SSA_NAME_IS_DEFAULT_DEF (arg1)) + arg0 = gimple_vuse (def); + if (SSA_NAME_IS_DEFAULT_DEF (arg0)) + break; + def = SSA_NAME_DEF_STMT (arg0); + if (gimple_code (def) == GIMPLE_PHI) { - arg0 = arg1; - break; + /* 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; } - if (dominated_by_p (CDI_DOMINATORS, - gimple_bb (SSA_NAME_DEF_STMT (arg0)), - gimple_bb (SSA_NAME_DEF_STMT (arg1)))) - arg0 = arg1; } + break; +next:; + } + if (! arg0) + return NULL_TREE; - /* Then pairwise reduce 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) - return NULL_TREE; - } - - return arg0; + /* Then check against the found candidate. */ + for (i = 0; i < nargs; ++i) + { + arg1 = PHI_ARG_DEF (phi, i); + if (arg1 == arg0) + ; + else if (! maybe_skip_until (phi, arg0, ref, arg1, cnt, visited, + abort_on_visited, translate, data)) + return NULL_TREE; } - return NULL_TREE; + return arg0; } /* Based on the memory reference REF and its virtual use VUSE call