diff options
author | U-THEFACEBOOK\smarlow <smarlow@SIMONMARLOW-PC.TheFacebook.com> | 2016-05-01 08:27:35 +0100 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2016-05-02 21:22:30 +0100 |
commit | 5f8c0b84b2b281abe4f7b44514efd80bc2e2b994 (patch) | |
tree | 483bd7452096325688e4f8918ef96fb0f6608ee9 /rts/sm/BlockAlloc.c | |
parent | 36d29f7ce332a2b1fbc36de831b0eef7a6405555 (diff) | |
download | haskell-5f8c0b84b2b281abe4f7b44514efd80bc2e2b994.tar.gz |
Revert "Revert "Use __builtin_clz() to implement log_1()""
This reverts commit 546f24e4f8a7c086b1e5afcdda624176610cbcf8.
And adds a fix for Windows: we need to use __builtin_clzll() rather than
__builtin_clzl(), because StgWord is unsigned long long on Windows.
Diffstat (limited to 'rts/sm/BlockAlloc.c')
-rw-r--r-- | rts/sm/BlockAlloc.c | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/rts/sm/BlockAlloc.c b/rts/sm/BlockAlloc.c index a633726935..dc0d0ed478 100644 --- a/rts/sm/BlockAlloc.c +++ b/rts/sm/BlockAlloc.c @@ -199,31 +199,47 @@ initGroup(bdescr *head) } } -// There are quicker non-loopy ways to do log_2, but we expect n to be -// usually small, and MAX_FREE_LIST is also small, so the loop version -// might well be the best choice here. +#if SIZEOF_VOID_P == SIZEOF_LONG +#define CLZW(n) (__builtin_clzl(n)) +#else +#define CLZW(n) (__builtin_clzll(n)) +#endif + +// log base 2 (floor), needs to support up to 2^MAX_FREE_LIST STATIC_INLINE nat -log_2_ceil(W_ n) +log_2(W_ n) { +#if defined(__GNUC__) + return CLZW(n) ^ (sizeof(StgWord)*8 - 1); + // generates good code on x86. __builtin_clz() compiles to bsr+xor, but + // we want just bsr, so the xor here cancels out gcc's xor. +#else W_ i, x; - x = 1; + x = n; for (i=0; i < MAX_FREE_LIST; i++) { - if (x >= n) return i; - x = x << 1; + x = x >> 1; + if (x == 0) return i; } return MAX_FREE_LIST; +#endif } +// log base 2 (ceiling), needs to support up to 2^MAX_FREE_LIST STATIC_INLINE nat -log_2(W_ n) +log_2_ceil(W_ n) { +#if defined(__GNUC__) + nat r = log_2(n); + return (n & (n-1)) ? r+1 : r; +#else W_ i, x; - x = n; + x = 1; for (i=0; i < MAX_FREE_LIST; i++) { - x = x >> 1; - if (x == 0) return i; + if (x >= n) return i; + x = x << 1; } return MAX_FREE_LIST; +#endif } STATIC_INLINE void |