tree-ssa-alias.c (get_continuation_for_phi): Improve looking for the last VUSE which...
authorRichard Biener <rguenther@suse.de>
Thu, 4 May 2017 13:29:08 +0000 (13:29 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 4 May 2017 13:29:08 +0000 (13:29 +0000)
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

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-58.c [new file with mode: 0644]
gcc/tree-ssa-alias.c

index 854884537963aae739a9e37fb1b4b6c038b67956..b87dc25a4c597799c0f0af676c8900ba66eddc3f 100644 (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
index 39fc9284da382797f817995733d067e97327d2c4..edf2247543ad7d9b107cbcd67df5c4ceb97eb754 100644 (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.
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 (file)
index 0000000..7f30ad4
--- /dev/null
@@ -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" } } */
index dc54533e48bd3bc96e6f5225dc1e0347e46351b5..74ee2b0a0cc448135fa5c7c5c561673d6439a401 100644 (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,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