re PR tree-optimization/88775 (Optimize std::string assignment)
authorJakub Jelinek <jakub@redhat.com>
Tue, 15 Jan 2019 08:11:00 +0000 (09:11 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 15 Jan 2019 08:11:00 +0000 (09:11 +0100)
PR tree-optimization/88775
* match.pd (cmp (convert1?@2 addr@0) (convert2? addr@1)): Optimize
equal == 0 equality pointer comparisons some more if compared in
integral types and either one points to an automatic var and the
other to a global, or we can prove at least one points to the middle
or both point to start or both point to end.

* gcc.dg/tree-ssa/pr88775-1.c: New test.
* gcc.dg/tree-ssa/pr88775-2.c: New test.

From-SVN: r267931

gcc/ChangeLog
gcc/match.pd
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/pr88775-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr88775-2.c [new file with mode: 0644]

index 03667c8d97ff19469e0e50fab9de9aa45ead5e04..c350d1cec0f661da64603593ceb22a33d77146d5 100644 (file)
@@ -1,3 +1,12 @@
+2019-01-15  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/88775
+       * match.pd (cmp (convert1?@2 addr@0) (convert2? addr@1)): Optimize
+       equal == 0 equality pointer comparisons some more if compared in
+       integral types and either one points to an automatic var and the
+       other to a global, or we can prove at least one points to the middle
+       or both point to start or both point to end.
+
 2019-01-14  Andi Kleen  <ak@linux.intel.com>
 
        * Makefile.in: Lower autofdo sampling rate by 10x.
index 60b12f94f9ee3e5c1fef2cbb8185663624a6c59d..bccf4df05a2f94785446719b3097b3f912fafe96 100644 (file)
@@ -3896,6 +3896,52 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
                    || TREE_CODE (base1) == SSA_NAME
                    || TREE_CODE (base1) == STRING_CST))
          equal = (base0 == base1);
+       if (equal == 0)
+        {
+          if (!DECL_P (base0) || !DECL_P (base1))
+            equal = 2;
+          else if (cmp != EQ_EXPR && cmp != NE_EXPR)
+            equal = 2;
+          /* If this is a pointer comparison, ignore for now even
+             valid equalities where one pointer is the offset zero
+             of one object and the other to one past end of another one.  */
+          else if (!INTEGRAL_TYPE_P (TREE_TYPE (@2)))
+            ;
+          /* Assume that automatic variables can't be adjacent to global
+             variables.  */
+          else if (is_global_var (base0) != is_global_var (base1))
+            ;
+          else
+            {
+              tree sz0 = DECL_SIZE_UNIT (base0);
+              tree sz1 = DECL_SIZE_UNIT (base1);
+              /* If sizes are unknown, e.g. VLA or not representable,
+                 punt.  */
+              if (!tree_fits_poly_int64_p (sz0)
+                  || !tree_fits_poly_int64_p (sz1))
+                equal = 2;
+              else
+                {
+                  poly_int64 size0 = tree_to_poly_int64 (sz0);
+                  poly_int64 size1 = tree_to_poly_int64 (sz1);
+                  /* If one offset is pointing (or could be) to the beginning
+                     of one object and the other is pointing to one past the
+                     last byte of the other object, punt.  */
+                  if (maybe_eq (off0, 0) && maybe_eq (off1, size1))
+                    equal = 2;
+                  else if (maybe_eq (off1, 0) && maybe_eq (off0, size0))
+                    equal = 2;
+                  /* If both offsets are the same, there are some cases
+                     we know that are ok.  Either if we know they aren't
+                     zero, or if we know both sizes are no zero.  */
+                  if (equal == 2
+                      && known_eq (off0, off1)
+                      && (known_ne (off0, 0)
+                          || (known_ne (size0, 0) && known_ne (size1, 0))))
+                    equal = 0;
+                }
+            }
+        }
      }
      (if (equal == 1
          && (cmp == EQ_EXPR || cmp == NE_EXPR
@@ -3918,16 +3964,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
        { constant_boolean_node (known_ge (off0, off1), type); })
        (if (cmp == GT_EXPR && (known_gt (off0, off1) || known_le (off0, off1)))
        { constant_boolean_node (known_gt (off0, off1), type); }))
-      (if (equal == 0
-          && DECL_P (base0) && DECL_P (base1)
-          /* If we compare this as integers require equal offset.  */
-          && (!INTEGRAL_TYPE_P (TREE_TYPE (@2))
-              || known_eq (off0, off1)))
-       (switch
-       (if (cmp == EQ_EXPR)
-        { constant_boolean_node (false, type); })
-       (if (cmp == NE_EXPR)
-        { constant_boolean_node (true, type); })))))))))
+      (if (equal == 0)
+       (switch
+        (if (cmp == EQ_EXPR)
+         { constant_boolean_node (false, type); })
+        (if (cmp == NE_EXPR)
+         { constant_boolean_node (true, type); })))))))))
 
 /* Simplify pointer equality compares using PTA.  */
 (for neeq (ne eq)
index 20c212c267aaca5f67161b93cebd96c336617340..810c45780a78d3713aae0a2e996499fa531026fd 100644 (file)
@@ -1,3 +1,9 @@
+2019-01-15  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/88775
+       * gcc.dg/tree-ssa/pr88775-1.c: New test.
+       * gcc.dg/tree-ssa/pr88775-2.c: New test.
+
 2019-01-14  Marek Polacek  <polacek@redhat.com>
 
        PR c++/88825 - ICE with bogus function return type deduction.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr88775-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr88775-1.c
new file mode 100644 (file)
index 0000000..779b2b7
--- /dev/null
@@ -0,0 +1,73 @@
+/* PR tree-optimization/88775 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "return 1;" 10 "optimized" } } */
+
+int a[64] = {};
+int b[64] = {};
+
+int
+f1 (void)
+{
+  return (__UINTPTR_TYPE__) &a[2] != (__UINTPTR_TYPE__) &b[2];
+}
+
+int
+f2 (void)
+{
+  return (__UINTPTR_TYPE__) &a[2] != (__UINTPTR_TYPE__) &b[10];
+}
+
+int
+f3 (void)
+{
+  return (__UINTPTR_TYPE__) &a[0] != (__UINTPTR_TYPE__) &b[0];
+}
+
+int
+f4 (void)
+{
+  return (__UINTPTR_TYPE__) &a[64] != (__UINTPTR_TYPE__) &b[64];
+}
+
+int
+f5 (void)
+{
+  int c[64] = {};
+  return (__UINTPTR_TYPE__) &a[0] != (__UINTPTR_TYPE__) &c[64];
+}
+
+int
+f6 (void)
+{
+  int c[64] = {};
+  return (__UINTPTR_TYPE__) &b[64] != (__UINTPTR_TYPE__) &c[0];
+}
+
+int
+f7 (void)
+{
+  int c[64] = {}, d[64] = {};
+  return (__UINTPTR_TYPE__) &c[2] != (__UINTPTR_TYPE__) &d[2];
+}
+
+int
+f8 (void)
+{
+  int c[64] = {}, d[64] = {};
+  return (__UINTPTR_TYPE__) &c[2] != (__UINTPTR_TYPE__) &d[10];
+}
+
+int
+f9 (void)
+{
+  int c[64] = {}, d[64] = {};
+  return (__UINTPTR_TYPE__) &c[0] != (__UINTPTR_TYPE__) &d[0];
+}
+
+int
+f10 (void)
+{
+  int c[64] = {}, d[64] = {};
+  return (__UINTPTR_TYPE__) &c[64] != (__UINTPTR_TYPE__) &d[64];
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr88775-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr88775-2.c
new file mode 100644 (file)
index 0000000..292ce6e
--- /dev/null
@@ -0,0 +1,43 @@
+/* PR tree-optimization/88775 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* These can't be decided until we know how the variables will
+   be laid out in memory.  */
+/* { dg-final { scan-tree-dump-not "return 1;" "optimized" } } */
+
+int a[64] = {};
+int b[64] = {};
+int e[0] = {};
+int f[0] = {};
+
+int
+f1 (void)
+{
+  return (__UINTPTR_TYPE__) &a[0] != (__UINTPTR_TYPE__) &b[64];
+}
+
+int
+f2 (void)
+{
+  return (__UINTPTR_TYPE__) &a[64] != (__UINTPTR_TYPE__) &b[0];
+}
+
+int
+f3 (void)
+{
+  return (__UINTPTR_TYPE__) &e[0] != (__UINTPTR_TYPE__) &f[0];
+}
+
+int
+f4 (void)
+{
+  int c[64] = {}, d[64] = {};
+  return (__UINTPTR_TYPE__) &c[0] != (__UINTPTR_TYPE__) &d[64];
+}
+
+int
+f5 (void)
+{
+  int c[64] = {}, d[64] = {};
+  return (__UINTPTR_TYPE__) &c[64] != (__UINTPTR_TYPE__) &d[0];
+}