Rewrite part of and_comparisons_1 into match.pd.
authorMartin Liska <mliska@suse.cz>
Mon, 16 Sep 2019 14:22:36 +0000 (16:22 +0200)
committerMartin Liska <marxin@gcc.gnu.org>
Mon, 16 Sep 2019 14:22:36 +0000 (14:22 +0000)
2019-09-16  Martin Liska  <mliska@suse.cz>

* genmatch.c (dt_node::append_simplify): Do not print
warning when we have duplicate patterns belonging
to a same simplify rule.
* gimple-fold.c (and_comparisons_1): Remove matching moved to match.pd.
(maybe_fold_comparisons_from_match_pd): Handle
tcc_comparison as a results.
* match.pd: Handle (X == CST1) && (X OP2 CST2) conditions.

From-SVN: r275750

gcc/ChangeLog
gcc/genmatch.c
gcc/gimple-fold.c
gcc/match.pd

index 3bb383769e5a75c23b0aca8485c18780c0f0c97c..cc3a397d7c12f575c40fc8c1878ffb4955192e22 100644 (file)
@@ -1,3 +1,13 @@
+2019-09-16  Martin Liska  <mliska@suse.cz>
+
+       * genmatch.c (dt_node::append_simplify): Do not print
+       warning when we have duplicate patterns belonging
+       to a same simplify rule.
+       * gimple-fold.c (and_comparisons_1): Remove matching moved to match.pd.
+       (maybe_fold_comparisons_from_match_pd): Handle
+       tcc_comparison as a results.
+       * match.pd: Handle (X == CST1) && (X OP2 CST2) conditions.
+
 2019-09-16  Li Jia He  <helijia@linux.ibm.com>
            Qi Feng  <ffengqi@linux.ibm.com>
 
index 2e7bf27eedaebd37b54e007c16ee89f42bbc59f3..cede432cdc9d1d45aea674f6a3ce7f276fd5477b 100644 (file)
@@ -1894,10 +1894,15 @@ dt_node *
 dt_node::append_simplify (simplify *s, unsigned pattern_no,
                          dt_operand **indexes)
 {
+  dt_simplify *s2;
   dt_simplify *n = new dt_simplify (s, pattern_no, indexes);
   for (unsigned i = 0; i < kids.length (); ++i)
-    if (dt_simplify *s2 = dyn_cast <dt_simplify *> (kids[i]))
+    if ((s2 = dyn_cast <dt_simplify *> (kids[i]))
+       && (verbose >= 1
+           || s->match->location != s2->s->match->location))
       {
+       /* With a nested patters, it's hard to avoid these in order
+          to keep match.pd rules relatively small.  */
        warning_at (s->match->location, "duplicate pattern");
        warning_at (s2->s->match->location, "previous pattern defined here");
        print_operand (s->match, stderr);
index 6d9ba36783906ffa7f9b337ce7ce307e3976fcd9..f82bedc6593c8e900199c78758fa95eb3237da3c 100644 (file)
@@ -5620,136 +5620,6 @@ and_comparisons_1 (tree type, enum tree_code code1, tree op1a, tree op1b,
        return t;
     }
 
-  /* If both comparisons are of the same value against constants, we might
-     be able to merge them.  */
-  if (operand_equal_p (op1a, op2a, 0)
-      && TREE_CODE (op1b) == INTEGER_CST
-      && TREE_CODE (op2b) == INTEGER_CST)
-    {
-      int cmp = tree_int_cst_compare (op1b, op2b);
-
-      /* If we have (op1a == op1b), we should either be able to
-        return that or FALSE, depending on whether the constant op1b
-        also satisfies the other comparison against op2b.  */
-      if (code1 == EQ_EXPR)
-       {
-         bool done = true;
-         bool val;
-         switch (code2)
-           {
-           case EQ_EXPR: val = (cmp == 0); break;
-           case NE_EXPR: val = (cmp != 0); break;
-           case LT_EXPR: val = (cmp < 0); break;
-           case GT_EXPR: val = (cmp > 0); break;
-           case LE_EXPR: val = (cmp <= 0); break;
-           case GE_EXPR: val = (cmp >= 0); break;
-           default: done = false;
-           }
-         if (done)
-           {
-             if (val)
-               return fold_build2 (code1, boolean_type_node, op1a, op1b);
-             else
-               return boolean_false_node;
-           }
-       }
-      /* Likewise if the second comparison is an == comparison.  */
-      else if (code2 == EQ_EXPR)
-       {
-         bool done = true;
-         bool val;
-         switch (code1)
-           {
-           case EQ_EXPR: val = (cmp == 0); break;
-           case NE_EXPR: val = (cmp != 0); break;
-           case LT_EXPR: val = (cmp > 0); break;
-           case GT_EXPR: val = (cmp < 0); break;
-           case LE_EXPR: val = (cmp >= 0); break;
-           case GE_EXPR: val = (cmp <= 0); break;
-           default: done = false;
-           }
-         if (done)
-           {
-             if (val)
-               return fold_build2 (code2, boolean_type_node, op2a, op2b);
-             else
-               return boolean_false_node;
-           }
-       }
-
-      /* Same business with inequality tests.  */
-      else if (code1 == NE_EXPR)
-       {
-         bool val;
-         switch (code2)
-           {
-           case EQ_EXPR: val = (cmp != 0); break;
-           case NE_EXPR: val = (cmp == 0); break;
-           case LT_EXPR: val = (cmp >= 0); break;
-           case GT_EXPR: val = (cmp <= 0); break;
-           case LE_EXPR: val = (cmp > 0); break;
-           case GE_EXPR: val = (cmp < 0); break;
-           default:
-             val = false;
-           }
-         if (val)
-           return fold_build2 (code2, boolean_type_node, op2a, op2b);
-       }
-      else if (code2 == NE_EXPR)
-       {
-         bool val;
-         switch (code1)
-           {
-           case EQ_EXPR: val = (cmp == 0); break;
-           case NE_EXPR: val = (cmp != 0); break;
-           case LT_EXPR: val = (cmp <= 0); break;
-           case GT_EXPR: val = (cmp >= 0); break;
-           case LE_EXPR: val = (cmp < 0); break;
-           case GE_EXPR: val = (cmp > 0); break;
-           default:
-             val = false;
-           }
-         if (val)
-           return fold_build2 (code1, boolean_type_node, op1a, op1b);
-       }
-
-      /* Chose the more restrictive of two < or <= comparisons.  */
-      else if ((code1 == LT_EXPR || code1 == LE_EXPR)
-              && (code2 == LT_EXPR || code2 == LE_EXPR))
-       {
-         if ((cmp < 0) || (cmp == 0 && code1 == LT_EXPR))
-           return fold_build2 (code1, boolean_type_node, op1a, op1b);
-         else
-           return fold_build2 (code2, boolean_type_node, op2a, op2b);
-       }
-
-      /* Likewise chose the more restrictive of two > or >= comparisons.  */
-      else if ((code1 == GT_EXPR || code1 == GE_EXPR)
-              && (code2 == GT_EXPR || code2 == GE_EXPR))
-       {
-         if ((cmp > 0) || (cmp == 0 && code1 == GT_EXPR))
-           return fold_build2 (code1, boolean_type_node, op1a, op1b);
-         else
-           return fold_build2 (code2, boolean_type_node, op2a, op2b);
-       }
-
-      /* Check for singleton ranges.  */
-      else if (cmp == 0
-              && ((code1 == LE_EXPR && code2 == GE_EXPR)
-                  || (code1 == GE_EXPR && code2 == LE_EXPR)))
-       return fold_build2 (EQ_EXPR, boolean_type_node, op1a, op2b);
-
-      /* Check for disjoint ranges. */
-      else if (cmp <= 0
-              && (code1 == LT_EXPR || code1 == LE_EXPR)
-              && (code2 == GT_EXPR || code2 == GE_EXPR))
-       return boolean_false_node;
-      else if (cmp >= 0
-              && (code1 == GT_EXPR || code1 == GE_EXPR)
-              && (code2 == LT_EXPR || code2 == LE_EXPR))
-       return boolean_false_node;
-    }
-
   /* Perhaps the first comparison is (NAME != 0) or (NAME == 1) where
      NAME's definition is a truth value.  See if there are any simplifications
      that can be done against the NAME's definition.  */
@@ -5899,6 +5769,16 @@ maybe_fold_comparisons_from_match_pd (tree type, enum tree_code code,
          else
            return res;
        }
+      else if (op.code.is_tree_code ()
+              && TREE_CODE_CLASS ((tree_code)op.code) == tcc_comparison)
+       {
+         tree op0 = op.ops[0];
+         tree op1 = op.ops[1];
+         if (op0 == lhs1 || op0 == lhs2 || op1 == lhs1 || op1 == lhs2)
+           return NULL_TREE;  /* not simple */
+
+         return build2 ((enum tree_code)op.code, op.type, op0, op1);
+       }
     }
 
   return NULL_TREE;
index 2ca88000cadee33c34164c1c13d526bc97471e9d..ac80dd7dd152546de1e99ff57bf7163bfdaec35e 100644 (file)
@@ -1958,6 +1958,72 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     (if (eqne == NE_EXPR)
      { constant_boolean_node (true, type); }))))
 
+/* Convert (X == CST1) && (X OP2 CST2) to a known value
+   based on CST1 OP2 CST2.  Similarly for (X != CST1).  */
+
+(for code1 (eq ne)
+ (for code2 (eq ne lt gt le ge)
+  (simplify
+   (bit_and:c (code1@3 @0 INTEGER_CST@1) (code2@4 @0 INTEGER_CST@2))
+    (with
+     {
+      int cmp = tree_int_cst_compare (@1, @2);
+      bool val;
+      switch (code2)
+        {
+       case EQ_EXPR: val = (cmp == 0); break;
+       case NE_EXPR: val = (cmp != 0); break;
+       case LT_EXPR: val = (cmp < 0); break;
+       case GT_EXPR: val = (cmp > 0); break;
+       case LE_EXPR: val = (cmp <= 0); break;
+       case GE_EXPR: val = (cmp >= 0); break;
+       default: gcc_unreachable ();
+       }
+     }
+     (switch
+      (if (code1 == EQ_EXPR && val) @3)
+      (if (code1 == EQ_EXPR && !val) { constant_boolean_node (false, type); })
+      (if (code1 == NE_EXPR && !val) @4))))))
+
+/* Convert (X OP1 CST1) && (X OP2 CST2).  */
+
+(for code1 (lt le gt ge)
+ (for code2 (lt le gt ge)
+  (simplify
+  (bit_and (code1:c@3 @0 INTEGER_CST@1) (code2:c@4 @0 INTEGER_CST@2))
+   (with
+    {
+     int cmp = tree_int_cst_compare (@1, @2);
+    }
+    (switch
+     /* Choose the more restrictive of two < or <= comparisons.  */
+     (if ((code1 == LT_EXPR || code1 == LE_EXPR)
+         && (code2 == LT_EXPR || code2 == LE_EXPR))
+      (if ((cmp < 0) || (cmp == 0 && code1 == LT_EXPR))
+       @3
+       @4))
+     /* Likewise chose the more restrictive of two > or >= comparisons.  */
+     (if ((code1 == GT_EXPR || code1 == GE_EXPR)
+         && (code2 == GT_EXPR || code2 == GE_EXPR))
+      (if ((cmp > 0) || (cmp == 0 && code1 == GT_EXPR))
+       @3
+       @4))
+     /* Check for singleton ranges.  */
+     (if (cmp == 0
+         && ((code1 == LE_EXPR && code2 == GE_EXPR)
+           || (code1 == GE_EXPR && code2 == LE_EXPR)))
+      (eq @0 @1))
+     /* Check for disjoint ranges.  */
+     (if (cmp <= 0
+         && (code1 == LT_EXPR || code1 == LE_EXPR)
+         && (code2 == GT_EXPR || code2 == GE_EXPR))
+      { constant_boolean_node (false, type); })
+     (if (cmp >= 0
+         && (code1 == GT_EXPR || code1 == GE_EXPR)
+         && (code2 == LT_EXPR || code2 == LE_EXPR))
+      { constant_boolean_node (false, type); })
+     )))))
+
 /* We can't reassociate at all for saturating types.  */
 (if (!TYPE_SATURATING (type))