summaryrefslogtreecommitdiff
path: root/rts/sm/BlockAlloc.c
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2016-04-28 15:20:43 +0100
committerSimon Peyton Jones <simonpj@microsoft.com>2016-04-28 17:36:19 +0100
commit546f24e4f8a7c086b1e5afcdda624176610cbcf8 (patch)
treee4e1443311b6e83d3b81e11f44976e620ed8a2f8 /rts/sm/BlockAlloc.c
parentc5b1014eb0a477aa32691841dcc2739dbcd2bc85 (diff)
downloadhaskell-546f24e4f8a7c086b1e5afcdda624176610cbcf8.tar.gz
Revert "Use __builtin_clz() to implement log_2()"
This reverts commit 24864ba5587c1a0447beabae90529e8bb4fa117a.
Diffstat (limited to 'rts/sm/BlockAlloc.c')
-rw-r--r--rts/sm/BlockAlloc.c32
1 files changed, 11 insertions, 21 deletions
diff --git a/rts/sm/BlockAlloc.c b/rts/sm/BlockAlloc.c
index 1c83de9ded..a633726935 100644
--- a/rts/sm/BlockAlloc.c
+++ b/rts/sm/BlockAlloc.c
@@ -199,41 +199,31 @@ initGroup(bdescr *head)
}
}
-// log base 2 (floor), needs to support up to 2^MAX_FREE_LIST
+// 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.
STATIC_INLINE nat
-log_2(W_ n)
+log_2_ceil(W_ n)
{
-#if defined(__GNUC__)
- return __builtin_clzl(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 = 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
}
-// log base 2 (ceiling), needs to support up to 2^MAX_FREE_LIST
STATIC_INLINE nat
-log_2_ceil(W_ n)
+log_2(W_ n)
{
-#if defined(__GNUC__)
- nat r = log_2(n);
- return (n & (n-1)) ? r+1 : r;
-#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
}
STATIC_INLINE void