This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

floor_log2_wide speedup


One of our customers noted that floor_log2_wide was implemented in a
naive way.  Here is a faster implementation.  The new function
benchmarks at about 5x faster this way, when tested independently in
ix86.  Tested under linux, but I didn't run any gcc-scoped benchmarks.

2004-05-24  DJ Delorie  <dj@redhat.com>

	* toplev.c (floor_log2_wide): Replace loop with faster bit
	operations.
	(exact_log2_wide): Define in terms of the above.
  
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.897
diff -p -C2 -r1.897 toplev.c
*** toplev.c	13 May 2004 06:39:45 -0000	1.897
--- toplev.c	24 May 2004 21:30:39 -0000
*************** read_integral_parameter (const char *p, 
*** 1244,1277 ****
  }
  
! /* Return the logarithm of X, base 2, considering X unsigned,
!    if X is a power of 2.  Otherwise, returns -1.
  
!    This should be used via the `exact_log2' macro.  */
  
  int
! exact_log2_wide (unsigned HOST_WIDE_INT x)
  {
!   int log = 0;
!   /* Test for 0 or a power of 2.  */
!   if (x == 0 || x != (x & -x))
      return -1;
!   while ((x >>= 1) != 0)
!     log++;
!   return log;
  }
  
! /* Given X, an unsigned number, return the largest int Y such that 2**Y <= X.
!    If X is 0, return -1.
  
!    This should be used via the floor_log2 macro.  */
  
  int
! floor_log2_wide (unsigned HOST_WIDE_INT x)
  {
!   int log = -1;
!   while (x != 0)
!     log++,
!     x >>= 1;
!   return log;
  }
  
--- 1244,1289 ----
  }
  
! /* Given X, an unsigned number, return the largest int Y such that 2**Y <= X.
!    If X is 0, return -1.
  
!    This should be used via the floor_log2 macro.  */
  
  int
! floor_log2_wide (unsigned HOST_WIDE_INT x)
  {
!   int t=0;
!   if (x == 0)
      return -1;
!   if (sizeof (HOST_WIDE_INT)*8 > 64)
!     if (x >= 1 << (t+64))
!       t += 64;
!   if (sizeof (HOST_WIDE_INT)*8 > 32)
!     if (x >= 1 << (t+32))
!       t += 32;
!   if (x >= 1 << (t+16))
!     t += 16;
!   if (x >= 1 << (t+8))
!     t += 8;
!   if (x >= 1 << (t+4))
!     t += 4;
!   if (x >= 1 << (t+2))
!     t += 2;
!   if (x >= 1 << (t+1))
!     t += 1;
!   return t;
  }
  
! /* Return the logarithm of X, base 2, considering X unsigned,
!    if X is a power of 2.  Otherwise, returns -1.
  
!    This should be used via the `exact_log2' macro.  */
  
  int
! exact_log2_wide (unsigned HOST_WIDE_INT x)
  {
!   /* Test for 0 or a power of 2.  */
!   if (x == 0 || x != (x & -x))
!     return -1;
!   return floor_log2_wide (x);
  }
  


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]