diff mbox

[wide-int] Handle more shift cases inline

Message ID 87bo13tqex.fsf@talisman.default
State New
Headers show

Commit Message

Richard Sandiford Nov. 29, 2013, 11:09 a.m. UTC
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
diff mbox

Patch

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);