Index: gcc/genmatch.c =================================================================== --- gcc/genmatch.c (revision 211732) +++ gcc/genmatch.c (working copy) @@ -293,14 +293,14 @@ e_operation::e_operation (const char *id struct simplify { simplify (const char *name_, - struct operand *match_, source_location match_location_, + vec matchers_, source_location match_location_, struct operand *ifexpr_, source_location ifexpr_location_, struct operand *result_, source_location result_location_) - : name (name_), match (match_), match_location (match_location_), + : name (name_), matchers (matchers_), match_location (match_location_), ifexpr (ifexpr_), ifexpr_location (ifexpr_location_), result (result_), result_location (result_location_) {} const char *name; - struct operand *match; + vec matchers; // vector to hold commutative expressions source_location match_location; struct operand *ifexpr; source_location ifexpr_location; @@ -308,7 +308,108 @@ struct simplify { source_location result_location; }; +void +print_operand (operand *o, FILE *f = stderr) +{ + if (o->type == operand::OP_CAPTURE) + fprintf (f, "@%s", (static_cast (o))->where); + + else if (o->type == operand::OP_PREDICATE) + fprintf (f, "%s", (static_cast (o))->ident); + + else if (o->type == operand::OP_C_EXPR) + fprintf (f, "c_expr"); + + else if (o->type == operand::OP_EXPR) + { + expr *e = static_cast (o); + fprintf (f, "(%s ", e->operation->op->id); + + for (unsigned i = 0; i < e->ops.length (); ++i) + { + print_operand (e->ops[i], f); + putc (' ', f); + } + + putc (')', f); + } + + else + gcc_unreachable (); +} + +void +print_matches (struct simplify *s, FILE *f = stderr) +{ + if (s->matchers.length () == 1) + return; + + fprintf (f, "for expression: "); + print_operand (s->matchers[0], f); // s->matchers[0] is equivalent to original expression + putc ('\n', f); + + fprintf (f, "commutative expressions:\n"); + for (unsigned i = 0; i < s->matchers.length (); ++i) + { + print_operand (s->matchers[i], f); + putc ('\n', f); + } +} + +bool +is_commutative (operand *op) +{ + if (op->type != operand::OP_EXPR) + return false; + + expr *e = static_cast (op); + operator_id *op_id = static_cast (e->operation->op); + enum tree_code code = op_id->code; + if (code == PLUS_EXPR || code == MULT_EXPR) + return true; + + return false; +} + +vec +commutate (operand *op) +{ + vec ret = vNULL; + + if (!is_commutative (op)) + { + ret.safe_push (op); // FIXME: should we clone op ? ret.safe_push (op->clone()) + return ret; + } + + expr *e = static_cast (op); + + vec v1 = commutate (e->ops[0]); + vec v2 = commutate (e->ops[1]); + + unsigned i, j; + + for (i = 0; i < v1.length (); ++i) + for (j = 0; j < v2.length (); ++j) + { + expr *ne = new expr (e->operation); // FIXME: e->operation should be cloned ? + ne->append_op (v1[i]); + ne->append_op (v2[j]); + ret.safe_push (ne); + } + + for (i = 0; i < v2.length (); ++i) + for (j = 0; j < v1.length (); ++j) + { + expr *ne = new expr (e->operation); + ne->append_op (v2[i]); + ne->append_op (v1[j]); + ret.safe_push (ne); + } + + return ret; +} /* Code gen off the AST. */ @@ -574,11 +675,15 @@ write_nary_simplifiers (FILE *f, vecmatch->type != operand::OP_EXPR) + for (unsigned i = 0; i < s->matchers.length (); ++i) + { + operand *match = s->matchers[i]; + if (match->type != operand::OP_EXPR) continue; - expr *e = static_cast (s->match); + expr *e = static_cast (match); if (e->ops.length () != n) continue; + char fail_label[16]; snprintf (fail_label, 16, "fail%d", label_cnt++); output_line_directive (f, s->match_location); @@ -627,6 +735,7 @@ write_nary_simplifiers (FILE *f, vecsrc_loc); } @@ -1043,6 +1152,9 @@ main(int argc, char **argv) } while (1); + for (unsigned i = 0; i < simplifiers.length (); ++i) + print_matches (simplifiers[i]); + write_gimple (stdout, simplifiers); cpp_finish (r, NULL);