mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-20 06:29:04 +08:00
fold-const.c (make_range): Correctly handle cases of converting from unsigned to signed type.
* fold-const.c (make_range): Correctly handle cases of converting from unsigned to signed type. * fold-const.c (merge_ranges): Make sure that if one range is subset of another, it will always be the second range. Correct (+,-) case to account for this. Brought over from gcc2; fixes sparc bug. From-SVN: r15678
This commit is contained in:
parent
4bc8c3c116
commit
ce2157a1a9
@ -1,3 +1,14 @@
|
||||
Tue Sep 23 12:34:51 1997 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
|
||||
|
||||
* fold-const.c (make_range): Correctly handle cases of converting
|
||||
from unsigned to signed type.
|
||||
|
||||
Tue Sep 23 12:34:51 1997 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
|
||||
|
||||
* fold-const.c (merge_ranges): Make sure that if one range is subset
|
||||
of another, it will always be the second range. Correct (+,-) case to
|
||||
account for this.
|
||||
|
||||
Tue Sep 23 01:15:50 1997 David S. Miller <davem@tanya.rutgers.edu>
|
||||
|
||||
* expmed.c (expand_divmod): If compute_mode is not the same as
|
||||
|
102
gcc/fold-const.c
102
gcc/fold-const.c
@ -2863,14 +2863,62 @@ make_range (exp, pin_p, plow, phigh)
|
||||
|| (high != 0 && ! int_fits_type_p (high, type)))
|
||||
break;
|
||||
|
||||
if (low != 0)
|
||||
low = convert (type, low);
|
||||
n_low = low, n_high = high;
|
||||
|
||||
if (high != 0)
|
||||
high = convert (type, high);
|
||||
if (n_low != 0)
|
||||
n_low = convert (type, n_low);
|
||||
|
||||
if (n_high != 0)
|
||||
n_high = convert (type, n_high);
|
||||
|
||||
/* If we're converting from an unsigned to a signed type,
|
||||
we will be doing the comparison as unsigned. The tests above
|
||||
have already verified that LOW and HIGH are both positive.
|
||||
|
||||
So we have to make sure that the original unsigned value will
|
||||
be interpreted as positive. */
|
||||
if (TREE_UNSIGNED (type) && ! TREE_UNSIGNED (TREE_TYPE (exp)))
|
||||
{
|
||||
tree equiv_type = type_for_mode (TYPE_MODE (type), 1);
|
||||
tree high_positive
|
||||
= fold (build (RSHIFT_EXPR, type,
|
||||
convert (type,
|
||||
TYPE_MAX_VALUE (equiv_type)),
|
||||
convert (type, integer_one_node)));
|
||||
|
||||
/* If the low bound is specified, "and" the range with the
|
||||
range for which the original unsigned value will be
|
||||
positive. */
|
||||
if (low != 0)
|
||||
{
|
||||
if (! merge_ranges (&n_in_p, &n_low, &n_high,
|
||||
1, n_low, n_high,
|
||||
1, convert (type, integer_zero_node),
|
||||
high_positive))
|
||||
break;
|
||||
|
||||
in_p = (n_in_p == in_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, "or" the range with the range of the input
|
||||
that will be interpreted as negative. */
|
||||
if (! merge_ranges (&n_in_p, &n_low, &n_high,
|
||||
0, n_low, n_high,
|
||||
1, convert (type, integer_zero_node),
|
||||
high_positive))
|
||||
break;
|
||||
|
||||
in_p = (in_p != n_in_p);
|
||||
}
|
||||
}
|
||||
|
||||
exp = arg0;
|
||||
low = n_low, high = n_high;
|
||||
continue;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
@ -2956,15 +3004,20 @@ merge_ranges (pin_p, plow, phigh, in0_p, low0, high0, in1_p, low1, high1)
|
||||
tree tem;
|
||||
int in_p;
|
||||
tree low, high;
|
||||
int lowequal = ((low0 == 0 && low1 == 0)
|
||||
|| integer_onep (range_binop (EQ_EXPR, integer_type_node,
|
||||
low0, 0, low1, 0)));
|
||||
int highequal = ((high0 == 0 && high1 == 0)
|
||||
|| integer_onep (range_binop (EQ_EXPR, integer_type_node,
|
||||
high0, 1, high1, 1)));
|
||||
|
||||
/* Make range 0 be the range that starts first. Swap them if it isn't. */
|
||||
/* Make range 0 be the range that starts first, or ends last if they
|
||||
start at the same value. Swap them if it isn't. */
|
||||
if (integer_onep (range_binop (GT_EXPR, integer_type_node,
|
||||
low0, 0, low1, 0))
|
||||
|| (((low0 == 0 && low1 == 0)
|
||||
|| integer_onep (range_binop (EQ_EXPR, integer_type_node,
|
||||
low0, 0, low1, 0)))
|
||||
|| (lowequal
|
||||
&& integer_onep (range_binop (GT_EXPR, integer_type_node,
|
||||
high0, 1, high1, 1))))
|
||||
high1, 1, high0, 1))))
|
||||
{
|
||||
temp = in0_p, in0_p = in1_p, in1_p = temp;
|
||||
tem = low0, low0 = low1, low1 = tem;
|
||||
@ -2996,27 +3049,32 @@ merge_ranges (pin_p, plow, phigh, in0_p, low0, high0, in1_p, low1, high1)
|
||||
|
||||
else if (in0_p && ! in1_p)
|
||||
{
|
||||
/* If they don't overlap, the result is the first range. If the
|
||||
second range is a subset of the first, we can't describe this as
|
||||
a single range unless both ranges end at the same place. If both
|
||||
ranges start in the same place, then the result is false.
|
||||
Otherwise, we go from the start of the first range to just before
|
||||
the start of the second. */
|
||||
/* 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
|
||||
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
|
||||
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
|
||||
first range and ends just before the second range.
|
||||
Otherwise, we can't describe this as a single range. */
|
||||
if (no_overlap)
|
||||
in_p = 1, low = low0, high = high0;
|
||||
else if (subset
|
||||
&& integer_zerop (range_binop (EQ_EXPR, integer_type_node,
|
||||
high0, 1, high1, 0)))
|
||||
return 0;
|
||||
else if (integer_onep (range_binop (EQ_EXPR, integer_type_node,
|
||||
low0, 0, low1, 0)))
|
||||
else if (lowequal && highequal)
|
||||
in_p = 0, low = high = 0;
|
||||
else
|
||||
else if (subset && lowequal)
|
||||
{
|
||||
in_p = 1, high = high0;
|
||||
low = range_binop (PLUS_EXPR, NULL_TREE, high1, 0,
|
||||
integer_one_node, 0);
|
||||
}
|
||||
else if (! subset || highequal)
|
||||
{
|
||||
in_p = 1, low = low0;
|
||||
high = range_binop (MINUS_EXPR, NULL_TREE, low1, 0,
|
||||
integer_one_node, 0);
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
else if (! in0_p && in1_p)
|
||||
|
Loading…
Reference in New Issue
Block a user