Commit 4e71066d by Richard Guenther Committed by Richard Biener

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
parent dbe36d67
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.
...@@ -8636,6 +8636,64 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode, ...@@ -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, ...@@ -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;
......
...@@ -294,42 +294,7 @@ fold_gimple_assign (gimple_stmt_iterator *si) ...@@ -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) ...@@ -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)
{ {
......
...@@ -428,6 +428,24 @@ dump_ternary_rhs (pretty_printer *buffer, gimple gs, int spc, int flags) ...@@ -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 ();
} }
......
...@@ -2611,19 +2611,19 @@ get_gimple_rhs_num_ops (enum tree_code code) ...@@ -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,
......
...@@ -3668,7 +3668,8 @@ verify_gimple_assign_ternary (gimple stmt) ...@@ -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) ...@@ -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) ...@@ -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;
......
...@@ -53,7 +53,7 @@ static void expr_object_size (struct object_size_info *, tree, tree); ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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);
} }
......
...@@ -1796,7 +1796,8 @@ interpret_expr (struct loop *loop, gimple at_stmt, tree expr) ...@@ -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);
......
...@@ -540,12 +540,9 @@ forward_propagate_into_gimple_cond (gimple stmt) ...@@ -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 int static bool
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) ...@@ -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) ...@@ -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) ...@@ -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)
{ {
......
...@@ -1251,11 +1251,9 @@ move_computations_stmt (struct dom_walk_data *dw_data, ...@@ -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;
} }
......
...@@ -225,24 +225,7 @@ fold_assignment_stmt (gimple stmt) ...@@ -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) ...@@ -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);
} }
......
...@@ -2126,15 +2126,15 @@ vect_is_simple_reduction_1 (loop_vec_info loop_info, gimple phi, ...@@ -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)
{ {
......
...@@ -4740,7 +4740,6 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi, ...@@ -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, ...@@ -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, ...@@ -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 */
......
...@@ -3190,11 +3190,11 @@ extract_range_from_unary_expr (value_range_t *vr, enum tree_code code, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment