[commit: ghc] master: Workaround GCC `__ctzdi2` intrinsic linker errors (6375934)

git at git.haskell.org git at git.haskell.org
Sun Aug 17 11:10:45 UTC 2014


Repository : ssh://git@git.haskell.org/ghc

On branch  : master
Link       : http://ghc.haskell.org/trac/ghc/changeset/6375934bfe64ca15eb215327629f9f07a185377a/ghc

>---------------------------------------------------------------

commit 6375934bfe64ca15eb215327629f9f07a185377a
Author: Herbert Valerio Riedel <hvr at gnu.org>
Date:   Sun Aug 17 12:19:45 2014 +0200

    Workaround GCC `__ctzdi2` intrinsic linker errors
    
    On Linux/i386 the 64bit `__builtin_ctzll()` instrinsic doesn't get
    inlined by GCC but rather a short `__ctzdi2` runtime function is
    inserted when needed into compiled object files.
    
    This causes failures for the four test-cases
    
      TEST="T8639_api T8628 dynCompileExpr T5313"
    
    with error messages of the kind
    
      dynCompileExpr: .../libraries/ghc-prim/dist-install/build/libHSghcpr_BE58KUgBe9ELCsPXiJ1Q2r.a: unknown symbol `__ctzdi2'
      dynCompileExpr: dynCompileExpr: unable to load package `ghc-prim'
    
    This workaround forces GCC on 32bit x86 to to express `hs_ctz64` in
    terms of the 32bit `__builtin_ctz()` (this is no loss, as there's no
    64bit BSF instruction on i686 anyway) and thus avoid the problematic
    out-of-line runtime function.
    
    Note: `__builtin_ctzll()` is used since
          e0c1767d0ea8d12e0a4badf43682a08784e379c6 (re #9340)


>---------------------------------------------------------------

6375934bfe64ca15eb215327629f9f07a185377a
 libraries/ghc-prim/cbits/ctz.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/libraries/ghc-prim/cbits/ctz.c b/libraries/ghc-prim/cbits/ctz.c
index cc420b9..f68f628 100644
--- a/libraries/ghc-prim/cbits/ctz.c
+++ b/libraries/ghc-prim/cbits/ctz.c
@@ -31,7 +31,23 @@ hs_ctz32(StgWord x)
 StgWord
 hs_ctz64(StgWord64 x)
 {
-#if SIZEOF_UNSIGNED_LONG == 8
+#if defined(__GNUC__) && defined(i386_HOST_ARCH)
+  /* On Linux/i386, the 64bit `__builtin_ctzll()` instrinsic doesn't
+     get inlined by GCC but rather a short `__ctzdi2` runtime function
+     is inserted when needed into compiled object files.
+
+     This workaround forces GCC on 32bit x86 to to express `hs_ctz64` in
+     terms of the 32bit `__builtin_ctz()` (this is no loss, as there's no
+     64bit BSF instruction on i686 anyway) and thus avoid the problematic
+     out-of-line runtime function.
+  */
+
+  if (!x) return 64;
+
+  return ((uint32_t)x ? __builtin_ctz((uint32_t)x)
+                      : (__builtin_ctz(x >> 32) + 32));
+
+#elif SIZEOF_UNSIGNED_LONG == 8
   return x ? __builtin_ctzl(x) : 64;
 #elif SIZEOF_UNSIGNED_LONG_LONG == 8
   return x ? __builtin_ctzll(x) : 64;



More information about the ghc-commits mailing list