On Wed, 31 Aug 2011, Richard Guenther wrote: > > $subject says it all, COND_EXPR to follow. rhs1 will still be > a "single" tree, namely a is_gimple_condexpr () operand. That's > not easy to change (without forcing it to a separate statement, > thus making it a is_gimple_val) because it embeds another tree code. > > Bootstrapped and tested on x86_64-unknown-linux-gnu. > > Any serious objections?
None, though the following implements it for both COND_EXPR and VEC_COND_EXPR. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2011-08-31 Richard Guenther <rguent...@suse.de> * expr.c (expand_expr_real_2): Move COND_EXPR and VEC_COND_EXPR handling here, from ... (expand_expr_real_1): ... here. * gimple-pretty-print.c (dump_ternary_rhs): Handle COND_EXPR and VEC_COND_EXPR. * gimple.c (gimple_rhs_class_table): Make COND_EXPR and VEC_COND_EXPR a GIMPLE_TERNARY_RHS. * tree-cfg.c (verify_gimple_assign_ternary): Handle COND_EXPR and VEC_COND_EXPR here ... (verify_gimple_assign_single): ... not here. * gimple-fold.c (fold_gimple_assign): Move COND_EXPR folding. * tree-object-size.c (cond_expr_object_size): Adjust. (collect_object_sizes_for): Likewise. * tree-scalar-evolution.c (interpret_expr): Don't handle ternary RHSs. * tree-ssa-forwprop.c (forward_propagate_into_cond): Fix and simplify. (ssa_forward_propagate_and_combine): Adjust. * tree-ssa-loop-im.c (move_computations_stmt): Build the COND_EXPR as ternary. * tree-ssa-threadedge.c (fold_assignment_stmt): Adjust. * tree-vect-loop.c (vect_is_simple_reduction_1): Likewise. * tree-vect-stmt.c (vectorizable_condition): Likewise. * tree-vrp.c (extract_range_from_cond_expr): Likewise. (extract_range_from_assignment): Likewise. Index: trunk/gcc/expr.c =================================================================== *** trunk.orig/gcc/expr.c 2011-09-01 12:08:51.000000000 +0200 --- trunk/gcc/expr.c 2011-09-01 12:10:04.000000000 +0200 *************** expand_expr_real_2 (sepops ops, rtx targ *** 8636,8641 **** --- 8636,8699 ---- return temp; } + case COND_EXPR: + /* A COND_EXPR with its type being VOID_TYPE represents a + conditional jump and is handled in + expand_gimple_cond_expr. */ + gcc_assert (!VOID_TYPE_P (type)); + + /* Note that COND_EXPRs whose type is a structure or union + are required to be constructed to contain assignments of + a temporary variable, so that we can evaluate them here + for side effect only. If type is void, we must do likewise. */ + + gcc_assert (!TREE_ADDRESSABLE (type) + && !ignore + && TREE_TYPE (treeop1) != void_type_node + && TREE_TYPE (treeop2) != void_type_node); + + /* If we are not to produce a result, we have no target. Otherwise, + if a target was specified use it; it will not be used as an + intermediate target unless it is safe. If no target, use a + temporary. */ + + if (modifier != EXPAND_STACK_PARM + && original_target + && safe_from_p (original_target, treeop0, 1) + && GET_MODE (original_target) == mode + #ifdef HAVE_conditional_move + && (! can_conditionally_move_p (mode) + || REG_P (original_target)) + #endif + && !MEM_P (original_target)) + temp = original_target; + else + temp = assign_temp (type, 0, 0, 1); + + do_pending_stack_adjust (); + NO_DEFER_POP; + op0 = gen_label_rtx (); + op1 = gen_label_rtx (); + jumpifnot (treeop0, op0, -1); + store_expr (treeop1, temp, + modifier == EXPAND_STACK_PARM, + false); + + emit_jump_insn (gen_jump (op1)); + emit_barrier (); + emit_label (op0); + store_expr (treeop2, temp, + modifier == EXPAND_STACK_PARM, + false); + + emit_label (op1); + OK_DEFER_POP; + return temp; + + case VEC_COND_EXPR: + target = expand_vec_cond_expr (type, treeop0, treeop1, treeop2, target); + return target; + default: gcc_unreachable (); } *************** expand_expr_real_1 (tree exp, rtx target *** 9878,9941 **** return op0; - case COND_EXPR: - /* A COND_EXPR with its type being VOID_TYPE represents a - conditional jump and is handled in - expand_gimple_cond_expr. */ - gcc_assert (!VOID_TYPE_P (type)); - - /* Note that COND_EXPRs whose type is a structure or union - are required to be constructed to contain assignments of - a temporary variable, so that we can evaluate them here - for side effect only. If type is void, we must do likewise. */ - - gcc_assert (!TREE_ADDRESSABLE (type) - && !ignore - && TREE_TYPE (treeop1) != void_type_node - && TREE_TYPE (treeop2) != void_type_node); - - /* If we are not to produce a result, we have no target. Otherwise, - if a target was specified use it; it will not be used as an - intermediate target unless it is safe. If no target, use a - temporary. */ - - if (modifier != EXPAND_STACK_PARM - && original_target - && safe_from_p (original_target, treeop0, 1) - && GET_MODE (original_target) == mode - #ifdef HAVE_conditional_move - && (! can_conditionally_move_p (mode) - || REG_P (original_target)) - #endif - && !MEM_P (original_target)) - temp = original_target; - else - temp = assign_temp (type, 0, 0, 1); - - do_pending_stack_adjust (); - NO_DEFER_POP; - op0 = gen_label_rtx (); - op1 = gen_label_rtx (); - jumpifnot (treeop0, op0, -1); - store_expr (treeop1, temp, - modifier == EXPAND_STACK_PARM, - false); - - emit_jump_insn (gen_jump (op1)); - emit_barrier (); - emit_label (op0); - store_expr (treeop2, temp, - modifier == EXPAND_STACK_PARM, - false); - - emit_label (op1); - OK_DEFER_POP; - return temp; - - case VEC_COND_EXPR: - target = expand_vec_cond_expr (type, treeop0, treeop1, treeop2, target); - return target; - case MODIFY_EXPR: { tree lhs = treeop0; --- 9936,9941 ---- Index: trunk/gcc/gimple-pretty-print.c =================================================================== *** trunk.orig/gcc/gimple-pretty-print.c 2011-09-01 12:08:51.000000000 +0200 --- trunk/gcc/gimple-pretty-print.c 2011-09-01 12:10:04.000000000 +0200 *************** dump_ternary_rhs (pretty_printer *buffer *** 428,433 **** --- 428,451 ---- pp_string (buffer, ">"); break; + case COND_EXPR: + dump_generic_node (buffer, gimple_assign_rhs1 (gs), spc, flags, false); + pp_string (buffer, " ? "); + dump_generic_node (buffer, gimple_assign_rhs2 (gs), spc, flags, false); + pp_string (buffer, " : "); + dump_generic_node (buffer, gimple_assign_rhs3 (gs), spc, flags, false); + break; + + case VEC_COND_EXPR: + pp_string (buffer, "VEC_COND_EXPR <"); + dump_generic_node (buffer, gimple_assign_rhs1 (gs), spc, flags, false); + pp_string (buffer, ", "); + dump_generic_node (buffer, gimple_assign_rhs2 (gs), spc, flags, false); + pp_string (buffer, ", "); + dump_generic_node (buffer, gimple_assign_rhs3 (gs), spc, flags, false); + pp_string (buffer, ">"); + break; + default: gcc_unreachable (); } Index: trunk/gcc/gimple.c =================================================================== *** trunk.orig/gcc/gimple.c 2011-09-01 12:08:51.000000000 +0200 --- trunk/gcc/gimple.c 2011-09-01 12:10:04.000000000 +0200 *************** get_gimple_rhs_num_ops (enum tree_code c *** 2611,2629 **** || (SYM) == TRUTH_OR_EXPR \ || (SYM) == TRUTH_XOR_EXPR) ? GIMPLE_BINARY_RHS \ : (SYM) == TRUTH_NOT_EXPR ? GIMPLE_UNARY_RHS \ ! : ((SYM) == WIDEN_MULT_PLUS_EXPR \ || (SYM) == WIDEN_MULT_MINUS_EXPR \ || (SYM) == DOT_PROD_EXPR \ || (SYM) == REALIGN_LOAD_EXPR \ || (SYM) == FMA_EXPR) ? GIMPLE_TERNARY_RHS \ ! : ((SYM) == COND_EXPR \ ! || (SYM) == CONSTRUCTOR \ || (SYM) == OBJ_TYPE_REF \ || (SYM) == ASSERT_EXPR \ || (SYM) == ADDR_EXPR \ || (SYM) == WITH_SIZE_EXPR \ ! || (SYM) == SSA_NAME \ ! || (SYM) == VEC_COND_EXPR) ? GIMPLE_SINGLE_RHS \ : GIMPLE_INVALID_RHS), #define END_OF_BASE_TREE_CODES (unsigned char) GIMPLE_INVALID_RHS, --- 2611,2629 ---- || (SYM) == TRUTH_OR_EXPR \ || (SYM) == TRUTH_XOR_EXPR) ? GIMPLE_BINARY_RHS \ : (SYM) == TRUTH_NOT_EXPR ? GIMPLE_UNARY_RHS \ ! : ((SYM) == COND_EXPR \ ! || (SYM) == WIDEN_MULT_PLUS_EXPR \ || (SYM) == WIDEN_MULT_MINUS_EXPR \ || (SYM) == DOT_PROD_EXPR \ || (SYM) == REALIGN_LOAD_EXPR \ + || (SYM) == VEC_COND_EXPR \ || (SYM) == FMA_EXPR) ? GIMPLE_TERNARY_RHS \ ! : ((SYM) == CONSTRUCTOR \ || (SYM) == OBJ_TYPE_REF \ || (SYM) == ASSERT_EXPR \ || (SYM) == ADDR_EXPR \ || (SYM) == WITH_SIZE_EXPR \ ! || (SYM) == SSA_NAME) ? GIMPLE_SINGLE_RHS \ : GIMPLE_INVALID_RHS), #define END_OF_BASE_TREE_CODES (unsigned char) GIMPLE_INVALID_RHS, Index: trunk/gcc/tree-cfg.c =================================================================== *** trunk.orig/gcc/tree-cfg.c 2011-09-01 12:08:51.000000000 +0200 --- trunk/gcc/tree-cfg.c 2011-09-01 12:10:04.000000000 +0200 *************** verify_gimple_assign_ternary (gimple stm *** 3761,3767 **** return true; } ! if (!is_gimple_val (rhs1) || !is_gimple_val (rhs2) || !is_gimple_val (rhs3)) { --- 3761,3768 ---- return true; } ! if (((rhs_code == VEC_COND_EXPR || rhs_code == COND_EXPR) ! ? !is_gimple_condexpr (rhs1) : !is_gimple_val (rhs1)) || !is_gimple_val (rhs2) || !is_gimple_val (rhs3)) { *************** verify_gimple_assign_ternary (gimple stm *** 3804,3809 **** --- 3805,3823 ---- } break; + case COND_EXPR: + case VEC_COND_EXPR: + if (!useless_type_conversion_p (lhs_type, rhs2_type) + || !useless_type_conversion_p (lhs_type, rhs3_type)) + { + error ("type mismatch in conditional expression"); + debug_generic_expr (lhs_type); + debug_generic_expr (rhs2_type); + debug_generic_expr (rhs3_type); + return true; + } + break; + case DOT_PROD_EXPR: case REALIGN_LOAD_EXPR: /* FIXME. */ *************** verify_gimple_assign_single (gimple stmt *** 3920,3945 **** } return res; - case COND_EXPR: - if (!is_gimple_reg (lhs) - || (!is_gimple_reg (TREE_OPERAND (rhs1, 0)) - && !COMPARISON_CLASS_P (TREE_OPERAND (rhs1, 0))) - || (!is_gimple_reg (TREE_OPERAND (rhs1, 1)) - && !is_gimple_min_invariant (TREE_OPERAND (rhs1, 1))) - || (!is_gimple_reg (TREE_OPERAND (rhs1, 2)) - && !is_gimple_min_invariant (TREE_OPERAND (rhs1, 2)))) - { - error ("invalid COND_EXPR in gimple assignment"); - debug_generic_stmt (rhs1); - return true; - } - return res; - case CONSTRUCTOR: case OBJ_TYPE_REF: case ASSERT_EXPR: case WITH_SIZE_EXPR: - case VEC_COND_EXPR: /* FIXME. */ return res; --- 3934,3943 ---- Index: trunk/gcc/gimple-fold.c =================================================================== *** trunk.orig/gcc/gimple-fold.c 2011-09-01 12:08:51.000000000 +0200 --- trunk/gcc/gimple-fold.c 2011-09-01 12:10:04.000000000 +0200 *************** fold_gimple_assign (gimple_stmt_iterator *** 294,335 **** { tree rhs = gimple_assign_rhs1 (stmt); ! /* Try to fold a conditional expression. */ ! if (TREE_CODE (rhs) == COND_EXPR) ! { ! tree op0 = COND_EXPR_COND (rhs); ! tree tem; ! bool set = false; ! location_t cond_loc = EXPR_LOCATION (rhs); ! ! if (COMPARISON_CLASS_P (op0)) ! { ! fold_defer_overflow_warnings (); ! tem = fold_binary_loc (cond_loc, ! TREE_CODE (op0), TREE_TYPE (op0), ! TREE_OPERAND (op0, 0), ! TREE_OPERAND (op0, 1)); ! /* This is actually a conditional expression, not a GIMPLE ! conditional statement, however, the valid_gimple_rhs_p ! test still applies. */ ! set = (tem && is_gimple_condexpr (tem) ! && valid_gimple_rhs_p (tem)); ! fold_undefer_overflow_warnings (set, stmt, 0); ! } ! else if (is_gimple_min_invariant (op0)) ! { ! tem = op0; ! set = true; ! } ! else ! return NULL_TREE; ! ! if (set) ! result = fold_build3_loc (cond_loc, COND_EXPR, TREE_TYPE (rhs), tem, ! COND_EXPR_THEN (rhs), COND_EXPR_ELSE (rhs)); ! } ! ! else if (REFERENCE_CLASS_P (rhs)) return maybe_fold_reference (rhs, false); else if (TREE_CODE (rhs) == ADDR_EXPR) --- 294,300 ---- { tree rhs = gimple_assign_rhs1 (stmt); ! if (REFERENCE_CLASS_P (rhs)) return maybe_fold_reference (rhs, false); else if (TREE_CODE (rhs) == ADDR_EXPR) *************** fold_gimple_assign (gimple_stmt_iterator *** 469,479 **** break; case GIMPLE_TERNARY_RHS: ! result = fold_ternary_loc (loc, subcode, ! TREE_TYPE (gimple_assign_lhs (stmt)), ! gimple_assign_rhs1 (stmt), ! gimple_assign_rhs2 (stmt), ! gimple_assign_rhs3 (stmt)); if (result) { --- 434,482 ---- break; case GIMPLE_TERNARY_RHS: ! /* Try to fold a conditional expression. */ ! if (gimple_assign_rhs_code (stmt) == COND_EXPR) ! { ! tree op0 = gimple_assign_rhs1 (stmt); ! tree tem; ! bool set = false; ! location_t cond_loc = gimple_location (stmt); ! ! if (COMPARISON_CLASS_P (op0)) ! { ! fold_defer_overflow_warnings (); ! tem = fold_binary_loc (cond_loc, ! TREE_CODE (op0), TREE_TYPE (op0), ! TREE_OPERAND (op0, 0), ! TREE_OPERAND (op0, 1)); ! /* This is actually a conditional expression, not a GIMPLE ! conditional statement, however, the valid_gimple_rhs_p ! test still applies. */ ! set = (tem && is_gimple_condexpr (tem) ! && valid_gimple_rhs_p (tem)); ! fold_undefer_overflow_warnings (set, stmt, 0); ! } ! else if (is_gimple_min_invariant (op0)) ! { ! tem = op0; ! set = true; ! } ! else ! return NULL_TREE; ! ! if (set) ! result = fold_build3_loc (cond_loc, COND_EXPR, ! TREE_TYPE (gimple_assign_lhs (stmt)), tem, ! gimple_assign_rhs2 (stmt), ! gimple_assign_rhs3 (stmt)); ! } ! ! if (!result) ! result = fold_ternary_loc (loc, subcode, ! TREE_TYPE (gimple_assign_lhs (stmt)), ! gimple_assign_rhs1 (stmt), ! gimple_assign_rhs2 (stmt), ! gimple_assign_rhs3 (stmt)); if (result) { Index: trunk/gcc/tree-object-size.c =================================================================== *** trunk.orig/gcc/tree-object-size.c 2011-09-01 12:08:51.000000000 +0200 --- trunk/gcc/tree-object-size.c 2011-09-01 12:10:04.000000000 +0200 *************** static void expr_object_size (struct obj *** 53,59 **** static bool merge_object_sizes (struct object_size_info *, tree, tree, unsigned HOST_WIDE_INT); static bool plus_stmt_object_size (struct object_size_info *, tree, gimple); ! static bool cond_expr_object_size (struct object_size_info *, tree, tree); static unsigned int compute_object_sizes (void); static void init_offset_limit (void); static void check_for_plus_in_loops (struct object_size_info *, tree); --- 53,59 ---- static bool merge_object_sizes (struct object_size_info *, tree, tree, unsigned HOST_WIDE_INT); static bool plus_stmt_object_size (struct object_size_info *, tree, gimple); ! static bool cond_expr_object_size (struct object_size_info *, tree, gimple); static unsigned int compute_object_sizes (void); static void init_offset_limit (void); static void check_for_plus_in_loops (struct object_size_info *, tree); *************** plus_stmt_object_size (struct object_siz *** 827,851 **** } ! /* Compute object_sizes for VAR, defined to VALUE, which is a COND_EXPR. Return true if the object size might need reexamination later. */ static bool ! cond_expr_object_size (struct object_size_info *osi, tree var, tree value) { tree then_, else_; int object_size_type = osi->object_size_type; unsigned int varno = SSA_NAME_VERSION (var); bool reexamine = false; ! gcc_assert (TREE_CODE (value) == COND_EXPR); if (object_sizes[object_size_type][varno] == unknown[object_size_type]) return false; ! then_ = COND_EXPR_THEN (value); ! else_ = COND_EXPR_ELSE (value); if (TREE_CODE (then_) == SSA_NAME) reexamine |= merge_object_sizes (osi, var, then_, 0); --- 827,851 ---- } ! /* Compute object_sizes for VAR, defined at STMT, which is a COND_EXPR. Return true if the object size might need reexamination later. */ static bool ! cond_expr_object_size (struct object_size_info *osi, tree var, gimple stmt) { tree then_, else_; int object_size_type = osi->object_size_type; unsigned int varno = SSA_NAME_VERSION (var); bool reexamine = false; ! gcc_assert (gimple_assign_rhs_code (stmt) == COND_EXPR); if (object_sizes[object_size_type][varno] == unknown[object_size_type]) return false; ! then_ = gimple_assign_rhs2 (stmt); ! else_ = gimple_assign_rhs3 (stmt); if (TREE_CODE (then_) == SSA_NAME) reexamine |= merge_object_sizes (osi, var, then_, 0); *************** collect_object_sizes_for (struct object_ *** 932,945 **** || (gimple_assign_rhs_code (stmt) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (rhs, 0)) == MEM_REF)) reexamine = plus_stmt_object_size (osi, var, stmt); else if (gimple_assign_single_p (stmt) || gimple_assign_unary_nop_p (stmt)) { if (TREE_CODE (rhs) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (rhs))) reexamine = merge_object_sizes (osi, var, rhs, 0); - else if (TREE_CODE (rhs) == COND_EXPR) - reexamine = cond_expr_object_size (osi, var, rhs); else expr_object_size (osi, var, rhs); } --- 932,945 ---- || (gimple_assign_rhs_code (stmt) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (rhs, 0)) == MEM_REF)) reexamine = plus_stmt_object_size (osi, var, stmt); + else if (gimple_assign_rhs_code (stmt) == COND_EXPR) + reexamine = cond_expr_object_size (osi, var, stmt); else if (gimple_assign_single_p (stmt) || gimple_assign_unary_nop_p (stmt)) { if (TREE_CODE (rhs) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (rhs))) reexamine = merge_object_sizes (osi, var, rhs, 0); else expr_object_size (osi, var, rhs); } *************** collect_object_sizes_for (struct object_ *** 956,963 **** if (TREE_CODE (arg) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (arg))) reexamine = merge_object_sizes (osi, var, arg, 0); - else if (TREE_CODE (arg) == COND_EXPR) - reexamine = cond_expr_object_size (osi, var, arg); else expr_object_size (osi, var, arg); } --- 956,961 ---- Index: trunk/gcc/tree-scalar-evolution.c =================================================================== *** trunk.orig/gcc/tree-scalar-evolution.c 2011-09-01 12:08:51.000000000 +0200 --- trunk/gcc/tree-scalar-evolution.c 2011-09-01 12:10:04.000000000 +0200 *************** interpret_expr (struct loop *loop, gimpl *** 1796,1802 **** if (automatically_generated_chrec_p (expr)) return expr; ! if (TREE_CODE (expr) == POLYNOMIAL_CHREC) return chrec_dont_know; extract_ops_from_tree (expr, &code, &op0, &op1); --- 1796,1803 ---- if (automatically_generated_chrec_p (expr)) return expr; ! if (TREE_CODE (expr) == POLYNOMIAL_CHREC ! || get_gimple_rhs_class (TREE_CODE (expr)) == GIMPLE_TERNARY_RHS) return chrec_dont_know; extract_ops_from_tree (expr, &code, &op0, &op1); Index: trunk/gcc/tree-ssa-forwprop.c =================================================================== *** trunk.orig/gcc/tree-ssa-forwprop.c 2011-09-01 12:08:51.000000000 +0200 --- trunk/gcc/tree-ssa-forwprop.c 2011-09-01 12:17:17.000000000 +0200 *************** forward_propagate_into_gimple_cond (gimp *** 540,551 **** /* Propagate from the ssa name definition statements of COND_EXPR in the rhs of statement STMT into the conditional if that simplifies it. ! Returns zero if no statement was changed, one if there were ! changes and two if cfg_cleanup needs to run. ! This must be kept in sync with forward_propagate_into_gimple_cond. */ ! ! static int forward_propagate_into_cond (gimple_stmt_iterator *gsi_p) { gimple stmt = gsi_stmt (*gsi_p); --- 540,548 ---- /* Propagate from the ssa name definition statements of COND_EXPR in the rhs of statement STMT into the conditional if that simplifies it. ! Returns true zero if the stmt was changed. */ ! static bool forward_propagate_into_cond (gimple_stmt_iterator *gsi_p) { gimple stmt = gsi_stmt (*gsi_p); *************** forward_propagate_into_cond (gimple_stmt *** 560,574 **** TREE_OPERAND (cond, 1)); else if (TREE_CODE (cond) == SSA_NAME) { ! tree name = cond, rhs0; gimple def_stmt = get_prop_source_stmt (name, true, NULL); if (!def_stmt || !can_propagate_from (def_stmt)) return 0; ! rhs0 = gimple_assign_rhs1 (def_stmt); ! tmp = combine_cond_expr_cond (stmt, NE_EXPR, boolean_type_node, rhs0, ! build_int_cst (TREE_TYPE (rhs0), 0), ! false); } if (tmp) --- 557,573 ---- TREE_OPERAND (cond, 1)); else if (TREE_CODE (cond) == SSA_NAME) { ! tree name = cond; gimple def_stmt = get_prop_source_stmt (name, true, NULL); if (!def_stmt || !can_propagate_from (def_stmt)) return 0; ! if (TREE_CODE_CLASS (gimple_assign_rhs_code (def_stmt)) == tcc_comparison) ! tmp = fold_build2_loc (gimple_location (def_stmt), ! gimple_assign_rhs_code (def_stmt), ! boolean_type_node, ! gimple_assign_rhs1 (def_stmt), ! gimple_assign_rhs2 (def_stmt)); } if (tmp) *************** forward_propagate_into_cond (gimple_stmt *** 582,592 **** fprintf (dump_file, "'\n"); } ! gimple_assign_set_rhs_from_tree (gsi_p, unshare_expr (tmp)); stmt = gsi_stmt (*gsi_p); update_stmt (stmt); ! return is_gimple_min_invariant (tmp) ? 2 : 1; } return 0; --- 581,596 ---- fprintf (dump_file, "'\n"); } ! if (integer_onep (tmp)) ! gimple_assign_set_rhs_from_tree (gsi_p, gimple_assign_rhs2 (stmt)); ! 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); ! return true; } return 0; *************** ssa_forward_propagate_and_combine (void) *** 2436,2447 **** else if (code == COND_EXPR) { /* In this case the entire COND_EXPR is in rhs1. */ ! int did_something; ! did_something = forward_propagate_into_cond (&gsi); stmt = gsi_stmt (gsi); - if (did_something == 2) - cfg_changed = true; - changed = did_something != 0; } else if (TREE_CODE_CLASS (code) == tcc_comparison) { --- 2440,2447 ---- else if (code == COND_EXPR) { /* In this case the entire COND_EXPR is in rhs1. */ ! changed |= forward_propagate_into_cond (&gsi); stmt = gsi_stmt (gsi); } else if (TREE_CODE_CLASS (code) == tcc_comparison) { Index: trunk/gcc/tree-ssa-loop-im.c =================================================================== *** trunk.orig/gcc/tree-ssa-loop-im.c 2011-09-01 12:08:51.000000000 +0200 --- trunk/gcc/tree-ssa-loop-im.c 2011-09-01 12:10:04.000000000 +0200 *************** move_computations_stmt (struct dom_walk_ *** 1251,1261 **** gcc_assert (arg0 && arg1); t = build2 (gimple_cond_code (cond), boolean_type_node, gimple_cond_lhs (cond), gimple_cond_rhs (cond)); ! t = build3 (COND_EXPR, TREE_TYPE (gimple_phi_result (stmt)), ! t, arg0, arg1); ! new_stmt = gimple_build_assign_with_ops (COND_EXPR, ! gimple_phi_result (stmt), ! t, NULL_TREE); SSA_NAME_DEF_STMT (gimple_phi_result (stmt)) = new_stmt; *((unsigned int *)(dw_data->global_data)) |= TODO_cleanup_cfg; } --- 1251,1259 ---- gcc_assert (arg0 && arg1); t = build2 (gimple_cond_code (cond), boolean_type_node, gimple_cond_lhs (cond), gimple_cond_rhs (cond)); ! new_stmt = gimple_build_assign_with_ops3 (COND_EXPR, ! gimple_phi_result (stmt), ! t, arg0, arg1); SSA_NAME_DEF_STMT (gimple_phi_result (stmt)) = new_stmt; *((unsigned int *)(dw_data->global_data)) |= TODO_cleanup_cfg; } Index: trunk/gcc/tree-ssa-threadedge.c =================================================================== *** trunk.orig/gcc/tree-ssa-threadedge.c 2011-09-01 12:08:51.000000000 +0200 --- trunk/gcc/tree-ssa-threadedge.c 2011-09-01 12:10:04.000000000 +0200 *************** fold_assignment_stmt (gimple stmt) *** 225,248 **** switch (get_gimple_rhs_class (subcode)) { case GIMPLE_SINGLE_RHS: ! { ! tree rhs = gimple_assign_rhs1 (stmt); ! ! if (TREE_CODE (rhs) == COND_EXPR) ! { ! /* Sadly, we have to handle conditional assignments specially ! here, because fold expects all the operands of an expression ! to be folded before the expression itself is folded, but we ! can't just substitute the folded condition here. */ ! tree cond = fold (COND_EXPR_COND (rhs)); ! if (cond == boolean_true_node) ! rhs = COND_EXPR_THEN (rhs); ! else if (cond == boolean_false_node) ! rhs = COND_EXPR_ELSE (rhs); ! } ! ! return fold (rhs); ! } case GIMPLE_UNARY_RHS: { --- 225,231 ---- switch (get_gimple_rhs_class (subcode)) { case GIMPLE_SINGLE_RHS: ! return fold (gimple_assign_rhs1 (stmt)); case GIMPLE_UNARY_RHS: { *************** fold_assignment_stmt (gimple stmt) *** 265,270 **** --- 248,261 ---- tree op0 = gimple_assign_rhs1 (stmt); tree op1 = gimple_assign_rhs2 (stmt); tree op2 = gimple_assign_rhs3 (stmt); + + /* Sadly, we have to handle conditional assignments specially + here, because fold expects all the operands of an expression + to be folded before the expression itself is folded, but we + can't just substitute the folded condition here. */ + if (gimple_assign_rhs_code (stmt) == COND_EXPR) + op0 = fold (op0); + return fold_ternary (subcode, TREE_TYPE (lhs), op0, op1, op2); } Index: trunk/gcc/tree-vect-loop.c =================================================================== *** trunk.orig/gcc/tree-vect-loop.c 2011-09-01 12:08:51.000000000 +0200 --- trunk/gcc/tree-vect-loop.c 2011-09-01 12:10:04.000000000 +0200 *************** vect_is_simple_reduction_1 (loop_vec_inf *** 2126,2140 **** return NULL; } ! op3 = TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 0); if (COMPARISON_CLASS_P (op3)) { op4 = TREE_OPERAND (op3, 1); op3 = TREE_OPERAND (op3, 0); } ! op1 = TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 1); ! op2 = TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 2); if (TREE_CODE (op1) != SSA_NAME && TREE_CODE (op2) != SSA_NAME) { --- 2126,2140 ---- return NULL; } ! op3 = gimple_assign_rhs1 (def_stmt); if (COMPARISON_CLASS_P (op3)) { op4 = TREE_OPERAND (op3, 1); op3 = TREE_OPERAND (op3, 0); } ! op1 = gimple_assign_rhs2 (def_stmt); ! op2 = gimple_assign_rhs3 (def_stmt); if (TREE_CODE (op1) != SSA_NAME && TREE_CODE (op2) != SSA_NAME) { Index: trunk/gcc/tree-vect-stmts.c =================================================================== *** trunk.orig/gcc/tree-vect-stmts.c 2011-09-01 12:08:51.000000000 +0200 --- trunk/gcc/tree-vect-stmts.c 2011-09-01 12:10:04.000000000 +0200 *************** vectorizable_condition (gimple stmt, gim *** 4740,4746 **** { tree scalar_dest = NULL_TREE; tree vec_dest = NULL_TREE; - tree op = NULL_TREE; tree cond_expr, then_clause, else_clause; stmt_vec_info stmt_info = vinfo_for_stmt (stmt); tree vectype = STMT_VINFO_VECTYPE (stmt_info); --- 4740,4745 ---- *************** vectorizable_condition (gimple stmt, gim *** 4794,4804 **** if (code != COND_EXPR) return false; ! gcc_assert (gimple_assign_single_p (stmt)); ! op = gimple_assign_rhs1 (stmt); ! cond_expr = TREE_OPERAND (op, 0); ! then_clause = TREE_OPERAND (op, 1); ! else_clause = TREE_OPERAND (op, 2); if (!vect_is_simple_cond (cond_expr, loop_vinfo)) return false; --- 4793,4801 ---- if (code != COND_EXPR) return false; ! cond_expr = gimple_assign_rhs1 (stmt); ! then_clause = gimple_assign_rhs2 (stmt); ! else_clause = gimple_assign_rhs3 (stmt); if (!vect_is_simple_cond (cond_expr, loop_vinfo)) return false; *************** vectorizable_condition (gimple stmt, gim *** 4839,4845 **** if (!vec_stmt) { STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type; ! return expand_vec_cond_expr_p (TREE_TYPE (op), vec_mode); } /* Transform */ --- 4836,4843 ---- if (!vec_stmt) { STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type; ! return expand_vec_cond_expr_p (TREE_TYPE (gimple_assign_lhs (stmt)), ! vec_mode); } /* Transform */ Index: trunk/gcc/tree-vrp.c =================================================================== *** trunk.orig/gcc/tree-vrp.c 2011-09-01 12:08:51.000000000 +0200 --- trunk/gcc/tree-vrp.c 2011-09-01 12:10:04.000000000 +0200 *************** extract_range_from_unary_expr (value_ran *** 3190,3200 **** } ! /* Extract range information from a conditional expression EXPR based on the ranges of each of its operands and the expression code. */ static void ! extract_range_from_cond_expr (value_range_t *vr, tree expr) { tree op0, op1; value_range_t vr0 = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL }; --- 3190,3200 ---- } ! /* Extract range information from a conditional expression STMT based on the ranges of each of its operands and the expression code. */ static void ! extract_range_from_cond_expr (value_range_t *vr, gimple stmt) { tree op0, op1; value_range_t vr0 = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL }; *************** extract_range_from_cond_expr (value_rang *** 3202,3208 **** /* Get value ranges for each operand. For constant operands, create a new value range with the operand to simplify processing. */ ! op0 = COND_EXPR_THEN (expr); if (TREE_CODE (op0) == SSA_NAME) vr0 = *(get_value_range (op0)); else if (is_gimple_min_invariant (op0)) --- 3202,3208 ---- /* Get value ranges for each operand. For constant operands, create a new value range with the operand to simplify processing. */ ! op0 = gimple_assign_rhs2 (stmt); if (TREE_CODE (op0) == SSA_NAME) vr0 = *(get_value_range (op0)); else if (is_gimple_min_invariant (op0)) *************** extract_range_from_cond_expr (value_rang *** 3210,3216 **** else set_value_range_to_varying (&vr0); ! op1 = COND_EXPR_ELSE (expr); if (TREE_CODE (op1) == SSA_NAME) vr1 = *(get_value_range (op1)); else if (is_gimple_min_invariant (op1)) --- 3210,3216 ---- else set_value_range_to_varying (&vr0); ! op1 = gimple_assign_rhs3 (stmt); if (TREE_CODE (op1) == SSA_NAME) vr1 = *(get_value_range (op1)); else if (is_gimple_min_invariant (op1)) *************** extract_range_from_assignment (value_ran *** 3302,3308 **** gimple_expr_type (stmt), gimple_assign_rhs1 (stmt)); else if (code == COND_EXPR) ! extract_range_from_cond_expr (vr, gimple_assign_rhs1 (stmt)); else if (TREE_CODE_CLASS (code) == tcc_comparison) extract_range_from_comparison (vr, gimple_assign_rhs_code (stmt), gimple_expr_type (stmt), --- 3302,3308 ---- gimple_expr_type (stmt), gimple_assign_rhs1 (stmt)); else if (code == COND_EXPR) ! extract_range_from_cond_expr (vr, stmt); else if (TREE_CODE_CLASS (code) == tcc_comparison) extract_range_from_comparison (vr, gimple_assign_rhs_code (stmt), gimple_expr_type (stmt),