Commit f8fe0545 by Eric Botcazou Committed by Eric Botcazou

fold-const.c (build_range_check): Make sure to use a valid type to apply the…

fold-const.c (build_range_check): Make sure to use a valid type to apply the "(c>=low) && (c<=high) into...

	* fold-const.c (build_range_check): Make sure to use a valid type to
	apply the "(c>=low) && (c<=high) into (c-low>=0) && (c-low<=high-low)"
	transformation.

	(range_predecessor): New static function.
	(range_successor): Likewise.
	(merge_ranges): Use them to compute predecessors and successors of
	range bounds.

From-SVN: r111866
parent d56ee62b
2006-03-09 Eric Botcazou <ebotcazou@adacore.com>
* fold-const.c (build_range_check): Make sure to use a valid type to
apply the "(c>=low) && (c<=high) into (c-low>=0) && (c-low<=high-low)"
transformation.
(range_predecessor): New static function.
(range_successor): Likewise.
(merge_ranges): Use them to compute predecessors and successors of
range bounds.
2006-03-09 Roger Sayle <roger@eyesopen.com> 2006-03-09 Roger Sayle <roger@eyesopen.com>
PR middle-end/26561 PR middle-end/26561
......
...@@ -108,6 +108,8 @@ static int all_ones_mask_p (tree, int); ...@@ -108,6 +108,8 @@ static int all_ones_mask_p (tree, int);
static tree sign_bit_p (tree, tree); static tree sign_bit_p (tree, tree);
static int simple_operand_p (tree); static int simple_operand_p (tree);
static tree range_binop (enum tree_code, tree, tree, int, tree, int); static tree range_binop (enum tree_code, tree, tree, int, tree, int);
static tree range_predecessor (tree);
static tree range_successor (tree);
static tree make_range (tree, int *, tree *, tree *); static tree make_range (tree, int *, tree *, tree *);
static tree build_range_check (tree, tree, int, tree, tree); static tree build_range_check (tree, tree, int, tree, tree);
static int merge_ranges (int *, tree *, tree *, int, tree, tree, int, tree, static int merge_ranges (int *, tree *, tree *, int, tree, tree, int, tree,
...@@ -3722,6 +3724,32 @@ range_binop (enum tree_code code, tree type, tree arg0, int upper0_p, ...@@ -3722,6 +3724,32 @@ range_binop (enum tree_code code, tree type, tree arg0, int upper0_p,
return constant_boolean_node (result, type); return constant_boolean_node (result, type);
} }
/* Return the predecessor of VAL in its type, handling the infinite case. */
static tree
range_predecessor (tree val)
{
tree type = TREE_TYPE (val);
if (INTEGRAL_TYPE_P (type) && val == TYPE_MIN_VALUE (type))
return 0;
else
return range_binop (MINUS_EXPR, NULL_TREE, val, 0, integer_one_node, 0);
}
/* Return the successor of VAL in its type, handling the infinite case. */
static tree
range_successor (tree val)
{
tree type = TREE_TYPE (val);
if (INTEGRAL_TYPE_P (type) && val == TYPE_MAX_VALUE (type))
return 0;
else
return range_binop (PLUS_EXPR, NULL_TREE, val, 0, integer_one_node, 0);
}
/* Given EXP, a logical expression, set the range it is testing into /* Given EXP, a logical expression, set the range it is testing into
variables denoted by PIN_P, PLOW, and PHIGH. Return the expression variables denoted by PIN_P, PLOW, and PHIGH. Return the expression
actually being tested. *PLOW and *PHIGH will be made of the same type actually being tested. *PLOW and *PHIGH will be made of the same type
...@@ -4089,60 +4117,59 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high) ...@@ -4089,60 +4117,59 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high)
} }
} }
value = const_binop (MINUS_EXPR, high, low, 0); /* Optimize (c>=low) && (c<=high) into (c-low>=0) && (c-low<=high-low).
if (value != 0 && (!flag_wrapv || TREE_OVERFLOW (value)) This requires wrap-around arithmetics for the type of the expression. */
&& ! TYPE_UNSIGNED (etype)) switch (TREE_CODE (etype))
{
case INTEGER_TYPE:
/* There is no requirement that LOW be within the range of ETYPE
if the latter is a subtype. It must, however, be within the base
type of ETYPE. So be sure we do the subtraction in that type. */
if (TREE_TYPE (etype))
etype = TREE_TYPE (etype);
break;
case ENUMERAL_TYPE:
case BOOLEAN_TYPE:
etype = lang_hooks.types.type_for_size (TYPE_PRECISION (etype),
TYPE_UNSIGNED (etype));
break;
default:
break;
}
/* If we don't have wrap-around arithmetics upfront, try to force it. */
if (TREE_CODE (etype) == INTEGER_TYPE
&& !TYPE_UNSIGNED (etype) && !flag_wrapv)
{ {
tree utype, minv, maxv; tree utype, minv, maxv;
/* Check if (unsigned) INT_MAX + 1 == (unsigned) INT_MIN /* Check if (unsigned) INT_MAX + 1 == (unsigned) INT_MIN
for the type in question, as we rely on this here. */ for the type in question, as we rely on this here. */
switch (TREE_CODE (etype)) utype = lang_hooks.types.unsigned_type (etype);
{ maxv = fold_convert (utype, TYPE_MAX_VALUE (etype));
case INTEGER_TYPE: maxv = range_binop (PLUS_EXPR, NULL_TREE, maxv, 1,
case ENUMERAL_TYPE: integer_one_node, 1);
/* There is no requirement that LOW be within the range of ETYPE minv = fold_convert (utype, TYPE_MIN_VALUE (etype));
if the latter is a subtype. It must, however, be within the base
type of ETYPE. So be sure we do the subtraction in that type. */ if (integer_zerop (range_binop (NE_EXPR, integer_type_node,
if (TREE_TYPE (etype)) minv, 1, maxv, 1)))
etype = TREE_TYPE (etype); etype = utype;
utype = lang_hooks.types.unsigned_type (etype); else
maxv = fold_convert (utype, TYPE_MAX_VALUE (etype)); return 0;
maxv = range_binop (PLUS_EXPR, NULL_TREE, maxv, 1,
integer_one_node, 1);
minv = fold_convert (utype, TYPE_MIN_VALUE (etype));
if (integer_zerop (range_binop (NE_EXPR, integer_type_node,
minv, 1, maxv, 1)))
{
etype = utype;
high = fold_convert (etype, high);
low = fold_convert (etype, low);
exp = fold_convert (etype, exp);
value = const_binop (MINUS_EXPR, high, low, 0);
}
break;
default:
break;
}
} }
if (value != 0 && ! TREE_OVERFLOW (value)) high = fold_convert (etype, high);
{ low = fold_convert (etype, low);
/* There is no requirement that LOW be within the range of ETYPE exp = fold_convert (etype, exp);
if the latter is a subtype. It must, however, be within the base
type of ETYPE. So be sure we do the subtraction in that type. */
if (INTEGRAL_TYPE_P (etype) && TREE_TYPE (etype))
{
etype = TREE_TYPE (etype);
exp = fold_convert (etype, exp);
low = fold_convert (etype, low);
value = fold_convert (etype, value);
}
return build_range_check (type, value = const_binop (MINUS_EXPR, high, low, 0);
fold_build2 (MINUS_EXPR, etype, exp, low),
1, build_int_cst (etype, 0), value); if (value != 0 && !TREE_OVERFLOW (value))
} return build_range_check (type,
fold_build2 (MINUS_EXPR, etype, exp, low),
1, build_int_cst (etype, 0), value);
return 0; return 0;
} }
...@@ -4208,7 +4235,7 @@ merge_ranges (int *pin_p, tree *plow, tree *phigh, int in0_p, tree low0, ...@@ -4208,7 +4235,7 @@ merge_ranges (int *pin_p, tree *plow, tree *phigh, int in0_p, tree low0,
/* If they don't overlap, the result is the first range. If they are /* If they don't overlap, the result is the first range. If they are
equal, the result is false. If the second range is a subset of the equal, the result is false. If the second range is a subset of the
first, and the ranges begin at the same place, we go from just after first, and the ranges begin at the same place, we go from just after
the end of the first range to the end of the second. If the second the end of the second range to the end of the first. If the second
range is not a subset of the first, or if it is a subset and both range is not a subset of the first, or if it is a subset and both
ranges end at the same place, the range starts at the start of the ranges end at the same place, the range starts at the start of the
first range and ends just before the second range. first range and ends just before the second range.
...@@ -4219,15 +4246,15 @@ merge_ranges (int *pin_p, tree *plow, tree *phigh, int in0_p, tree low0, ...@@ -4219,15 +4246,15 @@ merge_ranges (int *pin_p, tree *plow, tree *phigh, int in0_p, tree low0,
in_p = 0, low = high = 0; in_p = 0, low = high = 0;
else if (subset && lowequal) else if (subset && lowequal)
{ {
in_p = 1, high = high0; low = range_successor (high1);
low = range_binop (PLUS_EXPR, NULL_TREE, high1, 0, high = high0;
integer_one_node, 0); in_p = (low != 0);
} }
else if (! subset || highequal) else if (! subset || highequal)
{ {
in_p = 1, low = low0; low = low0;
high = range_binop (MINUS_EXPR, NULL_TREE, low1, 0, high = range_predecessor (low1);
integer_one_node, 0); in_p = (high != 0);
} }
else else
return 0; return 0;
...@@ -4245,9 +4272,9 @@ merge_ranges (int *pin_p, tree *plow, tree *phigh, int in0_p, tree low0, ...@@ -4245,9 +4272,9 @@ merge_ranges (int *pin_p, tree *plow, tree *phigh, int in0_p, tree low0,
in_p = 0, low = high = 0; in_p = 0, low = high = 0;
else else
{ {
in_p = 1, high = high1; low = range_successor (high0);
low = range_binop (PLUS_EXPR, NULL_TREE, high0, 1, high = high1;
integer_one_node, 0); in_p = (low != 0);
} }
} }
...@@ -4262,9 +4289,7 @@ merge_ranges (int *pin_p, tree *plow, tree *phigh, int in0_p, tree low0, ...@@ -4262,9 +4289,7 @@ merge_ranges (int *pin_p, tree *plow, tree *phigh, int in0_p, tree low0,
if (no_overlap) if (no_overlap)
{ {
if (integer_onep (range_binop (EQ_EXPR, integer_type_node, if (integer_onep (range_binop (EQ_EXPR, integer_type_node,
range_binop (PLUS_EXPR, NULL_TREE, range_successor (high0),
high0, 1,
integer_one_node, 1),
1, low1, 0))) 1, low1, 0)))
in_p = 0, low = low0, high = high1; in_p = 0, low = low0, high = high1;
else else
......
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