tree-vrp.c (extract_range_from_unary_expr_1): New function, split out from ...

2011-08-08  Richard Guenther  <rguenther@suse.de>

	* tree-vrp.c (extract_range_from_unary_expr_1): New function,
	split out from ...
	(extract_range_from_unary_expr): ... here.  Handle BIT_NOT_EXPR
	by composition.

From-SVN: r177558
This commit is contained in:
Richard Guenther 2011-08-08 11:40:08 +00:00 committed by Richard Biener
parent daae4650a9
commit ce6bfa50fa
2 changed files with 63 additions and 49 deletions

View File

@ -1,3 +1,10 @@
2011-08-08 Richard Guenther <rguenther@suse.de>
* tree-vrp.c (extract_range_from_unary_expr_1): New function,
split out from ...
(extract_range_from_unary_expr): ... here. Handle BIT_NOT_EXPR
by composition.
2011-08-08 Mikael Pettersson <mikpe@it.uu.se>
PR tree-optimization/50005

View File

@ -2805,48 +2805,18 @@ extract_range_from_binary_expr (value_range_t *vr,
extract_range_from_binary_expr_1 (vr, code, expr_type, &vr0, &vr1);
}
/* Extract range information from a unary expression EXPR based on
the range of its operand and the expression code. */
/* Extract range information from a unary operation CODE based on
the range of its operand *VR0 with type OP0_TYPE with resulting type TYPE.
The The resulting range is stored in *VR. */
static void
extract_range_from_unary_expr (value_range_t *vr, enum tree_code code,
tree type, tree op0)
extract_range_from_unary_expr_1 (value_range_t *vr,
enum tree_code code, tree type,
value_range_t *vr0_, tree op0_type)
{
value_range_t vr0 = *vr0_;
tree min, max;
int cmp;
value_range_t vr0 = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
/* Refuse to operate on certain unary expressions for which we
cannot easily determine a resulting range. */
if (code == FIX_TRUNC_EXPR
|| code == FLOAT_EXPR
|| code == BIT_NOT_EXPR
|| code == CONJ_EXPR)
{
/* We can still do constant propagation here. */
if ((op0 = op_with_constant_singleton_value_range (op0)) != NULL_TREE)
{
tree tem = fold_unary (code, type, op0);
if (tem
&& is_gimple_min_invariant (tem)
&& !is_overflow_infinity (tem))
{
set_value_range (vr, VR_RANGE, tem, tem, NULL);
return;
}
}
set_value_range_to_varying (vr);
return;
}
/* Get value ranges for the operand. For constant operands, create
a new value range with the operand to simplify processing. */
if (TREE_CODE (op0) == SSA_NAME)
vr0 = *(get_value_range (op0));
else if (is_gimple_min_invariant (op0))
set_value_range_to_value (&vr0, op0, NULL);
else
set_value_range_to_varying (&vr0);
/* If VR0 is UNDEFINED, so is the result. */
if (vr0.type == VR_UNDEFINED)
@ -2855,10 +2825,20 @@ extract_range_from_unary_expr (value_range_t *vr, enum tree_code code,
return;
}
/* Refuse to operate on certain unary expressions for which we
cannot easily determine a resulting range. */
if (code == FIX_TRUNC_EXPR
|| code == FLOAT_EXPR
|| code == CONJ_EXPR)
{
set_value_range_to_varying (vr);
return;
}
/* Refuse to operate on symbolic ranges, or if neither operand is
a pointer or integral type. */
if ((!INTEGRAL_TYPE_P (TREE_TYPE (op0))
&& !POINTER_TYPE_P (TREE_TYPE (op0)))
if ((!INTEGRAL_TYPE_P (op0_type)
&& !POINTER_TYPE_P (op0_type))
|| (vr0.type != VR_VARYING
&& symbolic_range_p (&vr0)))
{
@ -2868,29 +2848,23 @@ extract_range_from_unary_expr (value_range_t *vr, enum tree_code code,
/* If the expression involves pointers, we are only interested in
determining if it evaluates to NULL [0, 0] or non-NULL (~[0, 0]). */
if (POINTER_TYPE_P (type) || POINTER_TYPE_P (TREE_TYPE (op0)))
if (POINTER_TYPE_P (type) || POINTER_TYPE_P (op0_type))
{
bool sop;
sop = false;
if (range_is_nonnull (&vr0)
|| (tree_unary_nonzero_warnv_p (code, type, op0, &sop)
&& !sop))
if (range_is_nonnull (&vr0))
set_value_range_to_nonnull (vr, type);
else if (range_is_null (&vr0))
set_value_range_to_null (vr, type);
else
set_value_range_to_varying (vr);
return;
}
/* Handle unary expressions on integer ranges. */
if (CONVERT_EXPR_CODE_P (code)
&& INTEGRAL_TYPE_P (type)
&& INTEGRAL_TYPE_P (TREE_TYPE (op0)))
&& INTEGRAL_TYPE_P (op0_type))
{
tree inner_type = TREE_TYPE (op0);
tree inner_type = op0_type;
tree outer_type = type;
/* If VR0 is varying and we increase the type precision, assume
@ -3146,6 +3120,16 @@ extract_range_from_unary_expr (value_range_t *vr, enum tree_code code,
}
}
}
else if (code == BIT_NOT_EXPR)
{
/* ~X is simply -1 - X, so re-use existing code that also handles
anti-ranges fine. */
value_range_t minusone = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
set_value_range_to_value (&minusone, build_int_cst (type, -1), NULL);
extract_range_from_binary_expr_1 (vr, MINUS_EXPR,
type, &minusone, &vr0);
return;
}
else
{
/* Otherwise, operate on each end of the range. */
@ -3212,6 +3196,29 @@ extract_range_from_unary_expr (value_range_t *vr, enum tree_code code,
}
/* Extract range information from a unary expression CODE OP0 based on
the range of its operand with resulting type TYPE.
The resulting range is stored in *VR. */
static void
extract_range_from_unary_expr (value_range_t *vr, enum tree_code code,
tree type, tree op0)
{
value_range_t vr0 = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
/* Get value ranges for the operand. For constant operands, create
a new value range with the operand to simplify processing. */
if (TREE_CODE (op0) == SSA_NAME)
vr0 = *(get_value_range (op0));
else if (is_gimple_min_invariant (op0))
set_value_range_to_value (&vr0, op0, NULL);
else
set_value_range_to_varying (&vr0);
extract_range_from_unary_expr_1 (vr, code, type, &vr0, TREE_TYPE (op0));
}
/* Extract range information from a conditional expression EXPR based on
the ranges of each of its operands and the expression code. */