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)