mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-24 19:39:47 +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>
|
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
|
* 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)))
|
|| (high != 0 && ! int_fits_type_p (high, type)))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (low != 0)
|
n_low = low, n_high = high;
|
||||||
low = convert (type, low);
|
|
||||||
|
|
||||||
if (high != 0)
|
if (n_low != 0)
|
||||||
high = convert (type, high);
|
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;
|
exp = arg0;
|
||||||
|
low = n_low, high = n_high;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -2956,15 +3004,20 @@ merge_ranges (pin_p, plow, phigh, in0_p, low0, high0, in1_p, low1, high1)
|
|||||||
tree tem;
|
tree tem;
|
||||||
int in_p;
|
int in_p;
|
||||||
tree low, high;
|
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,
|
if (integer_onep (range_binop (GT_EXPR, integer_type_node,
|
||||||
low0, 0, low1, 0))
|
low0, 0, low1, 0))
|
||||||
|| (((low0 == 0 && low1 == 0)
|
|| (lowequal
|
||||||
|| integer_onep (range_binop (EQ_EXPR, integer_type_node,
|
|
||||||
low0, 0, low1, 0)))
|
|
||||||
&& integer_onep (range_binop (GT_EXPR, integer_type_node,
|
&& 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;
|
temp = in0_p, in0_p = in1_p, in1_p = temp;
|
||||||
tem = low0, low0 = low1, low1 = tem;
|
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)
|
else if (in0_p && ! in1_p)
|
||||||
{
|
{
|
||||||
/* If they don't overlap, the result is the first range. If the
|
/* If they don't overlap, the result is the first range. If they are
|
||||||
second range is a subset of the first, we can't describe this as
|
equal, the result is false. If the second range is a subset of the
|
||||||
a single range unless both ranges end at the same place. If both
|
first, and the ranges begin at the same place, we go from just after
|
||||||
ranges start in the same place, then the result is false.
|
the end of the first range to the end of the second. If the second
|
||||||
Otherwise, we go from the start of the first range to just before
|
range is not a subset of the first, or if it is a subset and both
|
||||||
the start of the second. */
|
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)
|
if (no_overlap)
|
||||||
in_p = 1, low = low0, high = high0;
|
in_p = 1, low = low0, high = high0;
|
||||||
else if (subset
|
else if (lowequal && highequal)
|
||||||
&& 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)))
|
|
||||||
in_p = 0, low = high = 0;
|
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;
|
in_p = 1, low = low0;
|
||||||
high = range_binop (MINUS_EXPR, NULL_TREE, low1, 0,
|
high = range_binop (MINUS_EXPR, NULL_TREE, low1, 0,
|
||||||
integer_one_node, 0);
|
integer_one_node, 0);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (! in0_p && in1_p)
|
else if (! in0_p && in1_p)
|
||||||
|
Loading…
Reference in New Issue
Block a user