Commit f255541f by Roberto Costa Committed by Roberto Costa

Better handling of COND_EXPRs in rhs

From-SVN: r120581
parent feb8476a
2007-01-08 Roberto Costa <roberto.costa@st.com>
* tree-vrp.c (extract_range_from_cond_expr): New.
(extract_range_from_expr): Handle COND_EXPR nodes used as expressions.
* tree-ssa-ccp.c (get_maxval_strlen): Handle COND_EXPR nodes used
as expressions.
(fold_stmt): Bug fix, avoid infinite recursion when folding COND_EXPRs.
* tree-ssa-forwprop.c (simplify_cond, forward_propagate_into_cond,
tree_ssa_forward_propagate_single_use_vars): Handle COND_EXPR nodes
used as expressions.
* tree-object-size.c (cond_expr_object_size): New.
(collect_object_sizes_for): Handle COND_EXPR nodes used as expressions.
2007-01-08 Jan Hubicka <jh@suse.cz> 2007-01-08 Jan Hubicka <jh@suse.cz>
* tree-ssa-forwprop.c (forward_propagate_into_cond, * tree-ssa-forwprop.c (forward_propagate_into_cond,
......
...@@ -50,6 +50,7 @@ static void expr_object_size (struct object_size_info *, tree, tree); ...@@ -50,6 +50,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_expr_object_size (struct object_size_info *, tree, tree); static bool plus_expr_object_size (struct object_size_info *, tree, tree);
static bool cond_expr_object_size (struct object_size_info *, tree, tree);
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);
...@@ -621,6 +622,40 @@ plus_expr_object_size (struct object_size_info *osi, tree var, tree value) ...@@ -621,6 +622,40 @@ plus_expr_object_size (struct object_size_info *osi, tree var, tree value)
} }
/* Compute object_sizes for PTR, 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);
else
expr_object_size (osi, var, then_);
if (TREE_CODE (else_) == SSA_NAME)
reexamine |= merge_object_sizes (osi, var, else_, 0);
else
expr_object_size (osi, var, else_);
return reexamine;
}
/* Compute object sizes for VAR. /* Compute object sizes for VAR.
For ADDR_EXPR an object size is the number of remaining bytes For ADDR_EXPR an object size is the number of remaining bytes
to the end of the object (where what is considered an object depends on to the end of the object (where what is considered an object depends on
...@@ -711,6 +746,9 @@ collect_object_sizes_for (struct object_size_info *osi, tree var) ...@@ -711,6 +746,9 @@ collect_object_sizes_for (struct object_size_info *osi, tree var)
else if (TREE_CODE (rhs) == PLUS_EXPR) else if (TREE_CODE (rhs) == PLUS_EXPR)
reexamine = plus_expr_object_size (osi, var, rhs); reexamine = plus_expr_object_size (osi, var, rhs);
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);
break; break;
......
...@@ -2109,6 +2109,10 @@ get_maxval_strlen (tree arg, tree *length, bitmap visited, int type) ...@@ -2109,6 +2109,10 @@ get_maxval_strlen (tree arg, tree *length, bitmap visited, int type)
if (TREE_CODE (arg) != SSA_NAME) if (TREE_CODE (arg) != SSA_NAME)
{ {
if (TREE_CODE (arg) == COND_EXPR)
return get_maxval_strlen (COND_EXPR_THEN (arg), length, visited, type)
&& get_maxval_strlen (COND_EXPR_ELSE (arg), length, visited, type);
if (type == 2) if (type == 2)
{ {
val = arg; val = arg;
...@@ -2438,6 +2442,13 @@ fold_stmt (tree *stmt_p) ...@@ -2438,6 +2442,13 @@ fold_stmt (tree *stmt_p)
} }
} }
} }
else if (TREE_CODE (rhs) == COND_EXPR)
{
tree temp = fold (COND_EXPR_COND (rhs));
if (temp != COND_EXPR_COND (rhs))
result = fold_build3 (COND_EXPR, TREE_TYPE (rhs), temp,
COND_EXPR_THEN (rhs), COND_EXPR_ELSE (rhs));
}
/* If we couldn't fold the RHS, hand over to the generic fold routines. */ /* If we couldn't fold the RHS, hand over to the generic fold routines. */
if (result == NULL_TREE) if (result == NULL_TREE)
......
...@@ -490,15 +490,16 @@ find_equivalent_equality_comparison (tree cond) ...@@ -490,15 +490,16 @@ find_equivalent_equality_comparison (tree cond)
return NULL; return NULL;
} }
/* STMT is a COND_EXPR /* EXPR is a COND_EXPR
STMT is the statement containing EXPR.
This routine attempts to find equivalent forms of the condition This routine attempts to find equivalent forms of the condition
which we may be able to optimize better. */ which we may be able to optimize better. */
static void static void
simplify_cond (tree stmt) simplify_cond (tree cond_expr, tree stmt)
{ {
tree cond = COND_EXPR_COND (stmt); tree cond = COND_EXPR_COND (cond_expr);
if (COMPARISON_CLASS_P (cond)) if (COMPARISON_CLASS_P (cond))
{ {
...@@ -517,7 +518,7 @@ simplify_cond (tree stmt) ...@@ -517,7 +518,7 @@ simplify_cond (tree stmt)
if (new_cond) if (new_cond)
{ {
COND_EXPR_COND (stmt) = new_cond; COND_EXPR_COND (cond_expr) = new_cond;
update_stmt (stmt); update_stmt (stmt);
} }
} }
...@@ -529,7 +530,7 @@ simplify_cond (tree stmt) ...@@ -529,7 +530,7 @@ simplify_cond (tree stmt)
times as possible. */ times as possible. */
static void static void
forward_propagate_into_cond (tree cond_expr) forward_propagate_into_cond (tree cond_expr, tree stmt)
{ {
gcc_assert (TREE_CODE (cond_expr) == COND_EXPR); gcc_assert (TREE_CODE (cond_expr) == COND_EXPR);
...@@ -554,7 +555,7 @@ forward_propagate_into_cond (tree cond_expr) ...@@ -554,7 +555,7 @@ forward_propagate_into_cond (tree cond_expr)
} }
COND_EXPR_COND (cond_expr) = new_cond; COND_EXPR_COND (cond_expr) = new_cond;
update_stmt (cond_expr); update_stmt (stmt);
if (has_zero_uses (test_var)) if (has_zero_uses (test_var))
{ {
...@@ -570,7 +571,7 @@ forward_propagate_into_cond (tree cond_expr) ...@@ -570,7 +571,7 @@ forward_propagate_into_cond (tree cond_expr)
against a constant where the SSA_NAME is the result of a against a constant where the SSA_NAME is the result of a
conversion. Perhaps this should be folded into the rest conversion. Perhaps this should be folded into the rest
of the COND_EXPR simplification code. */ of the COND_EXPR simplification code. */
simplify_cond (cond_expr); simplify_cond (cond_expr, stmt);
} }
/* We've just substituted an ADDR_EXPR into stmt. Update all the /* We've just substituted an ADDR_EXPR into stmt. Update all the
...@@ -1016,6 +1017,11 @@ tree_ssa_forward_propagate_single_use_vars (void) ...@@ -1016,6 +1017,11 @@ tree_ssa_forward_propagate_single_use_vars (void)
simplify_not_neg_expr (stmt); simplify_not_neg_expr (stmt);
bsi_next (&bsi); bsi_next (&bsi);
} }
else if (TREE_CODE (rhs) == COND_EXPR)
{
forward_propagate_into_cond (rhs, stmt);
bsi_next (&bsi);
}
else else
bsi_next (&bsi); bsi_next (&bsi);
} }
...@@ -1026,7 +1032,7 @@ tree_ssa_forward_propagate_single_use_vars (void) ...@@ -1026,7 +1032,7 @@ tree_ssa_forward_propagate_single_use_vars (void)
} }
else if (TREE_CODE (stmt) == COND_EXPR) else if (TREE_CODE (stmt) == COND_EXPR)
{ {
forward_propagate_into_cond (stmt); forward_propagate_into_cond (stmt, stmt);
bsi_next (&bsi); bsi_next (&bsi);
} }
else else
......
...@@ -43,6 +43,7 @@ static sbitmap found_in_subgraph; ...@@ -43,6 +43,7 @@ static sbitmap found_in_subgraph;
/* Local functions. */ /* Local functions. */
static int compare_values (tree val1, tree val2); static int compare_values (tree val1, tree val2);
static void vrp_meet (value_range_t *, value_range_t *);
/* Location information for ASSERT_EXPRs. Each instance of this /* Location information for ASSERT_EXPRs. Each instance of this
structure describes an ASSERT_EXPR for an SSA name. Since a single structure describes an ASSERT_EXPR for an SSA name. Since a single
...@@ -1919,6 +1920,40 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr) ...@@ -1919,6 +1920,40 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
} }
/* 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 };
value_range_t vr1 = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
/* 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))
set_value_range (&vr0, VR_RANGE, op0, op0, NULL);
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))
set_value_range (&vr1, VR_RANGE, op1, op1, NULL);
else
set_value_range_to_varying (&vr1);
/* The resulting value range is the union of the operand ranges */
vrp_meet (&vr0, &vr1);
copy_value_range (vr, &vr0);
}
/* Extract range information from a comparison expression EXPR based /* Extract range information from a comparison expression EXPR based
on the range of its operand and the expression code. */ on the range of its operand and the expression code. */
...@@ -1961,6 +1996,8 @@ extract_range_from_expr (value_range_t *vr, tree expr) ...@@ -1961,6 +1996,8 @@ extract_range_from_expr (value_range_t *vr, tree expr)
extract_range_from_binary_expr (vr, expr); extract_range_from_binary_expr (vr, expr);
else if (TREE_CODE_CLASS (code) == tcc_unary) else if (TREE_CODE_CLASS (code) == tcc_unary)
extract_range_from_unary_expr (vr, expr); extract_range_from_unary_expr (vr, expr);
else if (code == COND_EXPR)
extract_range_from_cond_expr (vr, expr);
else if (TREE_CODE_CLASS (code) == tcc_comparison) else if (TREE_CODE_CLASS (code) == tcc_comparison)
extract_range_from_comparison (vr, expr); extract_range_from_comparison (vr, expr);
else if (is_gimple_min_invariant (expr)) else if (is_gimple_min_invariant (expr))
......
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