I am testing the following patch to remove the endless recursion
between rshift_double and lshift_double trying to make their
signed count argument positive by simple negation.  I opted to
make rshift_double private because it is the deprecated interface
and is no longer used.

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

Richard.

2012-03-28  Richard Guenther  <rguent...@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.

Index: gcc/double-int.c
===================================================================
*** gcc/double-int.c    (revision 185911)
--- gcc/double-int.c    (working copy)
*************** mul_double_with_sign (unsigned HOST_WIDE
*** 186,209 ****
    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.
     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)
  {
    unsigned HOST_WIDE_INT signmask;
  
!   if (count < 0)
!     {
!       rshift_double (l1, h1, -count, prec, lv, hv, arith);
!       return;
!     }
  
    if (SHIFT_COUNT_TRUNCATED)
      count %= prec;
--- 186,207 ----
    return (*hv < 0 ? ~(toplow & tophigh) : toplow | tophigh) != 0;
  }
  
! /* 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.  */
  
! 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;
  
!   signmask = (arith
!             ? -((unsigned HOST_WIDE_INT) h1 >> (HOST_BITS_PER_WIDE_INT - 1))
!             : 0);
  
    if (SHIFT_COUNT_TRUNCATED)
      count %= prec;
*************** lshift_double (unsigned HOST_WIDE_INT l1
*** 217,277 ****
      }
    else if (count >= HOST_BITS_PER_WIDE_INT)
      {
!       *hv = l1 << (count - HOST_BITS_PER_WIDE_INT);
!       *lv = 0;
      }
    else
      {
!       *hv = (((unsigned HOST_WIDE_INT) h1 << count)
!            | (l1 >> (HOST_BITS_PER_WIDE_INT - count - 1) >> 1));
!       *lv = l1 << count;
      }
  
!   /* 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);
  
!   if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
      ;
!   else if (prec >= 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);
!       *lv |= signmask << prec;
      }
  }
  
! /* Shift the doubleword integer in L1, H1 right by COUNT places
!    keeping only PREC bits of result.  Shift left 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,
               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)
      {
!       lshift_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;
  
--- 215,272 ----
      }
    else if (count >= HOST_BITS_PER_WIDE_INT)
      {
!       *hv = 0;
!       *lv = (unsigned HOST_WIDE_INT) h1 >> (count - HOST_BITS_PER_WIDE_INT);
      }
    else
      {
!       *hv = (unsigned HOST_WIDE_INT) h1 >> count;
!       *lv = ((l1 >> count)
!            | ((unsigned HOST_WIDE_INT) h1
!               << (HOST_BITS_PER_WIDE_INT - count - 1) << 1));
      }
  
!   /* Zero / 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)
      ;
!   else if ((prec - count) >= 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 - count));
!       *lv |= signmask << (prec - count);
      }
  }
  
! /* 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
! 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 signmask;
  
    if (count < 0)
      {
!       rshift_double (l1, h1, absu_hwi (count), prec, lv, hv, arith);
        return;
      }
  
    if (SHIFT_COUNT_TRUNCATED)
      count %= prec;
  
*************** rshift_double (unsigned HOST_WIDE_INT l1
*** 284,319 ****
      }
    else if (count >= HOST_BITS_PER_WIDE_INT)
      {
!       *hv = 0;
!       *lv = (unsigned HOST_WIDE_INT) h1 >> (count - HOST_BITS_PER_WIDE_INT);
      }
    else
      {
!       *hv = (unsigned HOST_WIDE_INT) h1 >> count;
!       *lv = ((l1 >> count)
!            | ((unsigned HOST_WIDE_INT) h1
!               << (HOST_BITS_PER_WIDE_INT - count - 1) << 1));
      }
  
!   /* Zero / 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)
      ;
!   else if ((prec - count) >= 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 - count));
!       *lv |= signmask << (prec - count);
      }
  }
  
--- 279,313 ----
      }
    else if (count >= HOST_BITS_PER_WIDE_INT)
      {
!       *hv = l1 << (count - HOST_BITS_PER_WIDE_INT);
!       *lv = 0;
      }
    else
      {
!       *hv = (((unsigned HOST_WIDE_INT) h1 << count)
!            | (l1 >> (HOST_BITS_PER_WIDE_INT - count - 1) >> 1));
!       *lv = l1 << count;
      }
  
!   /* 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);
! 
!   if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
      ;
!   else if (prec >= 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);
!       *lv |= signmask << prec;
      }
  }
  
*************** double_int
*** 895,901 ****
  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);
    return ret;
  }
  
--- 889,895 ----
  double_int_rshift (double_int a, HOST_WIDE_INT count, unsigned int prec, bool 
arith)
  {
    double_int ret;
!   lshift_double (a.low, a.high, -count, prec, &ret.low, &ret.high, arith);
    return ret;
  }
  
Index: gcc/double-int.h
===================================================================
*** gcc/double-int.h    (revision 185911)
--- gcc/double-int.h    (working copy)
*************** extern int mul_double_with_sign (unsigne
*** 300,308 ****
  extern void lshift_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
                           HOST_WIDE_INT, unsigned int,
                           unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, bool);
- extern void rshift_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
-                          HOST_WIDE_INT, unsigned int,
-                          unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, bool);
  extern int div_and_round_double (unsigned, int, unsigned HOST_WIDE_INT,
                                 HOST_WIDE_INT, unsigned HOST_WIDE_INT,
                                 HOST_WIDE_INT, unsigned HOST_WIDE_INT *,
--- 300,305 ----

Reply via email to