summaryrefslogtreecommitdiff
path: root/rts/sm/BlockAlloc.c
diff options
context:
space:
mode:
authorU-THEFACEBOOK\smarlow <smarlow@SIMONMARLOW-PC.TheFacebook.com>2016-05-01 08:27:35 +0100
committerSimon Marlow <marlowsd@gmail.com>2016-05-02 21:22:30 +0100
commit5f8c0b84b2b281abe4f7b44514efd80bc2e2b994 (patch)
tree483bd7452096325688e4f8918ef96fb0f6608ee9 /rts/sm/BlockAlloc.c
parent36d29f7ce332a2b1fbc36de831b0eef7a6405555 (diff)
downloadhaskell-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.c38
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