@@ -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
@@ -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);
}
@@ -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)