http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59660
--- Comment #9 from Jan Hubicka <hubicka at ucw dot cz> --- Hi, this patch solves the testcase. The first hunk gets rid of the redundant NOP_EXPR converting TRUTH_EXPR from INT to BOOL. The second improves gimplifier to not introduce unnecesary control flow. If this approach seems to make sense, I will extend it to other booleans and prepare less hackish patch. Honza Index: fold-const.c =================================================================== --- fold-const.c (revision 206346) +++ fold-const.c (working copy) @@ -1977,6 +1977,8 @@ fold_convert_loc (location_t loc, tree t case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: case OFFSET_TYPE: + if (TREE_CODE (arg) == TRUTH_ORIF_EXPR) + return fold_build2_loc (loc, TRUTH_ORIF_EXPR, type, TREE_OPERAND (arg, 0), TREE_OPERAND (arg, 1)); if (TREE_CODE (arg) == INTEGER_CST) { tem = fold_convert_const (NOP_EXPR, type, arg); Index: gimplify.c =================================================================== --- gimplify.c (revision 206346) +++ gimplify.c (working copy) @@ -2931,14 +2931,37 @@ gimplify_cond_expr (tree *expr_p, gimple result = build_simple_mem_ref_loc (loc, tmp); } - /* Build the new then clause, `tmp = then_;'. But don't build the - assignment if the value is void; in C++ it can be if it's a throw. */ - if (!VOID_TYPE_P (TREE_TYPE (then_))) - TREE_OPERAND (expr, 1) = build2 (MODIFY_EXPR, type, tmp, then_); + /* Convert (A||B) ? true : false + as A ? tmp = true : tmp = B != 0. */ - /* Similarly, build the new else clause, `tmp = else_;'. */ - if (!VOID_TYPE_P (TREE_TYPE (else_))) - TREE_OPERAND (expr, 2) = build2 (MODIFY_EXPR, type, tmp, else_); + if (integer_zerop (else_) && integer_onep (then_) + && TREE_CODE (TREE_OPERAND (expr, 0)) == TRUTH_ORIF_EXPR) + { + tree pred = TREE_OPERAND (expr, 0); + location_t loc = EXPR_LOCATION (*expr_p); + TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 0); + /* Build the new then clause, `tmp = then_;'. But don't build the + assignment if the value is void; in C++ it can be if it's a throw. */ + TREE_OPERAND (expr, 1) = build2 (MODIFY_EXPR, type, tmp, + fold_convert (type, boolean_true_node)); + + /* Similarly, build the new else clause, `tmp = else_;'. */ + TREE_OPERAND (expr, 2) = build2 (MODIFY_EXPR, type, tmp, + fold_build2_loc (loc, NE_EXPR, type, TREE_OPERAND (pred, 1), + fold_convert (TREE_TYPE (TREE_OPERAND (pred, 1)), + integer_zero_node))); + } + else + { + /* Build the new then clause, `tmp = then_;'. But don't build the + assignment if the value is void; in C++ it can be if it's a throw. */ + if (!VOID_TYPE_P (TREE_TYPE (then_))) + TREE_OPERAND (expr, 1) = build2 (MODIFY_EXPR, type, tmp, then_); + + /* Similarly, build the new else clause, `tmp = else_;'. */ + if (!VOID_TYPE_P (TREE_TYPE (else_))) + TREE_OPERAND (expr, 2) = build2 (MODIFY_EXPR, type, tmp, else_); + } TREE_TYPE (expr) = void_type_node; recalculate_side_effects (expr);