match.pd: Move (X & C) eqne (Y & C) -> -> (X ^ Y) & C eqne 0 opt to match.pd [PR94718]
authorJakub Jelinek <jakub@redhat.com>
Mon, 4 May 2020 08:57:46 +0000 (10:57 +0200)
committerJakub Jelinek <jakub@redhat.com>
Mon, 4 May 2020 08:57:46 +0000 (10:57 +0200)
This patch moves this optimization from fold-const.c to match.pd where it
is actually much shorter to do and lets optimize even code not seen together
in a single expression in the source, as the first step towards fixing the
PR.

2020-05-04  Jakub Jelinek  <jakub@redhat.com>

PR tree-optimization/94718
* fold-const.c (fold_binary_loc): Move (X & C) eqne (Y & C)
-> (X ^ Y) & C eqne 0 optimization to ...
* match.pd ((X & C) op (Y & C) into (X ^ Y) & C op 0): ... here.

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

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

index 026ee8b185a8fdb946bcfb2e744faadc3e6d2d01..47eef982a59f27bb7e76de9ed0e319f76c77ad89 100644 (file)
@@ -1,5 +1,10 @@
 2020-05-04  Jakub Jelinek  <jakub@redhat.com>
 
+       PR tree-optimization/94718
+       * fold-const.c (fold_binary_loc): Move (X & C) eqne (Y & C)
+       -> (X ^ Y) & C eqne 0 optimization to ...
+       * match.pd ((X & C) op (Y & C) into (X ^ Y) & C op 0): ... here.
+
        * opts.c (get_option_html_page): Instead of hardcoding a list of
        options common between C/C++ and Fortran only use gfortran/
        documentation for warnings that have CL_Fortran set but not
index b79d059d7418c909db47f2d0976a89369c5536df..f054871746cd79c97a56b99cf36fe988a0738ba0 100644 (file)
@@ -11631,50 +11631,6 @@ fold_binary_loc (location_t loc, enum tree_code code, tree type,
          return omit_one_operand_loc (loc, type, res, arg0);
        }
 
-      /* Fold (X & C) op (Y & C) as (X ^ Y) & C op 0", and symmetries.  */
-      if (TREE_CODE (arg0) == BIT_AND_EXPR
-         && TREE_CODE (arg1) == BIT_AND_EXPR)
-       {
-         tree arg00 = TREE_OPERAND (arg0, 0);
-         tree arg01 = TREE_OPERAND (arg0, 1);
-         tree arg10 = TREE_OPERAND (arg1, 0);
-         tree arg11 = TREE_OPERAND (arg1, 1);
-         tree itype = TREE_TYPE (arg0);
-
-         if (operand_equal_p (arg01, arg11, 0))
-           {
-             tem = fold_convert_loc (loc, itype, arg10);
-             tem = fold_build2_loc (loc, BIT_XOR_EXPR, itype, arg00, tem);
-             tem = fold_build2_loc (loc, BIT_AND_EXPR, itype, tem, arg01);
-             return fold_build2_loc (loc, code, type, tem,
-                                     build_zero_cst (itype));
-           }
-         if (operand_equal_p (arg01, arg10, 0))
-           {
-             tem = fold_convert_loc (loc, itype, arg11);
-             tem = fold_build2_loc (loc, BIT_XOR_EXPR, itype, arg00, tem);
-             tem = fold_build2_loc (loc, BIT_AND_EXPR, itype, tem, arg01);
-             return fold_build2_loc (loc, code, type, tem,
-                                     build_zero_cst (itype));
-           }
-         if (operand_equal_p (arg00, arg11, 0))
-           {
-             tem = fold_convert_loc (loc, itype, arg10);
-             tem = fold_build2_loc (loc, BIT_XOR_EXPR, itype, arg01, tem);
-             tem = fold_build2_loc (loc, BIT_AND_EXPR, itype, tem, arg00);
-             return fold_build2_loc (loc, code, type, tem,
-                                     build_zero_cst (itype));
-           }
-         if (operand_equal_p (arg00, arg10, 0))
-           {
-             tem = fold_convert_loc (loc, itype, arg11);
-             tem = fold_build2_loc (loc, BIT_XOR_EXPR, itype, arg01, tem);
-             tem = fold_build2_loc (loc, BIT_AND_EXPR, itype, tem, arg00);
-             return fold_build2_loc (loc, code, type, tem,
-                                     build_zero_cst (itype));
-           }
-       }
-
       if (TREE_CODE (arg0) == BIT_XOR_EXPR
          && TREE_CODE (arg1) == BIT_XOR_EXPR)
        {
index 9cb37740f1e3427a0bca0bb1a037947c5fd1cbf7..123e670f9eeac781e13e9b93b6c8789e84a5aa43 100644 (file)
@@ -4335,7 +4335,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (simplify
   (cmp (convert? addr@0) integer_zerop)
   (if (tree_single_nonzero_warnv_p (@0, NULL))
-   { constant_boolean_node (cmp == NE_EXPR, type); })))
+   { constant_boolean_node (cmp == NE_EXPR, type); }))
+
+ /* (X & C) op (Y & C) into (X ^ Y) & C op 0.  */
+ (simplify
+  (cmp (bit_and:cs @0 @2) (bit_and:cs @1 @2))
+  (cmp (bit_and (bit_xor @0 @1) @2) { build_zero_cst (TREE_TYPE (@2)); })))
 
 /* If we have (A & C) == C where C is a power of 2, convert this into
    (A & C) != 0.  Similarly for NE_EXPR.  */
index ee5e80e7862f181469dc4ccdb243b47045902ecd..100870acedb458a2ff9a4430b2ae43544af36dbf 100644 (file)
@@ -1,3 +1,9 @@
+2020-05-04  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/94718
+       * gcc.dg/tree-ssa/pr94718-1.c: New test.
+       * gcc.dg/tree-ssa/pr94718-2.c: New test.
+
 2020-05-03  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/limited1_inner.adb (Finalize): Use 'Unrestricted_Access.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94718-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94718-1.c
new file mode 100644 (file)
index 0000000..510eec8
--- /dev/null
@@ -0,0 +1,49 @@
+/* PR tree-optimization/94718 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-ipa-icf -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "= \[xy]_\[0-9]+\\\(D\\\) \\^ \[xy]_\[0-9]+\\\(D\\\);" 6 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\[0-9]+ < 0;" 6 "optimized" } } */
+
+#define I (-__INT_MAX__ - 1)
+
+int
+f1 (int x, int y)
+{
+  return (x & I) != (y & I);
+}
+
+int
+f2 (int x, int y)
+{
+  return (~x & I) != (~y & I);
+}
+
+int
+f3 (int x, int y)
+{
+  return ((x & I) ^ I) != ((y & I) ^ I);
+}
+
+int
+f4 (int x, int y)
+{
+  int s = (x & I);
+  int t = (y & I);
+  return s != t;
+}
+
+int
+f5 (int x, int y)
+{
+  int s = (~x & I);
+  int t = (~y & I);
+  return s != t;
+}
+
+int
+f6 (int x, int y)
+{
+  int s = ((x & I) ^ I);
+  int t = ((y & I) ^ I);
+  return s != t;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94718-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94718-2.c
new file mode 100644 (file)
index 0000000..15a3d74
--- /dev/null
@@ -0,0 +1,49 @@
+/* PR tree-optimization/94718 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-ipa-icf -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "= \[xy]_\[0-9]+\\\(D\\\) \\^ \[xy]_\[0-9]+\\\(D\\\);" 6 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\[0-9]+ >= 0;" 6 "optimized" } } */
+
+#define I (-__INT_MAX__ - 1)
+
+int
+f1 (int x, int y)
+{
+  return (x & I) == (y & I);
+}
+
+int
+f2 (int x, int y)
+{
+  return (~x & I) == (~y & I);
+}
+
+int
+f3 (int x, int y)
+{
+  return ((x & I) ^ I) == ((y & I) ^ I);
+}
+
+int
+f4 (int x, int y)
+{
+  int s = (x & I);
+  int t = (y & I);
+  return s == t;
+}
+
+int
+f5 (int x, int y)
+{
+  int s = (~x & I);
+  int t = (~y & I);
+  return s == t;
+}
+
+int
+f6 (int x, int y)
+{
+  int s = ((x & I) ^ I);
+  int t = ((y & I) ^ I);
+  return s == t;
+}