Hi Richard,
This patch makes a minor change to genmatch to add reverse keyword for iterating
over user-defined operators in reverse in for-stmt and in define_operator_list.
eg:
(for op (bit_and bit_ior)
      rop (reverse (op))
  ...)

Verified gimple-match.c and generic-match.c remain unchanged with patch.
Bootstrap+test in progress on x86_64-unknown-linux-gnu.
OK to commit if passes ?

Thanks,
Prathamesh
2016-10-16  Prathamesh Kulkarni  <prathamesh.kulka...@linaro.org>

        * genmatch.c (parser::parse_for): Adjust for parsing reverse.
        (parser::parse_operator_list): Likewise.
        * match.pd: Use reverse in few patterns.
        * doc/match-and-simplify.texi: Add documentation for reverse.

diff --git a/gcc/doc/match-and-simplify.texi b/gcc/doc/match-and-simplify.texi
index aaa367b..9530224 100644
--- a/gcc/doc/match-and-simplify.texi
+++ b/gcc/doc/match-and-simplify.texi
@@ -420,3 +420,13 @@ You can use the above predicate like
 Which will match a bitwise and of an operand with its logical
 inverted value.
 
+@code{reverse} can be used in for and define_operator_list for iterating
+in reverse.
+
+@smallexample
+(for opo (bit_and bit_xor)
+     opi (reverse(opo))
+ (simplify
+  (opo:c (opi:c @@0 @@1) @@1)
+  (bit_and (bit_not @@0) @@1)))
+@end smallexample
diff --git a/gcc/genmatch.c b/gcc/genmatch.c
index fc4f598..0a96784 100644
--- a/gcc/genmatch.c
+++ b/gcc/genmatch.c
@@ -4506,7 +4506,15 @@ parser::parse_for (source_location)
       int arity = -1;
       while ((token = peek_ident ()) != 0)
        {
+         bool reverse = false;
          const char *oper = get_ident ();
+         if (!strcmp (oper, "reverse"))
+           {
+             reverse = true;
+             eat_token (CPP_OPEN_PAREN);
+             oper = get_ident ();
+             eat_token (CPP_CLOSE_PAREN);
+           }
          id_base *idb = get_operator (oper, true);
          if (idb == NULL)
            fatal_at (token, "no such operator '%s'", oper);
@@ -4527,10 +4535,29 @@ parser::parse_for (source_location)
          if (p)
            {
              if (p->is_oper_list)
-               op->substitutes.safe_splice (p->substitutes);
+               {
+                 if (reverse)
+                   {
+                     auto_vec<id_base *> substitutes;
+                     for (unsigned i = p->substitutes.length (); i > 0; --i)
+                       substitutes.safe_push (p->substitutes[i - 1]);
+                     op->substitutes.safe_splice (substitutes);
+                   }
+                 else
+                   op->substitutes.safe_splice (p->substitutes);
+               }
+             else if (reverse)
+               {
+                 auto_vec<id_base *> substitutes;
+                 for (unsigned i = p->substitutes.length (); i > 0; --i)
+                   substitutes.safe_push (p->substitutes[i - 1]);
+                 op->substitutes.safe_splice (substitutes);
+               }
              else
                fatal_at (token, "iterator cannot be used as operator-list");
            }
+         else if (reverse)
+           fatal_at (token, "reverse can only be used on user-defined 
operators");
          else 
            op->substitutes.safe_push (idb);
        }
@@ -4607,6 +4634,16 @@ parser::parse_operator_list (source_location)
     {
       token = peek (); 
       const char *oper = get_ident ();
+
+      bool reverse = false;
+      if (!strcmp (oper, "reverse"))
+       {
+         reverse = true;
+         eat_token (CPP_OPEN_PAREN);
+         oper = get_ident ();
+         eat_token (CPP_CLOSE_PAREN);
+       }
+
       id_base *idb = get_operator (oper, true);
       
       if (idb == 0)
@@ -4622,7 +4659,19 @@ parser::parse_operator_list (source_location)
 
       /* We allow composition of multiple operator lists.  */
       if (user_id *p = dyn_cast<user_id *> (idb))
-       op->substitutes.safe_splice (p->substitutes);
+       {
+         if (reverse)
+           {
+             auto_vec<id_base *> substitutes;
+             for (unsigned i = p->substitutes.length (); i > 0; --i)
+               substitutes.safe_push (p->substitutes[i - 1]);
+             op->substitutes.safe_splice (substitutes);
+           }
+         else
+           op->substitutes.safe_splice (p->substitutes);
+       }
+      else if (reverse)
+       fatal_at (token, "reverse can only be applied on user-defined 
operators");
       else
        op->substitutes.safe_push (idb);
     }
diff --git a/gcc/match.pd b/gcc/match.pd
index e4ff0e7..ac0ebc8 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -689,7 +689,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 /* ~x & ~y -> ~(x | y)
    ~x | ~y -> ~(x & y) */
 (for op (bit_and bit_ior)
-     rop (bit_ior bit_and)
+     rop (reverse(op))
  (simplify
   (op (convert1? (bit_not @0)) (convert2? (bit_not @1)))
   (if (element_precision (type) <= element_precision (TREE_TYPE (@0))
@@ -730,7 +730,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 
 /* Fold (X & Y) ^ Y and (X ^ Y) & Y as ~X & Y.  */
 (for opo (bit_and bit_xor)
-     opi (bit_xor bit_and)
+     opi (reverse(opo))
  (simplify
   (opo:c (opi:c @0 @1) @1) 
   (bit_and (bit_not @0) @1)))
@@ -860,7 +860,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
    (convert (bitop @0 (convert @1))))))
 
 (for bitop (bit_and bit_ior)
-     rbitop (bit_ior bit_and)
+     rbitop (reverse(bitop))
   /* (x | y) & x -> x */
   /* (x & y) | x -> x */
  (simplify
@@ -3336,7 +3336,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 /* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 -+ C1.  */
 (for cmp (eq ne)
  (for op (plus minus)
-      rop (minus plus)
+      rop (reverse(op))
   (simplify
    (cmp (op@3 @0 INTEGER_CST@1) INTEGER_CST@2)
    (if (!TREE_OVERFLOW (@1) && !TREE_OVERFLOW (@2)
@@ -3350,7 +3350,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
        (cmp @0 { res; }))))))))
 (for cmp (lt le gt ge)
  (for op (plus minus)
-      rop (minus plus)
+      rop (reverse(op))
   (simplify
    (cmp (op@3 @0 INTEGER_CST@1) INTEGER_CST@2)
    (if (!TREE_OVERFLOW (@1) && !TREE_OVERFLOW (@2)

Reply via email to