This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[fixed-point] Fix left shfit when the shift amount == the width
- From: "Fu, Chao-Ying" <fu at mips dot com>
- To: <gcc-patches at gcc dot gnu dot org>
- Cc: "Thekkath, Radhika" <radhika at mips dot com>, "Stephens, Nigel" <nigel at mips dot com>
- Date: Fri, 2 Feb 2007 17:08:09 -0800
- Subject: [fixed-point] Fix left shfit when the shift amount == the width
Hi,
This patch fixes the case when the shift amount is
the same as the full width for the 128-bit unsigned fract type.
Thanks!
Regards,
Chao-ying
2007-02-02 Chao-ying Fu <fu@mips.com>
* fixed-value.c (do_fixed_divide): Check the left shift amount to
just copy data directly when it is the same as the width.
This hits a corner case for the 128-bit unsigned fract type.
(do_fixed_shift): Likewise.
(fixed_convert_from_int): Likewise.
Index: fixed-value.c
===================================================================
--- fixed-value.c (revision 121327)
+++ fixed-value.c (working copy)
@@ -539,14 +539,23 @@
pos_b = b->data;
/* Left shift pos_a to {r, s} by FBIT. */
- lshift_double (pos_a.low, pos_a.high,
- GET_MODE_FBIT (f->mode),
- 2 * HOST_BITS_PER_WIDE_INT,
- &s.low, &s.high, 0);
- lshift_double (pos_a.low, pos_a.high,
- - (2 * HOST_BITS_PER_WIDE_INT - GET_MODE_FBIT (f->mode)),
- 2 * HOST_BITS_PER_WIDE_INT,
- &r.low, &r.high, 0);
+ if (GET_MODE_FBIT (f->mode) == 2 * HOST_BITS_PER_WIDE_INT)
+ {
+ r = pos_a;
+ s.high = 0;
+ s.low = 0;
+ }
+ else
+ {
+ lshift_double (pos_a.low, pos_a.high,
+ GET_MODE_FBIT (f->mode),
+ 2 * HOST_BITS_PER_WIDE_INT,
+ &s.low, &s.high, 0);
+ lshift_double (pos_a.low, pos_a.high,
+ - (2 * HOST_BITS_PER_WIDE_INT - GET_MODE_FBIT (f->mode)
),
+ 2 * HOST_BITS_PER_WIDE_INT,
+ &r.low, &r.high, 0);
+ }
/* Divide r by pos_b to quo_r. The remanider is in mod. */
div_and_round_double (TRUNC_DIV_EXPR, 1, r.low, r.high, pos_b.low,
@@ -639,15 +648,24 @@
else /* We need two double_int to store the left-shift result. */
{
double_int temp_high, temp_low;
- lshift_double (a->data.low, a->data.high,
- b->data.low,
- 2 * HOST_BITS_PER_WIDE_INT,
- &temp_low.low, &temp_low.high, !unsignedp);
- /* Logical shift right to temp_high. */
- lshift_double (a->data.low, a->data.high,
- b->data.low - 2 * HOST_BITS_PER_WIDE_INT,
- 2 * HOST_BITS_PER_WIDE_INT,
- &temp_high.low, &temp_high.high, 0);
+ if (b->data.low == 2 * HOST_BITS_PER_WIDE_INT)
+ {
+ temp_high = a->data;
+ temp_low.high = 0;
+ temp_low.low = 0;
+ }
+ else
+ {
+ lshift_double (a->data.low, a->data.high,
+ b->data.low,
+ 2 * HOST_BITS_PER_WIDE_INT,
+ &temp_low.low, &temp_low.high, !unsignedp);
+ /* Logical shift right to temp_high. */
+ lshift_double (a->data.low, a->data.high,
+ b->data.low - 2 * HOST_BITS_PER_WIDE_INT,
+ 2 * HOST_BITS_PER_WIDE_INT,
+ &temp_high.low, &temp_high.high, 0);
+ }
if (!unsignedp && a->data.high < 0) /* Signed-extend temp_high. */
temp_high = double_int_ext (temp_high, b->data.low, unsignedp);
f->data = temp_low;
@@ -953,6 +971,14 @@
/* Left shift a to temp_high, temp_low. */
double_int temp_high, temp_low;
int amount = GET_MODE_FBIT (mode);
+ if (amount == 2 * HOST_BITS_PER_WIDE_INT)
+ {
+ temp_high = a;
+ temp_low.low = 0;
+ temp_low.high = 0;
+ }
+ else
+ {
+ lshift_double (a.low, a.high,
+ amount,
+ 2 * HOST_BITS_PER_WIDE_INT,
+ &temp_low.low, &temp_low.high, 0);
- /* Logical shift right to temp_high. */
- lshift_double (a.low, a.high,
- amount - 2 * HOST_BITS_PER_WIDE_INT,
- 2 * HOST_BITS_PER_WIDE_INT,
- &temp_high.low, &temp_high.high, 0);
+ /* Logical shift right to temp_high. */
+ lshift_double (a.low, a.high,
+ amount - 2 * HOST_BITS_PER_WIDE_INT,
+ 2 * HOST_BITS_PER_WIDE_INT,
+ &temp_high.low, &temp_high.high, 0);
+ }