This removes an odd CSE failure of invariant addresses vs. non-invariant
ones.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2018-08-01  Richard Biener  <rguent...@suse.de>

        * tree-ssa-sccvn.c (visit_phi): Compare invariant addresses
        as base and offset.

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

Index: gcc/tree-ssa-sccvn.c
===================================================================
--- gcc/tree-ssa-sccvn.c        (revision 263190)
+++ gcc/tree-ssa-sccvn.c        (working copy)
@@ -3941,6 +3941,8 @@ static bool
 visit_phi (gimple *phi)
 {
   tree result, sameval = VN_TOP, seen_undef = NULL_TREE;
+  tree sameval_base = NULL_TREE;
+  poly_int64 soff, doff;
   unsigned n_executable = 0;
   bool allsame = true;
   edge_iterator ei;
@@ -3971,6 +3973,23 @@ visit_phi (gimple *phi)
          sameval = def;
        else if (!expressions_equal_p (def, sameval))
          {
+           /* We know we're arriving only with invariant addresses here,
+              try harder comparing them.  We can do some caching here
+              which we cannot do in expressions_equal_p.  */
+           if (TREE_CODE (def) == ADDR_EXPR
+               && TREE_CODE (sameval) == ADDR_EXPR
+               && sameval_base != (void *)-1)
+             {
+               if (!sameval_base)
+                 sameval_base = get_addr_base_and_unit_offset
+                                  (TREE_OPERAND (sameval, 0), &soff);
+               if (!sameval_base)
+                 sameval_base = (tree)(void *)-1;
+               else if ((get_addr_base_and_unit_offset
+                           (TREE_OPERAND (def, 0), &doff) == sameval_base)
+                        && known_eq (soff, doff))
+                 continue;
+             }
            allsame = false;
            break;
          }
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-68.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-68.c  (nonexistent)
+++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-68.c  (working copy)
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-fre1" } */
+
+struct S { char a[3]; char b[5]; } s = { "abc", "defg" };
+
+__SIZE_TYPE__
+foo (struct S s, int a, int b)
+{
+  char *p = (char *) &s.a[0];
+  if (a)
+    p = (char *) &s.a;
+  else if (b)
+    p = (char *) &s;
+  return __builtin_strlen (p);
+}
+
+__SIZE_TYPE__
+bar (int a, int b)
+{
+  char *p = (char *) &s.a[0];
+  if (a)
+    p = (char *) &s.a;
+  else if (b)
+    p = (char *) &s;
+  return __builtin_strlen (p);
+}
+
+/* { dg-final { scan-tree-dump-times "strlen \\\(&s" 2 "fre1" } } */

Reply via email to