This patch adds fast paths to lshift and lrshift for offset_int and
widest_int.  In the fold-const.ii testcase it reduces the number of
lshift_large calls from 369121 to 284 and the number lrshift_large
calls from 93646 to 6.

Tested on x86_64-linux-gnu.  OK to install?

Thanks,
Richard


Index: gcc/wide-int.h
===================================================================
--- gcc/wide-int.h      2013-11-29 10:53:49.183150051 +0000
+++ gcc/wide-int.h      2013-11-29 11:05:58.207044579 +0000
@@ -2789,7 +2789,20 @@ wi::lshift (const T1 &x, const T2 &y)
   else
     {
       unsigned int shift = yi.to_uhwi ();
-      if (precision <= HOST_BITS_PER_WIDE_INT)
+      /* For fixed-precision integers like offset_int and widest_int,
+        handle the case where the shift value is constant and the
+        result is a single nonnegative HWI (meaning that we don't
+        need to worry about val[1]).  This is particularly common
+        for converting a byte count to a bit count.
+
+        For variable-precision integers like wide_int, handle HWI
+        and sub-HWI integers inline.  */
+      if (STATIC_CONSTANT_P (xi.precision > HOST_BITS_PER_WIDE_INT)
+         ? (STATIC_CONSTANT_P (shift < HOST_BITS_PER_WIDE_INT - 1)
+            && xi.len == 1
+            && xi.val[0] <= (HOST_WIDE_INT) ((unsigned HOST_WIDE_INT)
+                                             HOST_WIDE_INT_MAX >> shift))
+         : precision <= HOST_BITS_PER_WIDE_INT)
        {
          val[0] = xi.ulow () << shift;
          result.set_len (1);
@@ -2821,7 +2834,17 @@ wi::lrshift (const T1 &x, const T2 &y)
   else
     {
       unsigned int shift = yi.to_uhwi ();
-      if (xi.precision <= HOST_BITS_PER_WIDE_INT)
+      /* For fixed-precision integers like offset_int and widest_int,
+        handle the case where the shift value is constant and the
+        shifted value is a single nonnegative HWI (meaning that all
+        bits above the HWI are zero).  This is particularly common
+        for converting a bit count to a byte count.
+
+        For variable-precision integers like wide_int, handle HWI
+        and sub-HWI integers inline.  */
+      if (STATIC_CONSTANT_P (xi.precision > HOST_BITS_PER_WIDE_INT)
+         ? xi.len == 1 && xi.val[0] >= 0
+         : xi.precision <= HOST_BITS_PER_WIDE_INT)
        {
          val[0] = xi.to_uhwi () >> shift;
          result.set_len (1);

Reply via email to