diff --git a/Data/BloomFilter/Hash.hs b/Data/BloomFilter/Hash.hs
--- a/Data/BloomFilter/Hash.hs
+++ b/Data/BloomFilter/Hash.hs
@@ -49,6 +49,7 @@
 import Foreign.Storable (Storable, peek, sizeOf)
 import System.IO.Unsafe (unsafePerformIO)
 import qualified Data.ByteString as SB
+import qualified Data.ByteString.Lazy.Internal as LB
 import qualified Data.ByteString.Lazy as LB
 
 #include "HsBaseConfig.h"
@@ -56,16 +57,16 @@
 -- Make sure we're not performing any expensive arithmetic operations.
 -- import Prelude hiding ((/), (*), div, divMod, mod, rem)
 
-foreign import ccall unsafe "_jenkins_hashword" hashWord
+foreign import ccall unsafe "lookup3.h _jenkins_hashword" hashWord
     :: Ptr CInt -> CSize -> CInt -> IO CInt
 
-foreign import ccall unsafe "_jenkins_hashword2" hashWord2
+foreign import ccall unsafe "lookup3.h _jenkins_hashword2" hashWord2
     :: Ptr CInt -> CSize -> Ptr CInt -> Ptr CInt -> IO ()
 
-foreign import ccall unsafe "_jenkins_hashlittle" hashLittle
+foreign import ccall unsafe "lookup3.h _jenkins_hashlittle" hashLittle
     :: Ptr a -> CSize -> CInt -> IO CInt
 
-foreign import ccall unsafe "_jenkins_hashlittle2" hashLittle2
+foreign import ccall unsafe "lookup3.h _jenkins_hashlittle2" hashLittle2
     :: Ptr a -> CSize -> Ptr CInt -> Ptr CInt -> IO ()
 
 class Hashable a where
@@ -141,10 +142,12 @@
 {-# SPECIALIZE cheapHashes :: Int -> SB.ByteString -> [Word32] #-}
 {-# SPECIALIZE cheapHashes :: Int -> LB.ByteString -> [Word32] #-}
 {-# SPECIALIZE cheapHashes :: Int -> String -> [Word32] #-}
-cheapHashes k v = [h1 + (h2 `shiftR` i) | i <- [0..j]]
-    where h = hashSalt64 0x9150a946c4a8966e v
-          h1 = fromIntegral (h `shiftR` 32) .&. maxBound
-          h2 = fromIntegral h
+cheapHashes k v = go 0
+    where go i | i == j = []
+               | otherwise = h1 + (h2 `shiftR` i) : go (i + 1)
+          !h1 = fromIntegral (h `shiftR` 32) .&. maxBound
+          !h2 = fromIntegral h
+          h = hashSalt64 0x9150a946c4a8966e v
           j = fromIntegral k - 1
 
 instance Hashable () where
@@ -246,11 +249,18 @@
     hashIO64 bs salt = SB.useAsCStringLen bs $ \(ptr, len) -> do
                       alignedHash2 ptr (fromIntegral len) salt
 
+rechunk :: LB.ByteString -> [SB.ByteString]
+rechunk s | LB.null s = []
+          | otherwise = let (pre,suf) = LB.splitAt chunkSize s
+                        in  repack pre : rechunk suf
+           where repack = SB.concat . LB.toChunks
+                 chunkSize = fromIntegral LB.defaultChunkSize
+
 instance Hashable LB.ByteString where
-    hashIO32 bs salt = foldM (flip hashIO32) salt (LB.toChunks bs)
+    hashIO32 bs salt = foldM (flip hashIO32) salt (rechunk bs)
 
     {-# INLINE hashIO64 #-}
-    hashIO64 bs salt = foldM go salt (LB.toChunks bs)
+    hashIO64 bs salt = foldM go salt (rechunk bs)
         where go a s = hashIO64 s a
 
 instance Hashable a => Hashable (Maybe a) where
diff --git a/bloomfilter.cabal b/bloomfilter.cabal
--- a/bloomfilter.cabal
+++ b/bloomfilter.cabal
@@ -1,5 +1,5 @@
 name:            bloomfilter
-version:         1.2.1
+version:         1.2.2
 license:         BSD3
 license-file:    LICENSE
 author:          Bryan O'Sullivan <bos@serpentine.com>
@@ -12,7 +12,7 @@
 build-type:      Simple
 cabal-version:   >= 1.2
 tested-with:     GHC ==6.8.2
-extra-source-files: README cbits/lookup3.c
+extra-source-files: README cbits/lookup3.c cbits/lookup3.h
                  examples/Makefile examples/SpellChecker.hs examples/Words.hs
 
 flag bytestring-in-base
@@ -32,11 +32,15 @@
   else
     build-depends:   base < 3.0
 
-  exposed-modules: Data.BloomFilter
-                   Data.BloomFilter.Easy
-                   Data.BloomFilter.Hash
-  other-modules:   Data.BloomFilter.Array
-                   Data.BloomFilter.Util
-  c-sources:       cbits/lookup3.c
-  ghc-options:     -O2 -Wall -fliberate-case-threshold=1000
-  cc-options:      -O3
+  exposed-modules:  Data.BloomFilter
+                    Data.BloomFilter.Easy
+                    Data.BloomFilter.Hash
+  other-modules:    Data.BloomFilter.Array
+                    Data.BloomFilter.Util
+  c-sources:        cbits/lookup3.c
+  ghc-options:      -O2 -Wall -fvia-C -optc-O3
+  ghc-prof-options: -auto-all
+  cc-options:       -O3
+  include-dirs:     cbits
+  includes:         lookup3.h
+  install-includes: lookup3.h
diff --git a/cbits/lookup3.c b/cbits/lookup3.c
--- a/cbits/lookup3.c
+++ b/cbits/lookup3.c
@@ -49,6 +49,8 @@
 # include <endian.h>    /* attempt to define endianness */
 #endif
 
+#include "lookup3.h"
+
 /*
  * My best guess at if you are big-endian or little-endian.  This may
  * need adjustment.
diff --git a/cbits/lookup3.h b/cbits/lookup3.h
new file mode 100644
--- /dev/null
+++ b/cbits/lookup3.h
@@ -0,0 +1,17 @@
+#ifndef _lookup3_h
+#define _lookup3_h
+
+#include <stdint.h>
+#include <sys/types.h>
+
+uint32_t _jenkins_hashword(const uint32_t *k, size_t length, uint32_t initval);
+
+uint32_t _jenkins_hashlittle(const void *key, size_t length, uint32_t initval);
+
+void _jenkins_hashword2(const uint32_t *key, size_t length,
+			uint32_t *pc, uint32_t *pb);
+
+void _jenkins_hashlittle2(const void *key, size_t length,
+			  uint32_t *pc, uint32_t *pb);
+
+#endif /* _lookup3_h */
diff --git a/examples/Makefile b/examples/Makefile
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -1,5 +1,5 @@
 hc := ghc
-hcflags := --make -O2
+hcflags := --make -O2 -fvia-C -optc-O2
 
 examples := words spellchecker
 
diff --git a/examples/Words.hs b/examples/Words.hs
--- a/examples/Words.hs
+++ b/examples/Words.hs
@@ -18,7 +18,7 @@
           k = 3
       in fromListB (cheapHashes (numHashes - k)) (size * k) xs
 
-testFunction = aggressive
+testFunction = conservative
 
 main = do
   args <- getArgs
