Fixed a silly mistake in match-bitwise.pd (I had put ')' at wrong place). This patch also checks if operator-list is used outside for-pattern (in parser::parse_operation).
* genmatch.c (user_id): Add new member is_oper_list. (user_id::user_id): Add new default argument. (parser::parse_operator_list): New member function in parser. (add_substitute): New function. (flatten_substitutes): Likewise. (parser::parse_for): Call add_substitute. (parser::parse_pattern): Call parser::parse_operator_list. (parser::parse_operation): Put check for operator-list. * match-bitwise.pd (bitwise_ors): New operator-list. (bitwise_ops): Likewise. Use bitwise_ors and bitwise_ops in patterns. * match-comparison.pd (eq_ops): New operator-list. (cmp_ops): Likewise. Use cmp_ops and eq_ops in patterns. Thanks, Prathamesh On Sat, Oct 25, 2014 at 10:44 PM, Prathamesh Kulkarni <bilbotheelffri...@gmail.com> wrote: > Hi, > This patch adds support for operator-lists, and uses > them in match-bitwise.pd and match-comparison.pd > > * genmatch.c > (parser::parse_operator_list): New member function in parser. > (add_substitute): New function. > (flatten_substitutes): Likewise. > (parser::parse_for): Call add_substitute. > (parser::parse_pattern): Call parser::parse_operator_list. > > * match-bitwise.pd > (bitwise_ors): New operator-list. > (bitwise_ops): Likewise. > Use bitwise_ors and bitwise_ops in patterns. > > * match-comparison.pd > (eq_ops): New operator-list. > (cmp_ops): Likewise. > Use cmp_ops and eq_ops in patterns. > > Thanks, > Prathamesh
Index: gcc/genmatch.c =================================================================== --- gcc/genmatch.c (revision 216673) +++ gcc/genmatch.c (working copy) @@ -218,9 +218,10 @@ struct user_id : public id_base { - user_id (const char *id_) - : id_base (id_base::USER, id_), substitutes (vNULL) {} + user_id (const char *id_, bool is_oper_list_ = false) + : id_base (id_base::USER, id_), substitutes (vNULL), is_oper_list (is_oper_list_) {} vec<id_base *> substitutes; + bool is_oper_list; }; template<> @@ -2419,6 +2420,7 @@ void parse_simplify (source_location, vec<simplify *>&, predicate_id *, expr *); void parse_for (source_location); + void parse_operator_list (); void parse_if (source_location); void parse_predicates (source_location); @@ -2582,8 +2584,14 @@ || strcmp (id, "convert2") == 0) fatal_at (id_tok, "expected '?' after conditional operator"); id_base *op = get_operator (id); + if (!op) fatal_at (id_tok, "unknown operator %s", id); + + user_id *uid; + if ((uid = dyn_cast<user_id *> (op)) != 0 && uid->is_oper_list) + fatal_at (id_tok, "operator-list '%s' can be used only in for", uid->id); + return op; } @@ -2900,6 +2908,20 @@ /* Parsing of the outer control structures. */ +bool +add_substitute (user_id *op, id_base *idb, int& arity) +{ + if (arity == -1) + arity = idb->nargs; + else if (idb->nargs == -1) + ; + else if (idb->nargs != arity) + return false; + + op->substitutes.safe_push (idb); + return true; +} + /* Parse a for expression for = '(' 'for' <subst>... <pattern> ')' subst = <ident> '(' <ident>... ')' */ @@ -2938,15 +2960,16 @@ if (*idb == CONVERT0 || *idb == CONVERT1 || *idb == CONVERT2) fatal_at (token, "conditional operators cannot be used inside for"); - if (arity == -1) - arity = idb->nargs; - else if (idb->nargs == -1) - ; - else if (idb->nargs != arity) - fatal_at (token, "operator '%s' with arity %d does not match " - "others with arity %d", oper, idb->nargs, arity); + vec<id_base *> substitutes = vNULL; + if (idb->kind == id_base::USER) + substitutes = (as_a<user_id *> (idb))->substitutes; + else + substitutes.safe_push (idb); - op->substitutes.safe_push (idb); + for (unsigned si = 0; si < substitutes.length (); ++si) + if (!add_substitute (op, substitutes[si], arity)) + fatal_at (token, "operator '%s' with arity %d does not match " + "others with arity %d", oper, idb->nargs, arity); } op->nargs = arity; token = expect (CPP_CLOSE_PAREN); @@ -2997,6 +3020,55 @@ operators->remove_elt (user_ids[i]); } +void +flatten_substitutes (vec<id_base *>& ids, vec<id_base *>& substitutes) +{ + user_id *op; + + for (unsigned i = 0; i < ids.length (); ++i) + if ((op = dyn_cast<user_id *> (ids[i])) != 0) + flatten_substitutes (op->substitutes, substitutes); + else + substitutes.safe_push (ids[i]); +} + +void +parser::parse_operator_list () +{ + const char *id = get_ident (); + user_id *op = new user_id (id, true); + vec<const cpp_token *> user_id_tokens = vNULL; + + id_base **slot = operators->find_slot_with_hash (op, op->hashval, INSERT); + if (*slot) + fatal ("operator %s already defined", id); + *slot = op; + + const cpp_token *token; + vec<id_base *> ids = vNULL; + + while ((token = peek_ident ()) != 0) + { + const char *oper = get_ident (); + id_base *p = get_operator (oper); + if (p == 0) + fatal_at (token, "%s is not defined", oper); + ids.safe_push (p); + user_id_tokens.safe_push (token); + } + + if (ids.length () == 0) + fatal_at (token, "operator list cannot be empty"); + + flatten_substitutes (ids, op->substitutes); + int arity = op->substitutes[0]->nargs; + for (unsigned i = 1; i < op->substitutes.length (); ++i) + if (op->substitutes[i]->nargs != -1 && arity != op->substitutes[i]->nargs) + fatal_at (user_id_tokens[i], "operator '%s' with arity %d does not match " + "others with arity %d", op->substitutes[i]->id, op->substitutes[i]->nargs, arity); +} + + /* Parse an outer if expression. if = '(' 'if' '(' <c-expr> ')' <pattern> ')' */ @@ -3097,6 +3169,8 @@ fatal_at (token, "define_predicates inside if or for is not supported"); parse_predicates (token->src_loc); } + else if (strcmp (id, "define_operator_list") == 0) + parse_operator_list (); else fatal_at (token, "expected %s'simplify', 'match', 'for' or 'if'", active_ifs.length () == 0 && active_fors.length () == 0 Index: gcc/match-bitwise.pd =================================================================== --- gcc/match-bitwise.pd (revision 216673) +++ gcc/match-bitwise.pd (working copy) @@ -17,6 +17,9 @@ along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ +(define_operator_list bitwise_ors bit_ior bit_xor) +(define_operator_list bitwise_ops bit_and bitwise_ors) + /* Try to fold (type) X op CST -> (type) (X op ((type-x) CST)) when profitable. */ /* For bitwise binary operations apply operand conversions to the @@ -23,7 +26,7 @@ binary operation result instead of to the operands. This allows to combine successive conversions and bitwise binary operations. */ /* We combine the above two cases by using a conditional convert. */ -(for bitop (bit_and bit_ior bit_xor) +(for bitop (bitwise_ops) (simplify (bitop (convert @0) (convert? @1)) (if (((TREE_CODE (@1) == INTEGER_CST @@ -48,7 +51,7 @@ (convert (bitop @0 (convert @1)))))) /* Simplify (A & B) OP0 (C & B) to (A OP0 C) & B. */ -(for bitop (bit_and bit_ior bit_xor) +(for bitop (bitwise_ops) (simplify (bitop (bit_and:c @0 @1) (bit_and @2 @1)) (bit_and (bitop @0 @2) @1))) @@ -59,7 +62,7 @@ (bit_ior (bit_and @0 @2) (bit_and @1 @2))) /* Combine successive equal operations with constants. */ -(for bitop (bit_and bit_ior bit_xor) +(for bitop (bitwise_ops) (simplify (bitop (bitop @0 CONSTANT_CLASS_P@1) CONSTANT_CLASS_P@2) (bitop @0 (bitop @1 @2)))) @@ -95,7 +98,7 @@ (bit_and @0 (logical_inverted_value @0)) { build_zero_cst (type); }) /* X | !X and X ^ !X -> 1, , if X is truth-valued. */ -(for op (bit_ior bit_xor) +(for op (bitwise_ors) (simplify (op truth_valued_p@0 (logical_inverted_value @0)) { build_one_cst (type); })) @@ -110,7 +113,7 @@ (bit_and:c @0 (bit_not @0)) { build_zero_cst (type); }) /* X | ~X -> ~0, X ^ ~X -> ~0. */ -(for bitop (bit_ior bit_xor) +(for bitop (bitwise_ors) (simplify (bitop:c @0 (bit_not @0)) { build_all_ones_cst (type); })) @@ -118,7 +121,7 @@ Also X != 1 vs. X ^ 1 vs ~X wants canonicalization for truth values. */ #if 0 /* FIXME. truth_valued_ssa_name isn't exported either. */ -(for bitop (bit_and bit_ior bit_xor) +(for bitop (bitwise_ops) /* X & (X == 0) -> 0. */ /* X | (X == 0) -> 1. */ (simplify @@ -201,7 +204,7 @@ /* Simple association cases that cancel one operand. */ /* ((a OP b) & ~a) -> (b & ~a) OP 0 */ -(for bitop (bit_and bit_ior bit_xor) +(for bitop (bitwise_ops) (simplify (bit_and:c (bitop:c @0 @1) (bit_not@2 @0)) (bitop (bit_and @1 @2) { build_zero_cst (type); }))) @@ -264,7 +267,7 @@ /* Similar transform for vector permute. ??? Missing an easy way to check if a mask is a reverse operation of another mask (most masks are not reversible). */ -(for bitop (bit_xor bit_ior bit_and) +(for bitop (bitwise_ops) (simplify (bitop (vec_perm @1 @2 @0) (vec_perm @3 @4 @0)) (vec_perm (bitop @1 @3) (bitop @2 @4) @0))) Index: gcc/match-comparison.pd =================================================================== --- gcc/match-comparison.pd (revision 216673) +++ gcc/match-comparison.pd (working copy) @@ -1,5 +1,8 @@ /* From fold_binary. */ +(define_operator_list eq_ops eq ne) +(define_operator_list cmp_ops eq_ops lt le gt ge) + /* On GIMPLE bool != 0 is simply the canonical way to express a condition in COND_EXPRs and GIMPLE_CONDs. ??? Of course for assignments we still may want to strip those... */ @@ -15,7 +18,7 @@ @0))) /* Distribute operations in equality compares. */ -(for op (eq ne) +(for op (eq_ops) /* -exp op CST is exp op -CST. */ (simplify /* ??? fix fold-const to use negate_expr_p */ @@ -29,7 +32,7 @@ /* From fold_comparison, in the order of transforms in there. */ /* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 -+ C1. */ -(for cmp (lt le eq ge gt ne) +(for cmp (cmp_ops) (for op (plus minus) (simplify (cmp (op @0 INTEGER_CST@1) INTEGER_CST@2) @@ -47,7 +50,7 @@ is undefined for the type, but performing it here badly interacts with the transformation in fold_cond_expr_with_comparison which attempts to synthetize ABS_EXPR. */ -(for cmp (eq ne) +(for cmp (eq_ops) (simplify (cmp (minus @0 @1) integer_zerop) (cmp @0 @1))) @@ -65,7 +68,7 @@ #endif /* Simplify X * C1 CMP 0 to X CMP 0 if C1 is not zero. */ -(for op (lt le eq ne ge gt) +(for op (cmp_ops) (simplify (op (mult @0 INTEGER_CST@1) integer_zerop@2) /* In fold-const.c we have this and the following pattern @@ -131,13 +134,13 @@ #endif /* Fold ~X op ~Y as Y op X. */ -(for cmp (lt le eq ge gt ne) +(for cmp (cmp_ops) (simplify (cmp (bit_not @0) (bit_not @1)) (cmp @1 @0))) /* Fold ~X op C as X op' ~C, where op' is the swapped comparison. */ -(for cmp (lt le eq ge gt ne) +(for cmp (cmp_ops) (simplify (cmp (bit_not @0) @1) /* ??? (for cst in INTEGER_CST VECTOR_CST) is not supported yet. */