diff options
author | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-10-03 21:33:57 +0000 |
---|---|---|
committer | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-10-03 21:33:57 +0000 |
commit | 67c65562f54b79711c2faccaebb6faa31fdbdd4f (patch) | |
tree | 09c0fbd9595e9411be41c39493368c74ad3a13be /gcc/simplify-rtx.c | |
parent | e0820f9b2ce32cdd93ad566100054d50bc3f542a (diff) | |
download | gcc-67c65562f54b79711c2faccaebb6faa31fdbdd4f.tar.gz |
PR optimization/9325, PR java/6391
* fold-const.c (fold_convert): For floating point to integer
conversions, return the maximum/minimum representable integer
value if the real constant overflows the destination type.
* tree.c (real_value_from_int_cst): Allow the type to be NULL,
meaning don't truncate the result to a floating point mode.
Simplify the logic by calling real_from_integer directly.
* simplify-rtx.c (simplify_unary_operation): Implement the
same semantics for folding floating point to integer conversions
in RTL.
* gcc.c-torture/execute/20031003-1.c: New test case.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@72079 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/simplify-rtx.c')
-rw-r--r-- | gcc/simplify-rtx.c | 94 |
1 files changed, 87 insertions, 7 deletions
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index c338b665ca0..3e0bdbfa27a 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -775,19 +775,99 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode, else if (GET_CODE (trueop) == CONST_DOUBLE && GET_MODE_CLASS (GET_MODE (trueop)) == MODE_FLOAT && GET_MODE_CLASS (mode) == MODE_INT - && width <= HOST_BITS_PER_WIDE_INT && width > 0) + && width <= 2*HOST_BITS_PER_WIDE_INT && width > 0) { - HOST_WIDE_INT i; - REAL_VALUE_TYPE d; - REAL_VALUE_FROM_CONST_DOUBLE (d, trueop); + /* Although the overflow semantics of RTL's FIX and UNSIGNED_FIX + operators are intentionally left unspecified (to ease implemention + by target backends), for consistency, this routine implements the + same semantics for constant folding as used by the middle-end. */ + + HOST_WIDE_INT xh, xl, th, tl; + REAL_VALUE_TYPE x, t; + REAL_VALUE_FROM_CONST_DOUBLE (x, trueop); switch (code) { - case FIX: i = REAL_VALUE_FIX (d); break; - case UNSIGNED_FIX: i = REAL_VALUE_UNSIGNED_FIX (d); break; + case FIX: + if (REAL_VALUE_ISNAN (x)) + return const0_rtx; + + /* Test against the signed upper bound. */ + if (width > HOST_BITS_PER_WIDE_INT) + { + th = ((unsigned HOST_WIDE_INT) 1 + << (width - HOST_BITS_PER_WIDE_INT - 1)) - 1; + tl = -1; + } + else + { + th = 0; + tl = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1; + } + real_from_integer (&t, VOIDmode, tl, th, 0); + if (REAL_VALUES_LESS (t, x)) + { + xh = th; + xl = tl; + break; + } + + /* Test against the signed lower bound. */ + if (width > HOST_BITS_PER_WIDE_INT) + { + th = (HOST_WIDE_INT) -1 << (width - HOST_BITS_PER_WIDE_INT - 1); + tl = 0; + } + else + { + th = -1; + tl = (HOST_WIDE_INT) -1 << (width - 1); + } + real_from_integer (&t, VOIDmode, tl, th, 0); + if (REAL_VALUES_LESS (x, t)) + { + xh = th; + xl = tl; + break; + } + REAL_VALUE_TO_INT (&xl, &xh, x); + break; + + case UNSIGNED_FIX: + if (REAL_VALUE_ISNAN (x) || REAL_VALUE_NEGATIVE (x)) + return const0_rtx; + + /* Test against the unsigned upper bound. */ + if (width == 2*HOST_BITS_PER_WIDE_INT) + { + th = -1; + tl = -1; + } + else if (width >= HOST_BITS_PER_WIDE_INT) + { + th = ((unsigned HOST_WIDE_INT) 1 + << (width - HOST_BITS_PER_WIDE_INT)) - 1; + tl = -1; + } + else + { + th = 0; + tl = ((unsigned HOST_WIDE_INT) 1 << width) - 1; + } + real_from_integer (&t, VOIDmode, tl, th, 1); + if (REAL_VALUES_LESS (t, x)) + { + xh = th; + xl = tl; + break; + } + + REAL_VALUE_TO_INT (&xl, &xh, x); + break; + default: abort (); } - return gen_int_mode (i, mode); + return immed_double_const (xl, xh, mode); } /* This was formerly used only for non-IEEE float. |