diff options
author | kazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-07-08 18:49:05 +0000 |
---|---|---|
committer | kazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-07-08 18:49:05 +0000 |
commit | 59653f01a8b8a7156962be7216653d0ce0062d79 (patch) | |
tree | 2b169e2dac4a9fc33a703bd4fb0f2964c782273a | |
parent | 1737b88ca8f5c70581394b5f0391b70ce5fbf39d (diff) | |
download | gcc-59653f01a8b8a7156962be7216653d0ce0062d79.tar.gz |
PR tree-optimization/22360
* tree.c (upper_bound_in_type): Fix calculations for casting
to a non-wider signed type and casting a signed value to a
wider unsigned type.
(lower_bound_in_type): Fix calculations for casting to a
non-wider signed type.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@101785 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/tree.c | 121 |
2 files changed, 88 insertions, 42 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 88c127f9ed9..db2a8ea62d7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2005-07-08 Kazu Hirata <kazu@codesourcery.com> + + PR tree-optimization/22360 + * tree.c (upper_bound_in_type): Fix calculations for casting + to a non-wider signed type and casting a signed value to a + wider unsigned type. + (lower_bound_in_type): Fix calculations for casting to a + non-wider signed type. + 2005-07-08 Andrew Pinski <pinskia@physics.uc.edu> PR tree-opt/22356 diff --git a/gcc/tree.c b/gcc/tree.c index 60678814824..f4e052c4c6a 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -6417,43 +6417,64 @@ tree upper_bound_in_type (tree outer, tree inner) { unsigned HOST_WIDE_INT lo, hi; - unsigned bits = TYPE_PRECISION (inner); + unsigned int det = 0; + unsigned oprec = TYPE_PRECISION (outer); + unsigned iprec = TYPE_PRECISION (inner); + unsigned prec; + + /* Compute a unique number for every combination. */ + det |= (oprec > iprec) ? 4 : 0; + det |= TYPE_UNSIGNED (outer) ? 2 : 0; + det |= TYPE_UNSIGNED (inner) ? 1 : 0; + + /* Determine the exponent to use. */ + switch (det) + { + case 0: + case 1: + /* oprec <= iprec, outer: signed, inner: don't care. */ + prec = oprec - 1; + break; + case 2: + case 3: + /* oprec <= iprec, outer: unsigned, inner: don't care. */ + prec = oprec; + break; + case 4: + /* oprec > iprec, outer: signed, inner: signed. */ + prec = iprec - 1; + break; + case 5: + /* oprec > iprec, outer: signed, inner: unsigned. */ + prec = iprec; + break; + case 6: + /* oprec > iprec, outer: unsigned, inner: signed. */ + prec = oprec; + break; + case 7: + /* oprec > iprec, outer: unsigned, inner: unsigned. */ + prec = iprec; + break; + default: + gcc_unreachable (); + } - if (TYPE_UNSIGNED (outer) || TYPE_UNSIGNED (inner)) + /* Compute 2^^prec - 1. */ + if (prec <= HOST_BITS_PER_WIDE_INT) { - /* Zero extending in these cases. */ - if (bits <= HOST_BITS_PER_WIDE_INT) - { - hi = 0; - lo = (~(unsigned HOST_WIDE_INT) 0) - >> (HOST_BITS_PER_WIDE_INT - bits); - } - else - { - hi = (~(unsigned HOST_WIDE_INT) 0) - >> (2 * HOST_BITS_PER_WIDE_INT - bits); - lo = ~(unsigned HOST_WIDE_INT) 0; - } + hi = 0; + lo = ((~(unsigned HOST_WIDE_INT) 0) + >> (HOST_BITS_PER_WIDE_INT - prec)); } else { - /* Sign extending in these cases. */ - if (bits <= HOST_BITS_PER_WIDE_INT) - { - hi = 0; - lo = (~(unsigned HOST_WIDE_INT) 0) - >> (HOST_BITS_PER_WIDE_INT - bits) >> 1; - } - else - { - hi = (~(unsigned HOST_WIDE_INT) 0) - >> (2 * HOST_BITS_PER_WIDE_INT - bits) >> 1; - lo = ~(unsigned HOST_WIDE_INT) 0; - } + hi = ((~(unsigned HOST_WIDE_INT) 0) + >> (2 * HOST_BITS_PER_WIDE_INT - prec)); + lo = ~(unsigned HOST_WIDE_INT) 0; } - return fold_convert (outer, - build_int_cst_wide (inner, lo, hi)); + return build_int_cst_wide (outer, lo, hi); } /* Returns the smallest value obtainable by casting something in INNER type to @@ -6463,23 +6484,39 @@ tree lower_bound_in_type (tree outer, tree inner) { unsigned HOST_WIDE_INT lo, hi; - unsigned bits = TYPE_PRECISION (inner); - - if (TYPE_UNSIGNED (outer) || TYPE_UNSIGNED (inner)) + unsigned oprec = TYPE_PRECISION (outer); + unsigned iprec = TYPE_PRECISION (inner); + + /* If OUTER type is unsigned, we can definitely cast 0 to OUTER type + and obtain 0. */ + if (TYPE_UNSIGNED (outer) + /* If we are widening something of an unsigned type, OUTER type + contains all values of INNER type. In particular, both INNER + and OUTER types have zero in common. */ + || (oprec > iprec && TYPE_UNSIGNED (inner))) lo = hi = 0; - else if (bits <= HOST_BITS_PER_WIDE_INT) - { - hi = ~(unsigned HOST_WIDE_INT) 0; - lo = (~(unsigned HOST_WIDE_INT) 0) << (bits - 1); - } else { - hi = (~(unsigned HOST_WIDE_INT) 0) << (bits - HOST_BITS_PER_WIDE_INT - 1); - lo = 0; + /* If we are widening a signed type to another signed type, we + want to obtain -2^^(iprec-1). If we are keeping the + precision or narrowing to a signed type, we want to obtain + -2^(oprec-1). */ + unsigned prec = oprec > iprec ? iprec : oprec; + + if (prec <= HOST_BITS_PER_WIDE_INT) + { + hi = ~(unsigned HOST_WIDE_INT) 0; + lo = (~(unsigned HOST_WIDE_INT) 0) << (prec - 1); + } + else + { + hi = ((~(unsigned HOST_WIDE_INT) 0) + << (prec - HOST_BITS_PER_WIDE_INT - 1)); + lo = 0; + } } - return fold_convert (outer, - build_int_cst_wide (inner, lo, hi)); + return build_int_cst_wide (outer, lo, hi); } /* Return nonzero if two operands that are suitable for PHI nodes are |