[genmatch] Introduce reverse keyword

Message ID CAAgBjM=ZUtxZUjCzq0yh9+kaWo7tsFW7WVfjGBAADYRYPvZQRA@mail.gmail.com
State New
Headers show

Commit Message

Prathamesh Kulkarni Oct. 15, 2016, 7:28 p.m.
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.kulkarni@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.

Patch hide | download patch | download mbox

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)