I observed that we fail to match patterns because when valueizing sub-expression operands we fail to canonicalize operand order and thus try matching (1 + a) - 1 instead of the canonical (a + 1) - 1. The following fixes this at least for commutative tree codes. For comparisons which we also canonicalize in the plumbing (by means of changing the comparison code via swap_tree_comparison) this isn't that easily done. I'm thinking of a proper solution here.
Bootstrap & regtest running on x86_64-unknown-linux-gnu. Richard. 2015-07-03 Richard Biener <rguent...@suse.de> * genmatch.c (commutative_tree_code, commutative_ternary_tree_code): Copy from tree.c (dt_operand::gen_gimple_expr): After valueizing operands re-canonicalize operand order for commutative tree codes. Index: gcc/genmatch.c =================================================================== --- gcc/genmatch.c (revision 225368) +++ gcc/genmatch.c (working copy) @@ -175,6 +175,62 @@ END_BUILTINS }; #undef DEF_BUILTIN +/* Return true if CODE represents a commutative tree code. Otherwise + return false. */ +bool +commutative_tree_code (enum tree_code code) +{ + switch (code) + { + case PLUS_EXPR: + case MULT_EXPR: + case MULT_HIGHPART_EXPR: + case MIN_EXPR: + case MAX_EXPR: + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + case BIT_AND_EXPR: + case NE_EXPR: + case EQ_EXPR: + case UNORDERED_EXPR: + case ORDERED_EXPR: + case UNEQ_EXPR: + case LTGT_EXPR: + case TRUTH_AND_EXPR: + case TRUTH_XOR_EXPR: + case TRUTH_OR_EXPR: + case WIDEN_MULT_EXPR: + case VEC_WIDEN_MULT_HI_EXPR: + case VEC_WIDEN_MULT_LO_EXPR: + case VEC_WIDEN_MULT_EVEN_EXPR: + case VEC_WIDEN_MULT_ODD_EXPR: + return true; + + default: + break; + } + return false; +} + +/* Return true if CODE represents a ternary tree code for which the + first two operands are commutative. Otherwise return false. */ +bool +commutative_ternary_tree_code (enum tree_code code) +{ + switch (code) + { + case WIDEN_MULT_PLUS_EXPR: + case WIDEN_MULT_MINUS_EXPR: + case DOT_PROD_EXPR: + case FMA_EXPR: + return true; + + default: + break; + } + return false; +} + /* Base class for all identifiers the parser knows. */ @@ -1996,6 +2052,25 @@ dt_operand::gen_gimple_expr (FILE *f) child_opname, child_opname); fprintf (f, "{\n"); } + /* While the toplevel operands are canonicalized by the caller + after valueizing operands of sub-expressions we have to + re-canonicalize operand order. */ + if (operator_id *code = dyn_cast <operator_id *> (id)) + { + /* ??? We can't canonicalize tcc_comparison operands here + because that requires changing the comparison code which + we already matched... */ + if (commutative_tree_code (code->code) + || commutative_ternary_tree_code (code->code)) + { + char child_opname0[20], child_opname1[20]; + gen_opname (child_opname0, 0); + gen_opname (child_opname1, 1); + fprintf (f, "if (tree_swap_operands_p (%s, %s, false))\n" + " std::swap (%s, %s);\n", child_opname0, child_opname1, + child_opname0, child_opname1); + } + } return n_ops; }