Hi, This patch adds support for outer-if expressions. Couple of issues: a) Doesn't interop with for-pattern, since we don't replace identifier in c-expr yet, and this gets more complicated with addition of outer-if.
b) I removed ifexpr-locations for now. I am not sure where to output if-expr locations when there are multiple if-exprs (one outer and one inner). * genmatch.c (simplify::ifexpr): Remove. (simplify::ifexpr_location): Likewise. (simplify::simplify): Adjust to changes in simplify and add parameter ifexpr_vec_. (dt_simplify::gen_gimple): Adjust to changes in simplify. (dt_simplify::gen_generic): Likewise. (parse_if): New function. (parse_pattern): Add call to parse_if. * match.pd: Use outer-if for plus-minus patterns. Thanks, Prathamesh
Index: gcc/genmatch.c =================================================================== --- gcc/genmatch.c (revision 212928) +++ gcc/genmatch.c (working copy) @@ -298,18 +298,17 @@ e_operation::e_operation (const char *id struct simplify { simplify (const char *name_, operand *match_, source_location match_location_, - struct operand *ifexpr_, source_location ifexpr_location_, - struct operand *result_, source_location result_location_) + struct operand *result_, source_location result_location_, vec<operand *> ifexpr_vec_ = vNULL) : name (name_), match (match_), match_location (match_location_), - ifexpr (ifexpr_), ifexpr_location (ifexpr_location_), - result (result_), result_location (result_location_) {} + result (result_), result_location (result_location_), + ifexpr_vec (ifexpr_vec_) {} + const char *name; operand *match; source_location match_location; - struct operand *ifexpr; - source_location ifexpr_location; struct operand *result; source_location result_location; + vec<operand *> ifexpr_vec; }; struct dt_node @@ -554,8 +553,7 @@ lower_commutative (simplify *s, vec<simp for (unsigned i = 0; i < matchers.length (); ++i) { simplify *ns = new simplify (s->name, matchers[i], s->match_location, - s->ifexpr, s->ifexpr_location, - s->result, s->result_location); + s->result, s->result_location, s->ifexpr_vec); simplifiers.safe_push (ns); } } @@ -1452,14 +1450,21 @@ dt_simplify::gen_gimple (FILE *f) fprintf (f, "captures[%u] = %s;\n", i, indexes[i]->get_name (opname)); } - if (s->ifexpr) - { - output_line_directive (f, s->ifexpr_location); - fprintf (f, "if ("); - s->ifexpr->gen_transform (f, NULL, true); - fprintf (f, ")\n"); - fprintf (f, "{\n"); + if (s->ifexpr_vec != vNULL) + { + fprintf (f, "if ("); + // we add in LIFO order, so traverse backwards + for (unsigned i = s->ifexpr_vec.length (); i; --i) + { + fprintf (f, "("); + s->ifexpr_vec[i - 1]->gen_transform (f, NULL, true); + fprintf (f, ")"); + if (i > 1) + fprintf (f, " && "); } + fprintf (f, ")\n"); + fprintf (f, "{\n"); + } output_line_directive (f, s->result_location); if (s->result->type == operand::OP_EXPR) @@ -1487,7 +1492,7 @@ dt_simplify::gen_gimple (FILE *f) gcc_unreachable (); fprintf (f, "return true;\n"); - if (s->ifexpr) + if (s->ifexpr_vec != vNULL) fprintf (f, "}\n"); fprintf (f, "}\n"); @@ -1510,14 +1515,22 @@ dt_simplify::gen_generic (FILE *f) fprintf (f, "captures[%u] = %s;\n", i, indexes[i]->get_name (opname)); } - if (s->ifexpr) - { - output_line_directive (f, s->ifexpr_location); - fprintf (f, "if ("); - s->ifexpr->gen_transform (f, NULL, false); - fprintf (f, ")\n"); - fprintf (f, "{\n"); - } + if (s->ifexpr_vec != vNULL) + { + fprintf (f, "if (\n"); + // we add in LIFO order, so traverse backwards + for (unsigned i = s->ifexpr_vec.length (); i; --i) + { + fprintf (f, "("); + s->ifexpr_vec[i - 1]->gen_transform (f, NULL, false); + fprintf (f, ")"); + if (i > 1) + fprintf (f, " && "); + } + fprintf (f, ")\n"); + fprintf (f, "{\n"); + } + output_line_directive (f, s->result_location); if (s->result->type == operand::OP_EXPR) @@ -1551,7 +1564,7 @@ dt_simplify::gen_generic (FILE *f) else gcc_unreachable (); - if (s->ifexpr) + if (s->ifexpr_vec != vNULL) fprintf (f, "}\n"); fprintf (f, "}\n"); @@ -2025,7 +2038,7 @@ parse_match_and_simplify (cpp_reader *r, token = peek (r); if (token->type != CPP_OPEN_PAREN) - return new simplify (id, match, match_location, 0, 0, parse_op (r), token->src_loc); + return new simplify (id, match, match_location, parse_op (r), token->src_loc); eat_token (r, CPP_OPEN_PAREN); @@ -2037,25 +2050,27 @@ parse_match_and_simplify (cpp_reader *r, { operand *result = parse_expr (r); eat_token (r, CPP_CLOSE_PAREN); - return new simplify (id, match, match_location, 0, 0, result, result_loc); + return new simplify (id, match, match_location, result, result_loc); } // (if c-expr) - source_location ifexpr_loc = token->src_loc; eat_ident (r, "if"); operand *ifexpr = parse_c_expr (r, CPP_OPEN_PAREN); eat_token (r, CPP_CLOSE_PAREN); result_loc = peek (r)->src_loc; - return new simplify (id, match, match_location, ifexpr, ifexpr_loc, parse_op (r), result_loc); + simplify *s = new simplify (id, match, match_location, parse_op (r), result_loc); + s->ifexpr_vec.safe_push (ifexpr); + return s; } +void parse_pattern (cpp_reader *, vec<simplify *>&); + void parse_for (cpp_reader *r, source_location, vec<simplify *>& simplifiers) { const char *user_id = get_ident (r); eat_ident (r, "in"); - void parse_pattern (cpp_reader *, vec<simplify *>&); vec<const char *> opers = vNULL; @@ -2086,8 +2101,7 @@ parse_for (cpp_reader *r, source_locatio operand *result_op = replace_id (s->result, user_id, opers[i]); simplify *ns = new simplify (s->name, match_op, s->match_location, - s->ifexpr, s->ifexpr_location, - result_op, s->result_location); + result_op, s->result_location, s->ifexpr_vec); simplifiers.safe_push (ns); } @@ -2095,6 +2109,30 @@ parse_for (cpp_reader *r, source_locatio } } +void +parse_if (cpp_reader *r, vec<simplify *>& simplifiers) +{ + operand *ifexpr = parse_c_expr (r, CPP_OPEN_PAREN); + + unsigned pos = (simplifiers != vNULL) ? simplifiers.length () - 1 : 0; + + const cpp_token *token = peek (r); + if (token->type == CPP_CLOSE_PAREN) + fatal_at (token, "no pattern defined in if"); + + while (1) + { + const cpp_token *token = peek (r); + if (token->type == CPP_CLOSE_PAREN) + break; + + parse_pattern (r, simplifiers); + } + + for (unsigned i = pos; i < simplifiers.length (); ++i) + simplifiers[i]->ifexpr_vec.safe_push (ifexpr); +} + static size_t round_alloc_size (size_t s) { @@ -2112,6 +2150,8 @@ parse_pattern (cpp_reader *r, vec<simpli simplifiers.safe_push (parse_match_and_simplify (r, token->src_loc)); else if (strcmp (id, "for") == 0) parse_for (r, token->src_loc, simplifiers); + else if (strcmp (id, "if") == 0) + parse_if (r, simplifiers); else fatal_at (token, "expected 'match_and_simplify' or 'for'"); @@ -2183,7 +2223,7 @@ main(int argc, char **argv) for (unsigned i = 0; i < simplifiers.length (); ++i) check_no_user_id (simplifiers[i]); - + vec<simplify *> out_simplifiers = vNULL; for (unsigned i = 0; i < simplifiers.length (); ++i) lower_commutative (simplifiers[i], out_simplifiers); Index: gcc/match.pd =================================================================== --- gcc/match.pd (revision 212928) +++ gcc/match.pd (working copy) @@ -120,28 +120,24 @@ along with GCC; see the file COPYING3. ??? !FLOAT_TYPE_P && !FIXED_POINT_TYPE_P condition missing because of saturation to +-Inf. */ -/* (A +- B) - A -> +-B. */ -(match_and_simplify - (minus (plus @0 @1) @0) - (if (!TYPE_SATURATING (type) - && !FLOAT_TYPE_P (type) && !FIXED_POINT_TYPE_P (type))) - @1) -(match_and_simplify - (minus (minus @0 @1) @0) - (if (!TYPE_SATURATING (type) - && !FLOAT_TYPE_P (type) && !FIXED_POINT_TYPE_P (type))) - (negate @1)) -/* (A +- B) -+ B -> A. */ -(match_and_simplify - (minus (plus @0 @1) @1) - (if (!TYPE_SATURATING (type) - && !FLOAT_TYPE_P (type) && !FIXED_POINT_TYPE_P (type))) - @0) -(match_and_simplify - (plus:c (minus @0 @1) @1) - (if (!TYPE_SATURATING (type) - && !FLOAT_TYPE_P (type) && !FIXED_POINT_TYPE_P (type))) - @0) +(if (!TYPE_SATURATING (type) + && !FLOAT_TYPE_P (type) && !FIXED_POINT_TYPE_P (type)) + (match_and_simplify + (minus (plus @0 @1) @0) + @1) + + (match_and_simplify + (minus (minus @0 @1) @0) + (negate @1)) + + (match_and_simplify + (minus (plus @0 @1) @1) + @0) + + (match_and_simplify + (plus:c (minus @0 @1) @1) + @0)) + /* (CST +- A) +- CST -> CST' +- A. */ /* match_and_simplify handles constant folding for us so we can implement these as re-association patterns.