This patch (also applicable to trunk) makes us canoncialize operand order for comparisons at the same time we canonicalize other operand order, in particular before dispatching to generic_simplify. It also adds operand canonicalization to ternary ops and adds FMA_EXPR and DOT_PROD_EXPR to the list of ternary commutative ops.
Bootstrap and regtest running on match-and-simplify branch and x86_64-unknown-linux-gnu. Richard. 2014-10-16 Richard Biener <rguent...@suse.de> * fold-const.c (fold_comparison): Remove redundant constant folding and operand swapping. (fold_binary_loc): Do comparison operand swapping here, dispatch to generic_simplify after operand canonicalization. (fold_ternary_loc): Canonicalize operand order for commutative ternary operations. * tree.c (commutative_ternary_tree_code): Add DOT_PROD_EXPR and FMA_EXPR. Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 216262) +++ gcc/fold-const.c (working copy) @@ -8726,14 +8726,6 @@ fold_comparison (location_t loc, enum tr STRIP_SIGN_NOPS (arg0); STRIP_SIGN_NOPS (arg1); - tem = fold_relational_const (code, type, arg0, arg1); - if (tem != NULL_TREE) - return tem; - - /* If one arg is a real or integer constant, put it last. */ - if (tree_swap_operands_p (arg0, arg1, true)) - return fold_build2_loc (loc, swap_tree_comparison (code), type, op1, op0); - /* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 -+ C1. */ if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR) && (equality_code || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))) @@ -9914,17 +9906,23 @@ fold_binary_loc (location_t loc, } } - extern tree generic_simplify (enum tree_code, tree, tree, tree); - tem = generic_simplify (code, type, op0, op1); - if (tem) - return tem; - /* If this is a commutative operation, and ARG0 is a constant, move it to ARG1 to reduce the number of tests below. */ if (commutative_tree_code (code) && tree_swap_operands_p (arg0, arg1, true)) return fold_build2_loc (loc, code, type, op1, op0); + /* Likewise if this is a comparison, and ARG0 is a constant, move it + to ARG1 to reduce the number of tests below. */ + if (kind == tcc_comparison + && tree_swap_operands_p (arg0, arg1, true)) + return fold_build2_loc (loc, swap_tree_comparison (code), type, op1, op0); + + extern tree generic_simplify (enum tree_code, tree, tree, tree); + tem = generic_simplify (code, type, op0, op1); + if (tem) + return tem; + /* ARG0 is the first operand of EXPR, and ARG1 is the second operand. First check for cases where an arithmetic operation is applied to a @@ -13809,6 +13807,12 @@ fold_ternary_loc (location_t loc, enum t gcc_assert (IS_EXPR_CODE_CLASS (kind) && TREE_CODE_LENGTH (code) == 3); + /* If this is a commutative operation, and OP0 is a constant, move it + to OP1 to reduce the number of tests below. */ + if (commutative_ternary_tree_code (code) + && tree_swap_operands_p (op0, op1, true)) + return fold_build3_loc (loc, code, type, op1, op0, op2); + extern tree generic_simplify (enum tree_code, tree, tree, tree, tree); tem = generic_simplify (code, type, op0, op1, op2); if (tem) Index: gcc/tree.c =================================================================== --- gcc/tree.c (revision 216244) +++ gcc/tree.c (working copy) @@ -7380,6 +7380,8 @@ commutative_ternary_tree_code (enum tree { case WIDEN_MULT_PLUS_EXPR: case WIDEN_MULT_MINUS_EXPR: + case DOT_PROD_EXPR: + case FMA_EXPR: return true; default: