This merges simplifications of conditionals from tree-ssa-forwprop.c. Slight complication arises from having to also implement 0 ? A : B because otherwise X ? A : A may trigger which may trigger an overflow warning during bootstrap if A and A are not equal but 0 and 0(OVF) but we selected the "wrong" result. As automatic side-effects handling in genmatch gives up for conditional execution it cannot simplify 0 ? x = callA() : x = callB() which in turn causes (bogus) evaluation order warnings during bootstrap. Thus I had to preserve the fold-const.c variant.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied. Richard. 2014-11-13 Richard Biener <rguent...@suse.de> * match.pd: Implement conditional expression patterns. * tree-ssa-forwprop.c (forward_propagate_into_cond): Remove them here. (combine_cond_exprs): Remove. (pass_forwprop::execute): Do not call combine_cond_exprs. * fold-const.c (fold_ternary_loc): Remove patterns here. (pedantic_omit_one_operand_loc): Remove. Index: trunk/gcc/match.pd =================================================================== *** trunk.orig/gcc/match.pd 2014-11-13 09:42:36.866294878 +0100 --- trunk/gcc/match.pd 2014-11-13 09:42:54.314294115 +0100 *************** along with GCC; see the file COPYING3. *** 590,592 **** --- 590,640 ---- (simplify (bswap (bitop:c (bswap @0) @1)) (bitop @0 (bswap @1))))) + + + /* Combine COND_EXPRs and VEC_COND_EXPRs. */ + + /* Simplify constant conditions. + Only optimize constant conditions when the selected branch + has the same type as the COND_EXPR. This avoids optimizing + away "c ? x : throw", where the throw has a void type. + Note that we cannot throw away the fold-const.c variant nor + this one as we depend on doing this transform before possibly + A ? B : B -> B triggers and the fold-const.c one can optimize + 0 ? A : B to B even if A has side-effects. Something + genmatch cannot handle. */ + (simplify + (cond INTEGER_CST@0 @1 @2) + (if (integer_zerop (@0) + && (!VOID_TYPE_P (TREE_TYPE (@2)) + || VOID_TYPE_P (type))) + @2) + (if (!integer_zerop (@0) + && (!VOID_TYPE_P (TREE_TYPE (@1)) + || VOID_TYPE_P (type))) + @1)) + (simplify + (vec_cond VECTOR_CST@0 @1 @2) + (if (integer_all_onesp (@0)) + @1) + (if (integer_zerop (@0)) + @2)) + + (for cnd (cond vec_cond) + /* A ? B : (A ? X : C) -> A ? B : C. */ + (simplify + (cnd @0 (cnd @0 @1 @2) @3) + (cnd @0 @1 @3)) + (simplify + (cnd @0 @1 (cnd @0 @2 @3)) + (cnd @0 @1 @3)) + + /* A ? B : B -> B. */ + (simplify + (cnd @0 @1 @1) + @1)) + + /* !A ? B : C -> A ? C : B. */ + (simplify + (cond (logical_inverted_value truth_valued_p@0) @1 @2) + (cond @0 @2 @1)) Index: trunk/gcc/tree-ssa-forwprop.c =================================================================== *** trunk.orig/gcc/tree-ssa-forwprop.c 2014-11-13 09:41:21.566298173 +0100 --- trunk/gcc/tree-ssa-forwprop.c 2014-11-13 09:42:39.776294751 +0100 *************** forward_propagate_into_cond (gimple_stmt *** 617,623 **** tree tmp = NULL_TREE; tree cond = gimple_assign_rhs1 (stmt); enum tree_code code = gimple_assign_rhs_code (stmt); - bool swap = false; /* We can do tree combining on SSA_NAME and comparison expressions. */ if (COMPARISON_CLASS_P (cond)) --- 617,622 ---- *************** forward_propagate_into_cond (gimple_stmt *** 640,654 **** TREE_TYPE (cond), gimple_assign_rhs1 (def_stmt), gimple_assign_rhs2 (def_stmt)); - else if (code == COND_EXPR - && ((def_code == BIT_NOT_EXPR - && TYPE_PRECISION (TREE_TYPE (cond)) == 1) - || (def_code == BIT_XOR_EXPR - && integer_onep (gimple_assign_rhs2 (def_stmt))))) - { - tmp = gimple_assign_rhs1 (def_stmt); - swap = true; - } } if (tmp --- 639,644 ---- *************** forward_propagate_into_cond (gimple_stmt *** 669,683 **** else if (integer_zerop (tmp)) gimple_assign_set_rhs_from_tree (gsi_p, gimple_assign_rhs3 (stmt)); else ! { ! gimple_assign_set_rhs1 (stmt, unshare_expr (tmp)); ! if (swap) ! { ! tree t = gimple_assign_rhs2 (stmt); ! gimple_assign_set_rhs2 (stmt, gimple_assign_rhs3 (stmt)); ! gimple_assign_set_rhs3 (stmt, t); ! } ! } stmt = gsi_stmt (*gsi_p); update_stmt (stmt); --- 659,665 ---- else if (integer_zerop (tmp)) gimple_assign_set_rhs_from_tree (gsi_p, gimple_assign_rhs3 (stmt)); else ! gimple_assign_set_rhs1 (stmt, unshare_expr (tmp)); stmt = gsi_stmt (*gsi_p); update_stmt (stmt); *************** forward_propagate_into_cond (gimple_stmt *** 687,744 **** return 0; } - /* Propagate from the ssa name definition statements of COND_EXPR - values in the rhs of statement STMT into the conditional arms - if that simplifies it. - Returns true if the stmt was changed. */ - - static bool - combine_cond_exprs (gimple_stmt_iterator *gsi_p) - { - gimple stmt = gsi_stmt (*gsi_p); - tree cond, val1, val2; - bool changed = false; - - cond = gimple_assign_rhs1 (stmt); - val1 = gimple_assign_rhs2 (stmt); - if (TREE_CODE (val1) == SSA_NAME) - { - gimple def_stmt = SSA_NAME_DEF_STMT (val1); - if (is_gimple_assign (def_stmt) - && gimple_assign_rhs_code (def_stmt) == gimple_assign_rhs_code (stmt) - && operand_equal_p (gimple_assign_rhs1 (def_stmt), cond, 0)) - { - val1 = unshare_expr (gimple_assign_rhs2 (def_stmt)); - gimple_assign_set_rhs2 (stmt, val1); - changed = true; - } - } - val2 = gimple_assign_rhs3 (stmt); - if (TREE_CODE (val2) == SSA_NAME) - { - gimple def_stmt = SSA_NAME_DEF_STMT (val2); - if (is_gimple_assign (def_stmt) - && gimple_assign_rhs_code (def_stmt) == gimple_assign_rhs_code (stmt) - && operand_equal_p (gimple_assign_rhs1 (def_stmt), cond, 0)) - { - val2 = unshare_expr (gimple_assign_rhs3 (def_stmt)); - gimple_assign_set_rhs3 (stmt, val2); - changed = true; - } - } - if (operand_equal_p (val1, val2, 0)) - { - gimple_assign_set_rhs_from_tree (gsi_p, val1); - stmt = gsi_stmt (*gsi_p); - changed = true; - } - - if (changed) - update_stmt (stmt); - - return changed; - } - /* We've just substituted an ADDR_EXPR into stmt. Update all the relevant data structures to match. */ --- 669,674 ---- *************** pass_forwprop::execute (function *fun) *** 2432,2439 **** || code == VEC_COND_EXPR) { /* In this case the entire COND_EXPR is in rhs1. */ ! if (forward_propagate_into_cond (&gsi) ! || combine_cond_exprs (&gsi)) { changed = true; stmt = gsi_stmt (gsi); --- 2362,2368 ---- || code == VEC_COND_EXPR) { /* In this case the entire COND_EXPR is in rhs1. */ ! if (forward_propagate_into_cond (&gsi)) { changed = true; stmt = gsi_stmt (gsi); Index: trunk/gcc/fold-const.c =================================================================== *** trunk.orig/gcc/fold-const.c 2014-11-13 09:42:03.921296320 +0100 --- trunk/gcc/fold-const.c 2014-11-13 09:42:39.781294751 +0100 *************** static enum tree_code compcode_to_compar *** 121,127 **** static int operand_equal_for_comparison_p (tree, tree, tree); static int twoval_comparison_p (tree, tree *, tree *, int *); static tree eval_subst (location_t, tree, tree, tree, tree, tree); - static tree pedantic_omit_one_operand_loc (location_t, tree, tree, tree); static tree distribute_bit_expr (location_t, enum tree_code, tree, tree, tree); static tree make_bit_field_ref (location_t, tree, tree, HOST_WIDE_INT, HOST_WIDE_INT, int); --- 121,126 ---- *************** omit_one_operand_loc (location_t loc, tr *** 3074,3100 **** return non_lvalue_loc (loc, t); } - /* Similar, but call pedantic_non_lvalue instead of non_lvalue. */ - - static tree - pedantic_omit_one_operand_loc (location_t loc, tree type, tree result, - tree omitted) - { - tree t = fold_convert_loc (loc, type, result); - - /* If the resulting operand is an empty statement, just return the omitted - statement casted to void. */ - if (IS_EMPTY_STMT (t) && TREE_SIDE_EFFECTS (omitted)) - return build1_loc (loc, NOP_EXPR, void_type_node, - fold_ignored_result (omitted)); - - if (TREE_SIDE_EFFECTS (omitted)) - return build2_loc (loc, COMPOUND_EXPR, type, - fold_ignored_result (omitted), t); - - return pedantic_non_lvalue_loc (loc, t); - } - /* Return a tree for the case when the result of an expression is RESULT converted to TYPE and OMITTED1 and OMITTED2 were previously operands of the expression but are now not needed. --- 3073,3078 ---- *************** fold_ternary_loc (location_t loc, enum t *** 13553,13563 **** } else if (TREE_CODE (arg0) == VECTOR_CST) { - if (integer_all_onesp (arg0)) - return pedantic_omit_one_operand_loc (loc, type, arg1, arg2); - if (integer_zerop (arg0)) - return pedantic_omit_one_operand_loc (loc, type, arg2, arg1); - if ((TREE_CODE (arg1) == VECTOR_CST || TREE_CODE (arg1) == CONSTRUCTOR) && (TREE_CODE (arg2) == VECTOR_CST --- 13531,13536 ---- *************** fold_ternary_loc (location_t loc, enum t *** 13582,13590 **** } } - if (operand_equal_p (arg1, op2, 0)) - return pedantic_omit_one_operand_loc (loc, type, arg1, arg0); - /* If we have A op B ? A : C, we may be able to convert this to a simpler expression, depending on the operation and the values of B and C. Signed zeros prevent all of these transformations, --- 13555,13560 ----