This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
floor_log2_wide speedup
- From: DJ Delorie <dj at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 24 May 2004 17:34:42 -0400
- Subject: 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);
}