genmatch.c (comparison_code_p): New predicate.
authorRichard Biener <rguenther@suse.de>
Wed, 1 Jun 2016 09:00:57 +0000 (09:00 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 1 Jun 2016 09:00:57 +0000 (09:00 +0000)
2016-06-01  Richard Biener  <rguenther@suse.de>

* genmatch.c (comparison_code_p): New predicate.
(swap_tree_comparison): New function.
(commutate): Add for_vec parameter to append new for entries.
Support commutating relational operators by swapping it alongside
operands.
(lower_commutative): Adjust.
(dt_simplify::gen): Do not pass artificial operators to gen
functions.
(decision_tree::gen): Do not add artificial operators as parameters.
(parser::parse_expr): Verify operator commutativity when :c is
applied.  Allow :C to override this.
* match.pd: Adjust patterns to use :C instead of :c where required.

From-SVN: r236977

gcc/ChangeLog
gcc/genmatch.c
gcc/match.pd

index a27cc911359bb6e5fba21e26125072c07fa41830..d9142b9857b044c1afbecdff05ce2c27788bd0b9 100644 (file)
@@ -1,3 +1,18 @@
+2016-06-01  Richard Biener  <rguenther@suse.de>
+
+       * genmatch.c (comparison_code_p): New predicate.
+       (swap_tree_comparison): New function.
+       (commutate): Add for_vec parameter to append new for entries.
+       Support commutating relational operators by swapping it alongside
+       operands.
+       (lower_commutative): Adjust.
+       (dt_simplify::gen): Do not pass artificial operators to gen
+       functions.
+       (decision_tree::gen): Do not add artificial operators as parameters.
+       (parser::parse_expr): Verify operator commutativity when :c is
+       applied.  Allow :C to override this.
+       * match.pd: Adjust patterns to use :C instead of :c where required.
+
 2016-06-01  Patrick Palka  <ppalka@gcc.gnu.org>
 
        PR tree-optimization/71077
index 2b666ddd6f7c790e2f1beda3722391e3eee1e79c..9bb1279dc0021d45a837e3877997fe50efa8b673 100644 (file)
@@ -291,6 +291,35 @@ commutative_ternary_tree_code (enum tree_code code)
   return false;
 }
 
+/* Return true if CODE is a comparison.  */
+
+bool
+comparison_code_p (enum tree_code code)
+{
+  switch (code)
+    {
+    case EQ_EXPR:
+    case NE_EXPR:
+    case ORDERED_EXPR:
+    case UNORDERED_EXPR:
+    case LTGT_EXPR:
+    case UNEQ_EXPR:
+    case GT_EXPR:
+    case GE_EXPR:
+    case LT_EXPR:
+    case LE_EXPR:
+    case UNGT_EXPR:
+    case UNGE_EXPR:
+    case UNLT_EXPR:
+    case UNLE_EXPR:
+      return true;
+
+    default:
+      break;
+    }
+  return false;
+}
+
 
 /* Base class for all identifiers the parser knows.  */
 
@@ -528,6 +557,42 @@ get_operator (const char *id, bool allow_null = false)
   return operators->find_with_hash (&tem, tem.hashval);
 }
 
+/* Return the comparison operators that results if the operands are
+   swapped.  This is safe for floating-point.  */
+
+id_base *
+swap_tree_comparison (operator_id *p)
+{
+  switch (p->code)
+    {
+    case EQ_EXPR:
+    case NE_EXPR:
+    case ORDERED_EXPR:
+    case UNORDERED_EXPR:
+    case LTGT_EXPR:
+    case UNEQ_EXPR:
+      return p;
+    case GT_EXPR:
+      return get_operator ("LT_EXPR");
+    case GE_EXPR:
+      return get_operator ("LE_EXPR");
+    case LT_EXPR:
+      return get_operator ("GT_EXPR");
+    case LE_EXPR:
+      return get_operator ("GE_EXPR");
+    case UNGT_EXPR:
+      return get_operator ("UNLT_EXPR");
+    case UNGE_EXPR:
+      return get_operator ("UNLE_EXPR");
+    case UNLT_EXPR:
+      return get_operator ("UNGT_EXPR");
+    case UNLE_EXPR:
+      return get_operator ("UNGE_EXPR");
+    default:
+      gcc_unreachable ();
+    }
+}
+
 typedef hash_map<nofree_string_hash, unsigned> cid_map_t;
 
 
@@ -816,7 +881,7 @@ cartesian_product (const vec< vec<operand *> >& ops_vector,
 /* Lower OP to two operands in case it is marked as commutative.  */
 
 static vec<operand *>
-commutate (operand *op)
+commutate (operand *op, vec<vec<user_id *> > &for_vec)
 {
   vec<operand *> ret = vNULL;
 
@@ -827,7 +892,7 @@ commutate (operand *op)
          ret.safe_push (op);
          return ret;
        }
-      vec<operand *> v = commutate (c->what);
+      vec<operand *> v = commutate (c->what, for_vec);
       for (unsigned i = 0; i < v.length (); ++i)
        {
          capture *nc = new capture (c->location, c->where, v[i]);
@@ -845,7 +910,7 @@ commutate (operand *op)
 
   vec< vec<operand *> > ops_vector = vNULL;
   for (unsigned i = 0; i < e->ops.length (); ++i)
-    ops_vector.safe_push (commutate (e->ops[i]));
+    ops_vector.safe_push (commutate (e->ops[i], for_vec));
 
   auto_vec< vec<operand *> > result;
   auto_vec<operand *> v (e->ops.length ());
@@ -868,6 +933,50 @@ commutate (operand *op)
   for (unsigned i = 0; i < result.length (); ++i)
     {
       expr *ne = new expr (e);
+      if (operator_id *p = dyn_cast <operator_id *> (ne->operation))
+       {
+         if (comparison_code_p (p->code))
+           ne->operation = swap_tree_comparison (p);
+       }
+      else if (user_id *p = dyn_cast <user_id *> (ne->operation))
+       {
+         bool found_compare = false;
+         for (unsigned j = 0; j < p->substitutes.length (); ++j)
+           if (operator_id *q = dyn_cast <operator_id *> (p->substitutes[j]))
+             {
+               if (comparison_code_p (q->code)
+                   && swap_tree_comparison (q) != q)
+                 {
+                   found_compare = true;
+                   break;
+                 }
+             }
+         if (found_compare)
+           {
+             user_id *newop = new user_id ("<internal>");
+             for (unsigned j = 0; j < p->substitutes.length (); ++j)
+               {
+                 id_base *subst = p->substitutes[j];
+                 if (operator_id *q = dyn_cast <operator_id *> (subst))
+                   {
+                     if (comparison_code_p (q->code))
+                       subst = swap_tree_comparison (q);
+                   }
+                 newop->substitutes.safe_push (subst);
+               }
+             ne->operation = newop;
+             /* Search for 'p' inside the for vector and push 'newop'
+                to the same level.  */
+             for (unsigned j = 0; newop && j < for_vec.length (); ++j)
+               for (unsigned k = 0; k < for_vec[j].length (); ++k)
+                 if (for_vec[j][k] == p)
+                   {
+                     for_vec[j].safe_push (newop);
+                     newop = NULL;
+                     break;
+                   }
+           }
+       }
       ne->is_commutative = false;
       // result[i].length () is 2 since e->operation is binary
       for (unsigned j = result[i].length (); j; --j)
@@ -884,7 +993,7 @@ commutate (operand *op)
 static void
 lower_commutative (simplify *s, vec<simplify *>& simplifiers)
 {
-  vec<operand *> matchers = commutate (s->match);
+  vec<operand *> matchers = commutate (s->match, s->for_vec);
   for (unsigned i = 0; i < matchers.length (); ++i)
     {
       simplify *ns = new simplify (s->kind, matchers[i], s->result,
@@ -3248,7 +3357,8 @@ dt_simplify::gen (FILE *f, int indent, bool gimple)
          fprintf_indent (f, indent, "if (%s (res_code, res_ops, seq, "
                          "valueize, type, captures", info->fname);
          for (unsigned i = 0; i < s->for_subst_vec.length (); ++i)
-           fprintf (f, ", %s", s->for_subst_vec[i].second->id);
+           if (s->for_subst_vec[i].first->used)
+             fprintf (f, ", %s", s->for_subst_vec[i].second->id);
          fprintf (f, "))\n");
          fprintf_indent (f, indent, "  return true;\n");
        }
@@ -3260,7 +3370,10 @@ dt_simplify::gen (FILE *f, int indent, bool gimple)
            fprintf (f, ", op%d", i);
          fprintf (f, ", captures");
          for (unsigned i = 0; i < s->for_subst_vec.length (); ++i)
-           fprintf (f, ", %s", s->for_subst_vec[i].second->id);
+           {
+             if (s->for_subst_vec[i].first->used)
+               fprintf (f, ", %s", s->for_subst_vec[i].second->id);
+           }
          fprintf (f, ");\n");
          fprintf_indent (f, indent, "if (res) return res;\n");
        }
@@ -3269,6 +3382,8 @@ dt_simplify::gen (FILE *f, int indent, bool gimple)
     {
       for (unsigned i = 0; i < s->for_subst_vec.length (); ++i)
        {
+         if (! s->for_subst_vec[i].first->used)
+           continue;
          if (is_a <operator_id *> (s->for_subst_vec[i].second))
            fprintf_indent (f, indent, "enum tree_code %s = %s;\n",
                            s->for_subst_vec[i].first->id,
@@ -3425,6 +3540,8 @@ decision_tree::gen (FILE *f, bool gimple)
        }
       for (unsigned i = 0; i < s->s->s->for_subst_vec.length (); ++i)
        {
+         if (! s->s->s->for_subst_vec[i].first->used)
+           continue;
          if (is_a <operator_id *> (s->s->s->for_subst_vec[i].second))
            fprintf (f, ", enum tree_code ARG_UNUSED (%s)",
                     s->s->s->for_subst_vec[i].first->id);
@@ -3885,6 +4002,30 @@ parser::parse_expr ()
              while (*sp)
                {
                  if (*sp == 'c')
+                   {
+                     if (operator_id *p
+                           = dyn_cast<operator_id *> (e->operation))
+                       {
+                         if (!commutative_tree_code (p->code)
+                             && !comparison_code_p (p->code))
+                           fatal_at (token, "operation is not commutative");
+                       }
+                     else if (user_id *p = dyn_cast<user_id *> (e->operation))
+                       for (unsigned i = 0;
+                            i < p->substitutes.length (); ++i)
+                         {
+                           if (operator_id *q
+                                 = dyn_cast<operator_id *> (p->substitutes[i]))
+                             {
+                               if (!commutative_tree_code (q->code)
+                                   && !comparison_code_p (q->code))
+                                 fatal_at (token, "operation %s is not "
+                                           "commutative", q->id);
+                             }
+                         }
+                     is_commutative = true;
+                   }
+                 else if (*sp == 'C')
                    is_commutative = true;
                  else if (*sp == 's')
                    {
index 953c0703d9216d5f1f7826eca65b2758fc4fc048..24e716e656559915566439c3d5ae3dee32fec376 100644 (file)
@@ -189,7 +189,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 /* Optimize -A / A to -1.0 if we don't care about
    NaNs or Infinities.  */
 (simplify
- (rdiv:c @0 (negate @0))
+ (rdiv:C @0 (negate @0))
  (if (FLOAT_TYPE_P (type)
       && ! HONOR_NANS (type)
       && ! HONOR_INFINITIES (type))
@@ -2830,7 +2830,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 
 /* cabs(x+0i) or cabs(0+xi) -> abs(x).  */
 (simplify
- (CABS (complex:c @0 real_zerop@1))
+ (CABS (complex:C @0 real_zerop@1))
  (abs @0))
 
 /* trunc(trunc(x)) -> trunc(x), etc.  */