expr.c (expand_expr_real_2): Move COND_EXPR and VEC_COND_EXPR handling here, from ...

2011-08-31  Richard Guenther  <rguenther@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.

From-SVN: r178408
This commit is contained in:
Richard Guenther 2011-09-01 11:46:08 +00:00 committed by Richard Biener
parent dbe36d674a
commit 4e71066d7e
14 changed files with 220 additions and 187 deletions

View file

@ -1,3 +1,31 @@
2011-08-31 Richard Guenther <rguenther@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.
2011-08-31 Richard Sandiford <rdsandiford@googlemail.com> 2011-08-31 Richard Sandiford <rdsandiford@googlemail.com>
* config/i386/i386.md: Use (match_test ...) for attribute tests. * config/i386/i386.md: Use (match_test ...) for attribute tests.

View file

@ -8636,6 +8636,64 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
return temp; 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: default:
gcc_unreachable (); gcc_unreachable ();
} }
@ -9878,64 +9936,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
return op0; 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: case MODIFY_EXPR:
{ {
tree lhs = treeop0; tree lhs = treeop0;

View file

@ -294,42 +294,7 @@ fold_gimple_assign (gimple_stmt_iterator *si)
{ {
tree rhs = gimple_assign_rhs1 (stmt); tree rhs = gimple_assign_rhs1 (stmt);
/* Try to fold a conditional expression. */ if (REFERENCE_CLASS_P (rhs))
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); return maybe_fold_reference (rhs, false);
else if (TREE_CODE (rhs) == ADDR_EXPR) else if (TREE_CODE (rhs) == ADDR_EXPR)
@ -469,11 +434,49 @@ fold_gimple_assign (gimple_stmt_iterator *si)
break; break;
case GIMPLE_TERNARY_RHS: case GIMPLE_TERNARY_RHS:
result = fold_ternary_loc (loc, subcode, /* Try to fold a conditional expression. */
TREE_TYPE (gimple_assign_lhs (stmt)), if (gimple_assign_rhs_code (stmt) == COND_EXPR)
gimple_assign_rhs1 (stmt), {
gimple_assign_rhs2 (stmt), tree op0 = gimple_assign_rhs1 (stmt);
gimple_assign_rhs3 (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) if (result)
{ {

View file

@ -428,6 +428,24 @@ dump_ternary_rhs (pretty_printer *buffer, gimple gs, int spc, int flags)
pp_string (buffer, ">"); pp_string (buffer, ">");
break; 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: default:
gcc_unreachable (); gcc_unreachable ();
} }

View file

@ -2611,19 +2611,19 @@ get_gimple_rhs_num_ops (enum tree_code code)
|| (SYM) == TRUTH_OR_EXPR \ || (SYM) == TRUTH_OR_EXPR \
|| (SYM) == TRUTH_XOR_EXPR) ? GIMPLE_BINARY_RHS \ || (SYM) == TRUTH_XOR_EXPR) ? GIMPLE_BINARY_RHS \
: (SYM) == TRUTH_NOT_EXPR ? GIMPLE_UNARY_RHS \ : (SYM) == TRUTH_NOT_EXPR ? GIMPLE_UNARY_RHS \
: ((SYM) == WIDEN_MULT_PLUS_EXPR \ : ((SYM) == COND_EXPR \
|| (SYM) == WIDEN_MULT_PLUS_EXPR \
|| (SYM) == WIDEN_MULT_MINUS_EXPR \ || (SYM) == WIDEN_MULT_MINUS_EXPR \
|| (SYM) == DOT_PROD_EXPR \ || (SYM) == DOT_PROD_EXPR \
|| (SYM) == REALIGN_LOAD_EXPR \ || (SYM) == REALIGN_LOAD_EXPR \
|| (SYM) == VEC_COND_EXPR \
|| (SYM) == FMA_EXPR) ? GIMPLE_TERNARY_RHS \ || (SYM) == FMA_EXPR) ? GIMPLE_TERNARY_RHS \
: ((SYM) == COND_EXPR \ : ((SYM) == CONSTRUCTOR \
|| (SYM) == CONSTRUCTOR \
|| (SYM) == OBJ_TYPE_REF \ || (SYM) == OBJ_TYPE_REF \
|| (SYM) == ASSERT_EXPR \ || (SYM) == ASSERT_EXPR \
|| (SYM) == ADDR_EXPR \ || (SYM) == ADDR_EXPR \
|| (SYM) == WITH_SIZE_EXPR \ || (SYM) == WITH_SIZE_EXPR \
|| (SYM) == SSA_NAME \ || (SYM) == SSA_NAME) ? GIMPLE_SINGLE_RHS \
|| (SYM) == VEC_COND_EXPR) ? GIMPLE_SINGLE_RHS \
: GIMPLE_INVALID_RHS), : GIMPLE_INVALID_RHS),
#define END_OF_BASE_TREE_CODES (unsigned char) GIMPLE_INVALID_RHS, #define END_OF_BASE_TREE_CODES (unsigned char) GIMPLE_INVALID_RHS,

View file

@ -3668,7 +3668,8 @@ verify_gimple_assign_ternary (gimple stmt)
return true; return true;
} }
if (!is_gimple_val (rhs1) 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 (rhs2)
|| !is_gimple_val (rhs3)) || !is_gimple_val (rhs3))
{ {
@ -3711,6 +3712,19 @@ verify_gimple_assign_ternary (gimple stmt)
} }
break; 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 DOT_PROD_EXPR:
case REALIGN_LOAD_EXPR: case REALIGN_LOAD_EXPR:
/* FIXME. */ /* FIXME. */
@ -3827,26 +3841,10 @@ verify_gimple_assign_single (gimple stmt)
} }
return res; 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 CONSTRUCTOR:
case OBJ_TYPE_REF: case OBJ_TYPE_REF:
case ASSERT_EXPR: case ASSERT_EXPR:
case WITH_SIZE_EXPR: case WITH_SIZE_EXPR:
case VEC_COND_EXPR:
/* FIXME. */ /* FIXME. */
return res; return res;

View file

@ -53,7 +53,7 @@ static void expr_object_size (struct object_size_info *, tree, tree);
static bool merge_object_sizes (struct object_size_info *, tree, tree, static bool merge_object_sizes (struct object_size_info *, tree, tree,
unsigned HOST_WIDE_INT); unsigned HOST_WIDE_INT);
static bool plus_stmt_object_size (struct object_size_info *, tree, gimple); 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 bool cond_expr_object_size (struct object_size_info *, tree, gimple);
static unsigned int compute_object_sizes (void); static unsigned int compute_object_sizes (void);
static void init_offset_limit (void); static void init_offset_limit (void);
static void check_for_plus_in_loops (struct object_size_info *, tree); static void check_for_plus_in_loops (struct object_size_info *, tree);
@ -827,25 +827,25 @@ plus_stmt_object_size (struct object_size_info *osi, tree var, gimple stmt)
} }
/* Compute object_sizes for VAR, defined to VALUE, which is /* Compute object_sizes for VAR, defined at STMT, which is
a COND_EXPR. Return true if the object size might need reexamination a COND_EXPR. Return true if the object size might need reexamination
later. */ later. */
static bool static bool
cond_expr_object_size (struct object_size_info *osi, tree var, tree value) cond_expr_object_size (struct object_size_info *osi, tree var, gimple stmt)
{ {
tree then_, else_; tree then_, else_;
int object_size_type = osi->object_size_type; int object_size_type = osi->object_size_type;
unsigned int varno = SSA_NAME_VERSION (var); unsigned int varno = SSA_NAME_VERSION (var);
bool reexamine = false; bool reexamine = false;
gcc_assert (TREE_CODE (value) == COND_EXPR); gcc_assert (gimple_assign_rhs_code (stmt) == COND_EXPR);
if (object_sizes[object_size_type][varno] == unknown[object_size_type]) if (object_sizes[object_size_type][varno] == unknown[object_size_type])
return false; return false;
then_ = COND_EXPR_THEN (value); then_ = gimple_assign_rhs2 (stmt);
else_ = COND_EXPR_ELSE (value); else_ = gimple_assign_rhs3 (stmt);
if (TREE_CODE (then_) == SSA_NAME) if (TREE_CODE (then_) == SSA_NAME)
reexamine |= merge_object_sizes (osi, var, then_, 0); reexamine |= merge_object_sizes (osi, var, then_, 0);
@ -932,14 +932,14 @@ collect_object_sizes_for (struct object_size_info *osi, tree var)
|| (gimple_assign_rhs_code (stmt) == ADDR_EXPR || (gimple_assign_rhs_code (stmt) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (rhs, 0)) == MEM_REF)) && TREE_CODE (TREE_OPERAND (rhs, 0)) == MEM_REF))
reexamine = plus_stmt_object_size (osi, var, stmt); 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) else if (gimple_assign_single_p (stmt)
|| gimple_assign_unary_nop_p (stmt)) || gimple_assign_unary_nop_p (stmt))
{ {
if (TREE_CODE (rhs) == SSA_NAME if (TREE_CODE (rhs) == SSA_NAME
&& POINTER_TYPE_P (TREE_TYPE (rhs))) && POINTER_TYPE_P (TREE_TYPE (rhs)))
reexamine = merge_object_sizes (osi, var, rhs, 0); reexamine = merge_object_sizes (osi, var, rhs, 0);
else if (TREE_CODE (rhs) == COND_EXPR)
reexamine = cond_expr_object_size (osi, var, rhs);
else else
expr_object_size (osi, var, rhs); expr_object_size (osi, var, rhs);
} }
@ -956,8 +956,6 @@ collect_object_sizes_for (struct object_size_info *osi, tree var)
if (TREE_CODE (arg) == SSA_NAME if (TREE_CODE (arg) == SSA_NAME
&& POINTER_TYPE_P (TREE_TYPE (arg))) && POINTER_TYPE_P (TREE_TYPE (arg)))
reexamine = merge_object_sizes (osi, var, arg, 0); reexamine = merge_object_sizes (osi, var, arg, 0);
else if (TREE_CODE (arg) == COND_EXPR)
reexamine = cond_expr_object_size (osi, var, arg);
else else
expr_object_size (osi, var, arg); expr_object_size (osi, var, arg);
} }

View file

@ -1796,7 +1796,8 @@ interpret_expr (struct loop *loop, gimple at_stmt, tree expr)
if (automatically_generated_chrec_p (expr)) if (automatically_generated_chrec_p (expr))
return expr; return expr;
if (TREE_CODE (expr) == POLYNOMIAL_CHREC) if (TREE_CODE (expr) == POLYNOMIAL_CHREC
|| get_gimple_rhs_class (TREE_CODE (expr)) == GIMPLE_TERNARY_RHS)
return chrec_dont_know; return chrec_dont_know;
extract_ops_from_tree (expr, &code, &op0, &op1); extract_ops_from_tree (expr, &code, &op0, &op1);

View file

@ -540,12 +540,9 @@ forward_propagate_into_gimple_cond (gimple stmt)
/* Propagate from the ssa name definition statements of COND_EXPR /* Propagate from the ssa name definition statements of COND_EXPR
in the rhs of statement STMT into the conditional if that simplifies it. in the rhs of statement STMT into the conditional if that simplifies it.
Returns zero if no statement was changed, one if there were Returns true zero if the stmt was changed. */
changes and two if cfg_cleanup needs to run.
This must be kept in sync with forward_propagate_into_gimple_cond. */ static bool
static int
forward_propagate_into_cond (gimple_stmt_iterator *gsi_p) forward_propagate_into_cond (gimple_stmt_iterator *gsi_p)
{ {
gimple stmt = gsi_stmt (*gsi_p); gimple stmt = gsi_stmt (*gsi_p);
@ -560,15 +557,17 @@ forward_propagate_into_cond (gimple_stmt_iterator *gsi_p)
TREE_OPERAND (cond, 1)); TREE_OPERAND (cond, 1));
else if (TREE_CODE (cond) == SSA_NAME) else if (TREE_CODE (cond) == SSA_NAME)
{ {
tree name = cond, rhs0; tree name = cond;
gimple def_stmt = get_prop_source_stmt (name, true, NULL); gimple def_stmt = get_prop_source_stmt (name, true, NULL);
if (!def_stmt || !can_propagate_from (def_stmt)) if (!def_stmt || !can_propagate_from (def_stmt))
return 0; return 0;
rhs0 = gimple_assign_rhs1 (def_stmt); if (TREE_CODE_CLASS (gimple_assign_rhs_code (def_stmt)) == tcc_comparison)
tmp = combine_cond_expr_cond (stmt, NE_EXPR, boolean_type_node, rhs0, tmp = fold_build2_loc (gimple_location (def_stmt),
build_int_cst (TREE_TYPE (rhs0), 0), gimple_assign_rhs_code (def_stmt),
false); boolean_type_node,
gimple_assign_rhs1 (def_stmt),
gimple_assign_rhs2 (def_stmt));
} }
if (tmp) if (tmp)
@ -582,11 +581,16 @@ forward_propagate_into_cond (gimple_stmt_iterator *gsi_p)
fprintf (dump_file, "'\n"); fprintf (dump_file, "'\n");
} }
gimple_assign_set_rhs_from_tree (gsi_p, unshare_expr (tmp)); 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); stmt = gsi_stmt (*gsi_p);
update_stmt (stmt); update_stmt (stmt);
return is_gimple_min_invariant (tmp) ? 2 : 1; return true;
} }
return 0; return 0;
@ -2436,12 +2440,8 @@ ssa_forward_propagate_and_combine (void)
else if (code == COND_EXPR) else if (code == COND_EXPR)
{ {
/* In this case the entire COND_EXPR is in rhs1. */ /* In this case the entire COND_EXPR is in rhs1. */
int did_something; changed |= forward_propagate_into_cond (&gsi);
did_something = forward_propagate_into_cond (&gsi);
stmt = gsi_stmt (gsi); stmt = gsi_stmt (gsi);
if (did_something == 2)
cfg_changed = true;
changed = did_something != 0;
} }
else if (TREE_CODE_CLASS (code) == tcc_comparison) else if (TREE_CODE_CLASS (code) == tcc_comparison)
{ {

View file

@ -1251,11 +1251,9 @@ move_computations_stmt (struct dom_walk_data *dw_data,
gcc_assert (arg0 && arg1); gcc_assert (arg0 && arg1);
t = build2 (gimple_cond_code (cond), boolean_type_node, t = build2 (gimple_cond_code (cond), boolean_type_node,
gimple_cond_lhs (cond), gimple_cond_rhs (cond)); gimple_cond_lhs (cond), gimple_cond_rhs (cond));
t = build3 (COND_EXPR, TREE_TYPE (gimple_phi_result (stmt)), new_stmt = gimple_build_assign_with_ops3 (COND_EXPR,
t, arg0, arg1); gimple_phi_result (stmt),
new_stmt = gimple_build_assign_with_ops (COND_EXPR, t, arg0, arg1);
gimple_phi_result (stmt),
t, NULL_TREE);
SSA_NAME_DEF_STMT (gimple_phi_result (stmt)) = new_stmt; SSA_NAME_DEF_STMT (gimple_phi_result (stmt)) = new_stmt;
*((unsigned int *)(dw_data->global_data)) |= TODO_cleanup_cfg; *((unsigned int *)(dw_data->global_data)) |= TODO_cleanup_cfg;
} }

View file

@ -225,24 +225,7 @@ fold_assignment_stmt (gimple stmt)
switch (get_gimple_rhs_class (subcode)) switch (get_gimple_rhs_class (subcode))
{ {
case GIMPLE_SINGLE_RHS: case GIMPLE_SINGLE_RHS:
{ return fold (gimple_assign_rhs1 (stmt));
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: case GIMPLE_UNARY_RHS:
{ {
@ -265,6 +248,14 @@ fold_assignment_stmt (gimple stmt)
tree op0 = gimple_assign_rhs1 (stmt); tree op0 = gimple_assign_rhs1 (stmt);
tree op1 = gimple_assign_rhs2 (stmt); tree op1 = gimple_assign_rhs2 (stmt);
tree op2 = gimple_assign_rhs3 (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); return fold_ternary (subcode, TREE_TYPE (lhs), op0, op1, op2);
} }

View file

@ -2126,15 +2126,15 @@ vect_is_simple_reduction_1 (loop_vec_info loop_info, gimple phi,
return NULL; return NULL;
} }
op3 = TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 0); op3 = gimple_assign_rhs1 (def_stmt);
if (COMPARISON_CLASS_P (op3)) if (COMPARISON_CLASS_P (op3))
{ {
op4 = TREE_OPERAND (op3, 1); op4 = TREE_OPERAND (op3, 1);
op3 = TREE_OPERAND (op3, 0); op3 = TREE_OPERAND (op3, 0);
} }
op1 = TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 1); op1 = gimple_assign_rhs2 (def_stmt);
op2 = TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 2); op2 = gimple_assign_rhs3 (def_stmt);
if (TREE_CODE (op1) != SSA_NAME && TREE_CODE (op2) != SSA_NAME) if (TREE_CODE (op1) != SSA_NAME && TREE_CODE (op2) != SSA_NAME)
{ {

View file

@ -4740,7 +4740,6 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
{ {
tree scalar_dest = NULL_TREE; tree scalar_dest = NULL_TREE;
tree vec_dest = NULL_TREE; tree vec_dest = NULL_TREE;
tree op = NULL_TREE;
tree cond_expr, then_clause, else_clause; tree cond_expr, then_clause, else_clause;
stmt_vec_info stmt_info = vinfo_for_stmt (stmt); stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
tree vectype = STMT_VINFO_VECTYPE (stmt_info); tree vectype = STMT_VINFO_VECTYPE (stmt_info);
@ -4794,11 +4793,9 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
if (code != COND_EXPR) if (code != COND_EXPR)
return false; return false;
gcc_assert (gimple_assign_single_p (stmt)); cond_expr = gimple_assign_rhs1 (stmt);
op = gimple_assign_rhs1 (stmt); then_clause = gimple_assign_rhs2 (stmt);
cond_expr = TREE_OPERAND (op, 0); else_clause = gimple_assign_rhs3 (stmt);
then_clause = TREE_OPERAND (op, 1);
else_clause = TREE_OPERAND (op, 2);
if (!vect_is_simple_cond (cond_expr, loop_vinfo)) if (!vect_is_simple_cond (cond_expr, loop_vinfo))
return false; return false;
@ -4839,7 +4836,8 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
if (!vec_stmt) if (!vec_stmt)
{ {
STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type; STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
return expand_vec_cond_expr_p (TREE_TYPE (op), vec_mode); return expand_vec_cond_expr_p (TREE_TYPE (gimple_assign_lhs (stmt)),
vec_mode);
} }
/* Transform */ /* Transform */

View file

@ -3190,11 +3190,11 @@ extract_range_from_unary_expr (value_range_t *vr, enum tree_code code,
} }
/* Extract range information from a conditional expression EXPR based on /* Extract range information from a conditional expression STMT based on
the ranges of each of its operands and the expression code. */ the ranges of each of its operands and the expression code. */
static void static void
extract_range_from_cond_expr (value_range_t *vr, tree expr) extract_range_from_cond_expr (value_range_t *vr, gimple stmt)
{ {
tree op0, op1; tree op0, op1;
value_range_t vr0 = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL }; value_range_t vr0 = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
@ -3202,7 +3202,7 @@ extract_range_from_cond_expr (value_range_t *vr, tree expr)
/* Get value ranges for each operand. For constant operands, create /* Get value ranges for each operand. For constant operands, create
a new value range with the operand to simplify processing. */ a new value range with the operand to simplify processing. */
op0 = COND_EXPR_THEN (expr); op0 = gimple_assign_rhs2 (stmt);
if (TREE_CODE (op0) == SSA_NAME) if (TREE_CODE (op0) == SSA_NAME)
vr0 = *(get_value_range (op0)); vr0 = *(get_value_range (op0));
else if (is_gimple_min_invariant (op0)) else if (is_gimple_min_invariant (op0))
@ -3210,7 +3210,7 @@ extract_range_from_cond_expr (value_range_t *vr, tree expr)
else else
set_value_range_to_varying (&vr0); set_value_range_to_varying (&vr0);
op1 = COND_EXPR_ELSE (expr); op1 = gimple_assign_rhs3 (stmt);
if (TREE_CODE (op1) == SSA_NAME) if (TREE_CODE (op1) == SSA_NAME)
vr1 = *(get_value_range (op1)); vr1 = *(get_value_range (op1));
else if (is_gimple_min_invariant (op1)) else if (is_gimple_min_invariant (op1))
@ -3302,7 +3302,7 @@ extract_range_from_assignment (value_range_t *vr, gimple stmt)
gimple_expr_type (stmt), gimple_expr_type (stmt),
gimple_assign_rhs1 (stmt)); gimple_assign_rhs1 (stmt));
else if (code == COND_EXPR) else if (code == COND_EXPR)
extract_range_from_cond_expr (vr, gimple_assign_rhs1 (stmt)); extract_range_from_cond_expr (vr, stmt);
else if (TREE_CODE_CLASS (code) == tcc_comparison) else if (TREE_CODE_CLASS (code) == tcc_comparison)
extract_range_from_comparison (vr, gimple_assign_rhs_code (stmt), extract_range_from_comparison (vr, gimple_assign_rhs_code (stmt),
gimple_expr_type (stmt), gimple_expr_type (stmt),