mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-23 14:11:05 +08:00
Better handling of COND_EXPRs in rhs
From-SVN: r120581
This commit is contained in:
parent
feb8476ac4
commit
f255541fb7
@ -1,3 +1,16 @@
|
||||
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>
|
||||
|
||||
* tree-ssa-forwprop.c (forward_propagate_into_cond,
|
||||
|
@ -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,
|
||||
unsigned HOST_WIDE_INT);
|
||||
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 void init_offset_limit (void);
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
/* 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.
|
||||
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
|
||||
@ -711,6 +746,9 @@ collect_object_sizes_for (struct object_size_info *osi, tree var)
|
||||
else if (TREE_CODE (rhs) == PLUS_EXPR)
|
||||
reexamine = plus_expr_object_size (osi, var, rhs);
|
||||
|
||||
else if (TREE_CODE (rhs) == COND_EXPR)
|
||||
reexamine = cond_expr_object_size (osi, var, rhs);
|
||||
|
||||
else
|
||||
expr_object_size (osi, var, rhs);
|
||||
break;
|
||||
|
@ -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) == 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)
|
||||
{
|
||||
val = arg;
|
||||
@ -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 (result == NULL_TREE)
|
||||
|
@ -490,15 +490,16 @@ find_equivalent_equality_comparison (tree cond)
|
||||
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
|
||||
which we may be able to optimize better. */
|
||||
|
||||
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))
|
||||
{
|
||||
@ -517,7 +518,7 @@ simplify_cond (tree stmt)
|
||||
|
||||
if (new_cond)
|
||||
{
|
||||
COND_EXPR_COND (stmt) = new_cond;
|
||||
COND_EXPR_COND (cond_expr) = new_cond;
|
||||
update_stmt (stmt);
|
||||
}
|
||||
}
|
||||
@ -529,7 +530,7 @@ simplify_cond (tree stmt)
|
||||
times as possible. */
|
||||
|
||||
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);
|
||||
|
||||
@ -554,7 +555,7 @@ forward_propagate_into_cond (tree cond_expr)
|
||||
}
|
||||
|
||||
COND_EXPR_COND (cond_expr) = new_cond;
|
||||
update_stmt (cond_expr);
|
||||
update_stmt (stmt);
|
||||
|
||||
if (has_zero_uses (test_var))
|
||||
{
|
||||
@ -570,7 +571,7 @@ forward_propagate_into_cond (tree cond_expr)
|
||||
against a constant where the SSA_NAME is the result of a
|
||||
conversion. Perhaps this should be folded into the rest
|
||||
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
|
||||
@ -1016,6 +1017,11 @@ tree_ssa_forward_propagate_single_use_vars (void)
|
||||
simplify_not_neg_expr (stmt);
|
||||
bsi_next (&bsi);
|
||||
}
|
||||
else if (TREE_CODE (rhs) == COND_EXPR)
|
||||
{
|
||||
forward_propagate_into_cond (rhs, stmt);
|
||||
bsi_next (&bsi);
|
||||
}
|
||||
else
|
||||
bsi_next (&bsi);
|
||||
}
|
||||
@ -1026,7 +1032,7 @@ tree_ssa_forward_propagate_single_use_vars (void)
|
||||
}
|
||||
else if (TREE_CODE (stmt) == COND_EXPR)
|
||||
{
|
||||
forward_propagate_into_cond (stmt);
|
||||
forward_propagate_into_cond (stmt, stmt);
|
||||
bsi_next (&bsi);
|
||||
}
|
||||
else
|
||||
|
@ -43,6 +43,7 @@ static sbitmap found_in_subgraph;
|
||||
|
||||
/* Local functions. */
|
||||
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
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
/* 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
|
||||
on the range of its operand and the expression code. */
|
||||
|
||||
@ -1961,6 +1996,8 @@ extract_range_from_expr (value_range_t *vr, tree expr)
|
||||
extract_range_from_binary_expr (vr, expr);
|
||||
else if (TREE_CODE_CLASS (code) == tcc_unary)
|
||||
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)
|
||||
extract_range_from_comparison (vr, expr);
|
||||
else if (is_gimple_min_invariant (expr))
|
||||
|
Loading…
x
Reference in New Issue
Block a user