diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-03-29 08:27:04 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-03-29 08:27:04 +0000 |
commit | e058414d8590f3bbba520bc9cf996896262e332f (patch) | |
tree | b43e29c3de16f535b3761a7a63b0cd8d9e988d63 /gcc/double-int.c | |
parent | 08709c1d8a245c9b8af084f3a7551b197e854461 (diff) | |
download | gcc-e058414d8590f3bbba520bc9cf996896262e332f.tar.gz |
2012-03-29 Richard Guenther <rguenther@suse.de>
PR middle-end/50708
* double-int.h (rshift_double): Remove.
* double-int.c (lshift_double): Use absu_hwi to make count
positive.
(rshift_double): Make static, take unsigned count argument,
remove handling of negative count argument.
(double_int_rshift): Dispatch to lshift_double.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@185951 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/double-int.c')
-rw-r--r-- | gcc/double-int.c | 112 |
1 files changed, 53 insertions, 59 deletions
diff --git a/gcc/double-int.c b/gcc/double-int.c index 834eaf9d6c2..0f954425093 100644 --- a/gcc/double-int.c +++ b/gcc/double-int.c @@ -186,24 +186,22 @@ mul_double_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, return (*hv < 0 ? ~(toplow & tophigh) : toplow | tophigh) != 0; } -/* Shift the doubleword integer in L1, H1 left by COUNT places - keeping only PREC bits of result. - Shift right if COUNT is negative. - ARITH nonzero specifies arithmetic shifting; otherwise use logical shift. +/* Shift the doubleword integer in L1, H1 right by COUNT places + keeping only PREC bits of result. ARITH nonzero specifies + arithmetic shifting; otherwise use logical shift. Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */ -void -lshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, - HOST_WIDE_INT count, unsigned int prec, - unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, bool arith) +static void +rshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, + unsigned HOST_WIDE_INT count, unsigned int prec, + unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, + bool arith) { unsigned HOST_WIDE_INT signmask; - if (count < 0) - { - rshift_double (l1, h1, -count, prec, lv, hv, arith); - return; - } + signmask = (arith + ? -((unsigned HOST_WIDE_INT) h1 >> (HOST_BITS_PER_WIDE_INT - 1)) + : 0); if (SHIFT_COUNT_TRUNCATED) count %= prec; @@ -217,61 +215,58 @@ lshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, } else if (count >= HOST_BITS_PER_WIDE_INT) { - *hv = l1 << (count - HOST_BITS_PER_WIDE_INT); - *lv = 0; + *hv = 0; + *lv = (unsigned HOST_WIDE_INT) h1 >> (count - HOST_BITS_PER_WIDE_INT); } else { - *hv = (((unsigned HOST_WIDE_INT) h1 << count) - | (l1 >> (HOST_BITS_PER_WIDE_INT - count - 1) >> 1)); - *lv = l1 << count; + *hv = (unsigned HOST_WIDE_INT) h1 >> count; + *lv = ((l1 >> count) + | ((unsigned HOST_WIDE_INT) h1 + << (HOST_BITS_PER_WIDE_INT - count - 1) << 1)); } - /* Sign extend all bits that are beyond the precision. */ - - signmask = -((prec > HOST_BITS_PER_WIDE_INT - ? ((unsigned HOST_WIDE_INT) *hv - >> (prec - HOST_BITS_PER_WIDE_INT - 1)) - : (*lv >> (prec - 1))) & 1); + /* Zero / sign extend all bits that are beyond the precision. */ - if (prec >= 2 * HOST_BITS_PER_WIDE_INT) + if (count >= (HOST_WIDE_INT)prec) + { + *hv = signmask; + *lv = signmask; + } + else if ((prec - count) >= 2 * HOST_BITS_PER_WIDE_INT) ; - else if (prec >= HOST_BITS_PER_WIDE_INT) + else if ((prec - count) >= HOST_BITS_PER_WIDE_INT) { - *hv &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT)); - *hv |= signmask << (prec - HOST_BITS_PER_WIDE_INT); + *hv &= ~((HOST_WIDE_INT) (-1) << (prec - count - HOST_BITS_PER_WIDE_INT)); + *hv |= signmask << (prec - count - HOST_BITS_PER_WIDE_INT); } else { *hv = signmask; - *lv &= ~((unsigned HOST_WIDE_INT) (-1) << prec); - *lv |= signmask << prec; + *lv &= ~((unsigned HOST_WIDE_INT) (-1) << (prec - count)); + *lv |= signmask << (prec - count); } } -/* Shift the doubleword integer in L1, H1 right by COUNT places - keeping only PREC bits of result. Shift left if COUNT is negative. +/* Shift the doubleword integer in L1, H1 left by COUNT places + keeping only PREC bits of result. + Shift right if COUNT is negative. ARITH nonzero specifies arithmetic shifting; otherwise use logical shift. Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */ void -rshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, +lshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, HOST_WIDE_INT count, unsigned int prec, - unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, - bool arith) + unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, bool arith) { unsigned HOST_WIDE_INT signmask; if (count < 0) { - lshift_double (l1, h1, -count, prec, lv, hv, arith); + rshift_double (l1, h1, absu_hwi (count), prec, lv, hv, arith); return; } - signmask = (arith - ? -((unsigned HOST_WIDE_INT) h1 >> (HOST_BITS_PER_WIDE_INT - 1)) - : 0); - if (SHIFT_COUNT_TRUNCATED) count %= prec; @@ -284,36 +279,35 @@ rshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, } else if (count >= HOST_BITS_PER_WIDE_INT) { - *hv = 0; - *lv = (unsigned HOST_WIDE_INT) h1 >> (count - HOST_BITS_PER_WIDE_INT); + *hv = l1 << (count - HOST_BITS_PER_WIDE_INT); + *lv = 0; } else { - *hv = (unsigned HOST_WIDE_INT) h1 >> count; - *lv = ((l1 >> count) - | ((unsigned HOST_WIDE_INT) h1 - << (HOST_BITS_PER_WIDE_INT - count - 1) << 1)); + *hv = (((unsigned HOST_WIDE_INT) h1 << count) + | (l1 >> (HOST_BITS_PER_WIDE_INT - count - 1) >> 1)); + *lv = l1 << count; } - /* Zero / sign extend all bits that are beyond the precision. */ + /* Sign extend all bits that are beyond the precision. */ - if (count >= (HOST_WIDE_INT)prec) - { - *hv = signmask; - *lv = signmask; - } - else if ((prec - count) >= 2 * HOST_BITS_PER_WIDE_INT) + signmask = -((prec > HOST_BITS_PER_WIDE_INT + ? ((unsigned HOST_WIDE_INT) *hv + >> (prec - HOST_BITS_PER_WIDE_INT - 1)) + : (*lv >> (prec - 1))) & 1); + + if (prec >= 2 * HOST_BITS_PER_WIDE_INT) ; - else if ((prec - count) >= HOST_BITS_PER_WIDE_INT) + else if (prec >= HOST_BITS_PER_WIDE_INT) { - *hv &= ~((HOST_WIDE_INT) (-1) << (prec - count - HOST_BITS_PER_WIDE_INT)); - *hv |= signmask << (prec - count - HOST_BITS_PER_WIDE_INT); + *hv &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT)); + *hv |= signmask << (prec - HOST_BITS_PER_WIDE_INT); } else { *hv = signmask; - *lv &= ~((unsigned HOST_WIDE_INT) (-1) << (prec - count)); - *lv |= signmask << (prec - count); + *lv &= ~((unsigned HOST_WIDE_INT) (-1) << prec); + *lv |= signmask << prec; } } @@ -895,7 +889,7 @@ double_int double_int_rshift (double_int a, HOST_WIDE_INT count, unsigned int prec, bool arith) { double_int ret; - rshift_double (a.low, a.high, count, prec, &ret.low, &ret.high, arith); + lshift_double (a.low, a.high, -count, prec, &ret.low, &ret.high, arith); return ret; } |