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:
parent
dbe36d674a
commit
4e71066d7e
14 changed files with 220 additions and 187 deletions
|
@ -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.
|
||||||
|
|
116
gcc/expr.c
116
gcc/expr.c
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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 ();
|
||||||
}
|
}
|
||||||
|
|
10
gcc/gimple.c
10
gcc/gimple.c
|
@ -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)
|
||||||
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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
/* 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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
{
|
{
|
||||||
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 */
|
||||||
|
|
|
@ -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),
|
||||||
|
|
Loading…
Add table
Reference in a new issue