Hi, This patch adds support for operator-lists to be used in expression. I reuse operator-list as the iterator. This is not really valid since user-defined operator-lists cannot be iterator in 'for', but it was convenient to reuse operator-list as a 'for' iterator and lower_for doesn't care about that. eg: (define_operator_list list1 plus minus)
(simplify (list1 @x integer_zerop) (non_lvalue @x)) is wrapped into 'for' as: (lower_operator_list): (for list1 (plus minus) (simplify (list1 @x integer_zerop) (non_lvalue @x))) this is not really valid since we reject list1 to be used as iterator if it were written by user. Is this okay or should I introduce an explicit temporary iterator ? so it gets lowered to something like: (for tmp1 (list1) (simplify (tmp1 @x integer_zerop) (non_lvalue @x))) * genmatch.c (fatal_at): New overloaded function. (simplify::oper_lists): New member. (simplify::simplify): Add default argument. (lower_commutative): Adjust call to simplify::simplify. (lower_opt_convert): Likewise. (lower_operator_list): New function. (lower): Call lower_operator_list. (parser::parsing_for_p): New member function. (parser::oper_lists): New member. (parser::parse_operation): Check for operator-list. (parser::parse_c_expr): Likewise. (parser::parse_simplify): Reset parser::oper_lists. Adjust call to simplify::simplify. (parser::parser): Initialize parser::oper_lists. * match-builtin.pd: Adjust patten to use SQRTs and POWs. Thanks, Prathamesh
Index: gcc/genmatch.c =================================================================== --- gcc/genmatch.c (revision 217284) +++ gcc/genmatch.c (working copy) @@ -110,6 +110,18 @@ #if GCC_VERSION >= 4001 __attribute__((format (printf, 2, 3))) #endif +fatal_at (source_location loc, const char *msg, ...) +{ + va_list ap; + va_start (ap, msg); + error_cb (NULL, CPP_DL_FATAL, 0, loc, 0, msg, &ap); + va_end (ap); +} + +static void +#if GCC_VERSION >= 4001 +__attribute__((format (printf, 2, 3))) +#endif warning_at (const cpp_token *tk, const char *msg, ...) { va_list ap; @@ -549,11 +561,11 @@ simplify (operand *match_, source_location match_location_, struct operand *result_, source_location result_location_, vec<if_or_with> ifexpr_vec_, vec<vec<user_id *> > for_vec_, - cid_map_t *capture_ids_) + cid_map_t *capture_ids_, vec<user_id *> oper_lists_ = vNULL) : match (match_), match_location (match_location_), result (result_), result_location (result_location_), ifexpr_vec (ifexpr_vec_), for_vec (for_vec_), - capture_ids (capture_ids_), capture_max (capture_ids_->elements () - 1) {} + capture_ids (capture_ids_), capture_max (capture_ids_->elements () - 1), oper_lists (oper_lists_) {} /* The expression that is matched against the GENERIC or GIMPLE IL. */ operand *match; @@ -572,6 +584,8 @@ /* A map of capture identifiers to indexes. */ cid_map_t *capture_ids; int capture_max; + /* collected operator-list used in expression */ + vec<user_id *> oper_lists; }; /* Debugging routines for dumping the AST. */ @@ -721,7 +735,7 @@ { simplify *ns = new simplify (matchers[i], s->match_location, s->result, s->result_location, s->ifexpr_vec, - s->for_vec, s->capture_ids); + s->for_vec, s->capture_ids, s->oper_lists); simplifiers.safe_push (ns); } } @@ -837,7 +851,7 @@ { simplify *ns = new simplify (matchers[i], s->match_location, s->result, s->result_location, s->ifexpr_vec, - s->for_vec, s->capture_ids); + s->for_vec, s->capture_ids, s->oper_lists); simplifiers.safe_push (ns); } } @@ -934,6 +948,38 @@ simplifiers.safe_push (worklist[i]); } +static void +lower_operator_list (simplify *s, vec<simplify *>& simplifiers) +{ + vec<user_id *> oper_lists = s->oper_lists; + if (oper_lists == vNULL) + { + simplifiers.safe_push (s); + return; + } + + unsigned min = oper_lists[0]->substitutes.length (); + for (unsigned i = 1; i < oper_lists.length (); ++i) + if (min > oper_lists[i]->substitutes.length ()) + min = oper_lists[i]->substitutes.length (); + + for (unsigned i = 0; i < oper_lists.length (); ++i) + if (oper_lists[i]->substitutes.length () % min != 0) + fatal_at (s->match_location, "All user-defined identifiers must have a multiple number " + "of operator substittions of the smallest number of substitutions"); + + vec< vec<user_id *> > for_vec = vNULL; + for_vec.safe_push (oper_lists); + + simplify ns (s->match, s->match_location, + s->result, s->result_location, + s->ifexpr_vec, for_vec, + s->capture_ids); + + lower_for (&ns, simplifiers); +} + + /* Lower the AST for everything in SIMPLIFIERS. */ static void @@ -947,14 +993,15 @@ for (unsigned i = 0; i < out_simplifiers0.length (); ++i) lower_commutative (out_simplifiers0[i], out_simplifiers1); + auto_vec<simplify *> out_simplifiers2; + for (unsigned i = 0; i < out_simplifiers1.length (); ++i) + lower_operator_list (out_simplifiers1[i], out_simplifiers2); + simplifiers.truncate (0); - for (unsigned i = 0; i < out_simplifiers1.length (); ++i) - lower_for (out_simplifiers1[i], simplifiers); + for (unsigned i = 0; i < out_simplifiers2.length (); ++i) + lower_for (out_simplifiers2[i], simplifiers); } - - - /* The decision tree built for generating GIMPLE and GENERIC pattern matching code. It represents the 'match' expression of all simplifies and has those as its leafs. */ @@ -2498,10 +2545,13 @@ void parse_if (source_location); void parse_predicates (source_location); void parse_operator_list (source_location); + + bool parsing_for_p () { return active_fors.length () != 0; } cpp_reader *r; vec<if_or_with> active_ifs; vec<vec<user_id *> > active_fors; + vec<user_id *> oper_lists; cid_map_t *capture_ids; @@ -2669,8 +2719,11 @@ user_id *p = dyn_cast<user_id *> (op); if (p && p->is_oper_list) - fatal_at (id_tok, "operator-list not allowed in expression"); - + { + if (parsing_for_p ()) + fatal_at (id_tok, "operator-list not allowed in expression enclosed in 'for'"); + oper_lists.safe_push (p); + } return op; } @@ -2807,8 +2860,13 @@ /* If this is possibly a user-defined identifier mark it used. */ if (token->type == CPP_NAME) - get_operator ((const char *)CPP_HASHNODE - (token->val.node.node)->ident.str); + { + id_base *idb = get_operator ((const char *)CPP_HASHNODE + (token->val.node.node)->ident.str); + user_id *p; + if (idb && (p = dyn_cast<user_id *> (idb)) && p->is_oper_list) + oper_lists.safe_push (p); + } /* Record the token. */ code.safe_push (*token); @@ -2893,6 +2951,8 @@ { /* Reset the capture map. */ capture_ids = new cid_map_t; + /* Reset oper_lists */ + oper_lists = vNULL; const cpp_token *loc = peek (); parsing_match_operand = true; @@ -2915,7 +2975,7 @@ simplifiers.safe_push (new simplify (match, match_location, result, token->src_loc, active_ifs.copy (), active_fors.copy (), - capture_ids)); + capture_ids, oper_lists.copy ())); return; } @@ -2941,7 +3001,7 @@ simplifiers.safe_push (new simplify (match, match_location, result, paren_loc, active_ifs.copy (), - active_fors.copy (), capture_ids)); + active_fors.copy (), capture_ids, oper_lists.copy ())); } } else if (peek_ident ("with")) @@ -2960,7 +3020,7 @@ simplifiers.safe_push (new simplify (match, match_location, op, token->src_loc, active_ifs.copy (), - active_fors.copy (), capture_ids)); + active_fors.copy (), capture_ids, oper_lists.copy ())); eat_token (CPP_CLOSE_PAREN); /* A "default" result closes the enclosing scope. */ if (active_ifs.length () > active_ifs_len) @@ -2992,7 +3052,7 @@ (new simplify (match, match_location, matcher ? result : parse_op (), token->src_loc, active_ifs.copy (), - active_fors.copy (), capture_ids)); + active_fors.copy (), capture_ids, oper_lists.copy ())); /* A "default" result closes the enclosing scope. */ if (active_ifs.length () > active_ifs_len) { @@ -3286,6 +3346,7 @@ active_ifs = vNULL; active_fors = vNULL; simplifiers = vNULL; + oper_lists = vNULL; user_predicates = vNULL; parsing_match_operand = false; Index: gcc/match-builtin.pd =================================================================== --- gcc/match-builtin.pd (revision 217284) +++ gcc/match-builtin.pd (working copy) @@ -147,8 +147,6 @@ dconstroot = real_value_truncate (TYPE_MODE (type), dconstroot); } (POW @0 { build_real (type, dconstroot); })))) /* Optimize sqrt(pow(x,y)) = pow(|x|,y*0.5). */ - (for SQRT (BUILT_IN_SQRTF BUILT_IN_SQRT BUILT_IN_SQRTL) - POW (BUILT_IN_POWF BUILT_IN_POW BUILT_IN_POWL) (simplify - (SQRT (POW @0 @1)) - (POW (abs @0) (mult @1 { build_real (TREE_TYPE (@1), dconsthalf); }))))) + (SQRTs (POWs @0 @1)) + (POWs (abs @0) (mult @1 { build_real (TREE_TYPE (@1), dconsthalf); }))))