diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,12 @@
 `small-bytearray-builder` is now just a compatibility shim
 to ease the migration process.
 
+## 0.3.11.0 -- 2022-04-12
+
+* Support GHC 9.2
+* Inline pragmas for better LEB encoding perf
+* Bump upper bound on tasty in test suite
+
 ## 0.3.10.0 -- 2022-03-01
 
 * Add upper bound on base since this does not build with GHC 9.2.
diff --git a/bytebuild.cabal b/bytebuild.cabal
--- a/bytebuild.cabal
+++ b/bytebuild.cabal
@@ -1,7 +1,7 @@
 cabal-version: 2.2
 name: bytebuild
-version: 0.3.10.0
-synopsis: Serialize to a small byte arrays
+version: 0.3.11.0
+synopsis: Build byte arrays
 description:
   This is similar to the builder facilities provided by
   `Data.ByteString.Builder`. It is intended to be used in
@@ -43,10 +43,12 @@
     Data.Bytes.Builder.Bounded
     Data.Bytes.Builder.Bounded.Class
     Data.Bytes.Builder.Bounded.Unsafe
+  other-modules:
+    Compat
   reexported-modules:
     Data.Bytes.Chunks
   build-depends:
-    , base >=4.12.0.0 && <4.16
+    , base >=4.12.0.0 && <4.17
     , byteslice >=0.2.6 && <0.3
     , bytestring >=0.10.8.2 && <0.12
     , haskell-src-meta >=0.8
@@ -59,6 +61,11 @@
     , text-short >=0.1.3 && <0.2
     , wide-word >=0.1.0.9 && <0.2
     , zigzag
+  if impl(ghc >= 9.2)
+    hs-source-dirs: src-9.2
+  else
+    if impl(ghc >= 8.10)
+      hs-source-dirs: src-9.0
   if flag(checked)
     build-depends: primitive-checked >= 0.7 && <0.8
   else
@@ -89,7 +96,7 @@
     , quickcheck-classes >=0.6.4
     , quickcheck-instances >=0.3.22
     , text-short
-    , tasty >=1.2.3 && <1.3
+    , tasty >=1.2.3 && <1.5
     , tasty-hunit >=0.10.0.2 && <0.11
     , tasty-quickcheck >=0.10.1 && <0.11
     , text >=1.2 && <1.3
diff --git a/src-9.0/Compat.hs b/src-9.0/Compat.hs
new file mode 100644
--- /dev/null
+++ b/src-9.0/Compat.hs
@@ -0,0 +1,53 @@
+{-# language MagicHash #-}
+
+-- This is actually used with both GHC 8.10 and with GHC 9.0.
+-- The name of the directory is a little misleading.
+module Compat
+  ( int8ToInt#
+  , int16ToInt#
+  , int32ToInt#
+  , wordToWord8#
+  , wordToWord16#
+  , wordToWord32#
+  , word8ToWord#
+  , word16ToWord#
+  , word32ToWord#
+  ) where
+
+import GHC.Exts (Int#,Word#)
+
+int8ToInt# :: Int# -> Int#
+{-# inline int8ToInt# #-}
+int8ToInt# x = x
+
+int16ToInt# :: Int# -> Int#
+{-# inline int16ToInt# #-}
+int16ToInt# x = x
+
+int32ToInt# :: Int# -> Int#
+{-# inline int32ToInt# #-}
+int32ToInt# x = x
+
+wordToWord8# :: Word# -> Word#
+{-# inline wordToWord8# #-}
+wordToWord8#  x = x
+
+wordToWord16# :: Word# -> Word#
+{-# inline wordToWord16# #-}
+wordToWord16# x = x
+
+wordToWord32# :: Word# -> Word#
+{-# inline wordToWord32# #-}
+wordToWord32# x = x
+
+word8ToWord# :: Word# -> Word#
+{-# inline word8ToWord# #-}
+word8ToWord# x = x
+
+word16ToWord# :: Word# -> Word#
+{-# inline word16ToWord# #-}
+word16ToWord# x = x
+
+word32ToWord# :: Word# -> Word#
+{-# inline word32ToWord# #-}
+word32ToWord# x = x
diff --git a/src-9.2/Compat.hs b/src-9.2/Compat.hs
new file mode 100644
--- /dev/null
+++ b/src-9.2/Compat.hs
@@ -0,0 +1,15 @@
+{-# language MagicHash #-}
+
+module Compat 
+  ( int8ToInt#
+  , int16ToInt#
+  , int32ToInt#
+  , wordToWord8# 
+  , wordToWord16#
+  , wordToWord32#
+  , word8ToWord#
+  , word16ToWord#
+  , word32ToWord#
+  ) where
+
+import GHC.Exts
diff --git a/src/Data/Bytes/Builder.hs b/src/Data/Bytes/Builder.hs
--- a/src/Data/Bytes/Builder.hs
+++ b/src/Data/Bytes/Builder.hs
@@ -172,6 +172,8 @@
 import GHC.Word (Word(W#),Word8(W8#))
 import Numeric.Natural (Natural)
 
+import qualified Compat as C
+
 import qualified Arithmetic.Nat as Nat
 import qualified Arithmetic.Types as Arithmetic
 import qualified Data.Bytes as Bytes
@@ -1160,14 +1162,17 @@
 
 -- | Encode a machine-sized word with LEB-128.
 wordLEB128 :: Word -> Builder
+{-# inline wordLEB128 #-}
 wordLEB128 w = fromBounded Nat.constant (Bounded.wordLEB128 w)
 
 -- | Encode a 32-bit word with LEB-128.
 word32LEB128 :: Word32 -> Builder
+{-# inline word32LEB128 #-}
 word32LEB128 w = fromBounded Nat.constant (Bounded.word32LEB128 w)
 
 -- | Encode a 64-bit word with LEB-128.
 word64LEB128 :: Word64 -> Builder
+{-# inline word64LEB128 #-}
 word64LEB128 w = fromBounded Nat.constant (Bounded.word64LEB128 w)
 
 -- | Encode a signed arbitrary-precision integer as decimal.
@@ -1277,7 +1282,7 @@
 --               (# sX, bufX, 0#, lenX, Mutable buf0 off0 cs0 #)
 
 unsafeWordToWord8 :: Word -> Word8
-unsafeWordToWord8 (W# w) = W8# w
+unsafeWordToWord8 (W# w) = W8# (C.wordToWord8# w)
 
 -- | This function and the documentation for it are copied from
 -- Takano Akio's fast-builder library.
diff --git a/src/Data/Bytes/Builder/Bounded.hs b/src/Data/Bytes/Builder/Bounded.hs
--- a/src/Data/Bytes/Builder/Bounded.hs
+++ b/src/Data/Bytes/Builder/Bounded.hs
@@ -123,6 +123,8 @@
 import GHC.Word (Word8(W8#),Word16(W16#),Word32(W32#),Word64(W64#))
 import Data.Bytes.Types (Bytes(Bytes))
 
+import qualified Compat as C
+
 import qualified Arithmetic.Lte as Lte
 import qualified Arithmetic.Nat as Nat
 import qualified Arithmetic.Types as Arithmetic
@@ -230,12 +232,12 @@
 -- | Requires up to 10 bytes. Encodes an unsigned 32-bit integer as decimal.
 -- This encoding never starts with a zero unless the argument was zero.
 word32Dec :: Word32 -> Builder 10
-word32Dec (W32# w) = wordCommonDec# w
+word32Dec (W32# w) = wordCommonDec# (C.word32ToWord# w)
 
 -- | Requires up to 5 bytes. Encodes an unsigned 16-bit integer as decimal.
 -- This encoding never starts with a zero unless the argument was zero.
 word16Dec :: Word16 -> Builder 5
-word16Dec (W16# w) = wordCommonDec# w
+word16Dec (W16# w) = wordCommonDec# (C.word16ToWord# w)
 
 -- | Requires up to 3 bytes. Encodes an unsigned 8-bit integer as decimal.
 -- This encoding never starts with a zero unless the argument was zero.
@@ -247,7 +249,7 @@
   -- However, I (Andrew Martin) am concerned that although lookup
   -- table perform very well in microbenchmarks, they can thrash
   -- L1 cache in real applications.
-  word8Dec# w
+  word8Dec# (C.word8ToWord# w)
 
 -- | Requires up to 19 bytes. Encodes an unsigned machine-sized integer
 -- as decimal. This encoding never starts with a zero unless the argument
@@ -267,21 +269,21 @@
 -- Negative numbers are preceded by a minus sign. Positive numbers
 -- are not preceded by anything.
 int32Dec :: Int32 -> Builder 11
-int32Dec (I32# w) = intCommonDec# w
+int32Dec (I32# w) = intCommonDec# (C.int32ToInt# w)
 
 -- | Requires up to 6 bytes. Encodes a signed 16-bit integer as decimal.
 -- This encoding never starts with a zero unless the argument was zero.
 -- Negative numbers are preceded by a minus sign. Positive numbers
 -- are not preceded by anything.
 int16Dec :: Int16 -> Builder 6
-int16Dec (I16# w) = intCommonDec# w
+int16Dec (I16# w) = intCommonDec# (C.int16ToInt# w)
 
 -- | Requires up to 4 bytes. Encodes a signed 8-bit integer as decimal.
 -- This encoding never starts with a zero unless the argument was zero.
 -- Negative numbers are preceded by a minus sign. Positive numbers
 -- are not preceded by anything.
 int8Dec :: Int8 -> Builder 4
-int8Dec (I8# w) = intCommonDec# w
+int8Dec (I8# w) = intCommonDec# (C.int8ToInt# w)
 
 -- | Requires up to 20 bytes. Encodes a signed machine-sized integer
 -- as decimal. This encoding never starts with a zero unless the
@@ -441,13 +443,13 @@
 -- hexadecimal, zero-padding the encoding to 8 digits. This uses
 -- uppercase for the alphabetical digits.
 word32PaddedUpperHex :: Word32 -> Builder 8
-word32PaddedUpperHex (W32# w) = word32PaddedUpperHex# w
+word32PaddedUpperHex (W32# w) = word32PaddedUpperHex# (C.word32ToWord# w)
 
 -- | Requires exactly 8 bytes. Encodes a 32-bit unsigned integer as
 -- hexadecimal, zero-padding the encoding to 8 digits. This uses
 -- lowercase for the alphabetical digits.
 word32PaddedLowerHex :: Word32 -> Builder 8
-word32PaddedLowerHex (W32# w) = word32PaddedLowerHex# w
+word32PaddedLowerHex (W32# w) = word32PaddedLowerHex# (C.word32ToWord# w)
 
 -- | Requires exactly 4 bytes. Encodes a 16-bit unsigned integer as
 -- hexadecimal, zero-padding the encoding to 4 digits. This uses
@@ -456,7 +458,7 @@
 -- >>> word16PaddedUpperHex 0xab0
 -- 0AB0
 word16PaddedUpperHex :: Word16 -> Builder 4
-word16PaddedUpperHex (W16# w) = word16PaddedUpperHex# w
+word16PaddedUpperHex (W16# w) = word16PaddedUpperHex# (C.word16ToWord# w)
 
 -- | Requires exactly 4 bytes. Encodes a 16-bit unsigned integer as
 -- hexadecimal, zero-padding the encoding to 4 digits. This uses
@@ -465,7 +467,7 @@
 -- >>> word16PaddedLowerHex 0xab0
 -- 0ab0
 word16PaddedLowerHex :: Word16 -> Builder 4
-word16PaddedLowerHex (W16# w) = word16PaddedLowerHex# w
+word16PaddedLowerHex (W16# w) = word16PaddedLowerHex# (C.word16ToWord# w)
 
 -- | Requires at most 4 bytes. Encodes a 16-bit unsigned integer as
 -- hexadecimal. No leading zeroes are displayed. Letters are presented
@@ -474,7 +476,7 @@
 -- >>> word16LowerHex 0xab0
 -- ab0
 word16LowerHex :: Word16 -> Builder 4
-word16LowerHex (W16# w) = word16LowerHex# w
+word16LowerHex (W16# w) = word16LowerHex# (C.word16ToWord# w)
 
 -- | Requires at most 4 bytes. Encodes a 16-bit unsigned integer as
 -- hexadecimal. No leading zeroes are displayed. Letters are presented
@@ -483,25 +485,25 @@
 -- >>> word16UpperHex 0xab0
 -- AB0
 word16UpperHex :: Word16 -> Builder 4
-word16UpperHex (W16# w) = word16UpperHex# w
+word16UpperHex (W16# w) = word16UpperHex# (C.word16ToWord# w)
 
 -- | Requires at most 2 bytes. Encodes a 8-bit unsigned integer as
 -- hexadecimal. No leading zeroes are displayed. If the number is zero,
 -- a single zero digit is used.
 word8LowerHex :: Word8 -> Builder 2
-word8LowerHex (W8# w) = word8LowerHex# w
+word8LowerHex (W8# w) = word8LowerHex# (C.word8ToWord# w)
 
 -- | Requires exactly 2 bytes. Encodes a 8-bit unsigned integer as
 -- hexadecimal, zero-padding the encoding to 2 digits. This uses
 -- uppercase for the alphabetical digits.
 word8PaddedUpperHex :: Word8 -> Builder 2
-word8PaddedUpperHex (W8# w) = word8PaddedUpperHex# w
+word8PaddedUpperHex (W8# w) = word8PaddedUpperHex# (C.word8ToWord# w)
 
 -- | Requires exactly 2 bytes. Encodes a 8-bit unsigned integer as
 -- hexadecimal, zero-padding the encoding to 2 digits. This uses
 -- lowercase for the alphabetical digits.
 word8PaddedLowerHex :: Word8 -> Builder 2
-word8PaddedLowerHex (W8# w) = word8PaddedLowerHex# w
+word8PaddedLowerHex (W8# w) = word8PaddedLowerHex# (C.word8ToWord# w)
 
 -- TODO: Is it actually worth unrolling this loop. I suspect that it
 -- might not be. Benchmark this.
@@ -849,14 +851,17 @@
 
 -- | Encode a machine-sized word with LEB-128.
 wordLEB128 :: Word -> Builder 10
+{-# inline wordLEB128 #-}
 wordLEB128 (W# w) = lebCommon (W# w)
 
 -- | Encode a 32-bit word with LEB-128.
 word32LEB128 :: Word32 -> Builder 5
-word32LEB128 (W32# w) = lebCommon (W# w)
+{-# inline word32LEB128 #-}
+word32LEB128 (W32# w) = lebCommon (W# (C.word32ToWord# w))
 
 -- | Encode a 64-bit word with LEB-128.
 word64LEB128 :: Word64 -> Builder 10
+{-# inline word64LEB128 #-}
 word64LEB128 (W64# w) = lebCommon (W# w)
 
 lebCommon :: Word -> Builder n
@@ -933,19 +938,19 @@
 int64BE (I64# i) = word64BE (W64# (int2Word# i))
 
 int32BE :: Int32 -> Builder 4
-int32BE (I32# i) = word32BE (W32# (int2Word# i))
+int32BE (I32# i) = word32BE (W32# (C.wordToWord32# (int2Word# (C.int32ToInt# i))))
 
 int16BE :: Int16 -> Builder 2
-int16BE (I16# i) = word16BE (W16# (int2Word# i))
+int16BE (I16# i) = word16BE (W16# (C.wordToWord16# (int2Word# (C.int16ToInt# i))))
 
 int64LE :: Int64 -> Builder 8
 int64LE (I64# i) = word64LE (W64# (int2Word# i))
 
 int32LE :: Int32 -> Builder 4
-int32LE (I32# i) = word32LE (W32# (int2Word# i))
+int32LE (I32# i) = word32LE (W32# (C.wordToWord32# (int2Word# (C.int32ToInt# i))))
 
 int16LE :: Int16 -> Builder 2
-int16LE (I16# i) = word16LE (W16# (int2Word# i))
+int16LE (I16# i) = word16LE (W16# (C.wordToWord16# (int2Word# (C.int16ToInt# i))))
 
 word128LE :: Word128 -> Builder 16
 word128LE (Word128 hi lo) = append (word64LE lo) (word64LE hi)
@@ -1072,7 +1077,7 @@
 approxDiv10 !n = unsafeShiftR (0x1999999A * n) 32
 
 unsafeWordToWord8 :: Word -> Word8
-unsafeWordToWord8 (W# w) = W8# w
+unsafeWordToWord8 (W# w) = W8# (C.wordToWord8# w)
 
 foreign import ccall unsafe "bytebuild_paste_double" c_paste_double ::
   MutableByteArray# s -> Int# -> Double# -> IO Int
diff --git a/src/Data/Bytes/Builder/Unsafe.hs b/src/Data/Bytes/Builder/Unsafe.hs
--- a/src/Data/Bytes/Builder/Unsafe.hs
+++ b/src/Data/Bytes/Builder/Unsafe.hs
@@ -47,6 +47,8 @@
 import GHC.ST (ST(ST))
 import GHC.IO (stToIO)
 
+import qualified Compat as C
+
 import qualified Data.Bytes.Builder.Bounded as Bounded
 import qualified Data.Bytes.Builder.Bounded.Unsafe as UnsafeBounded
 import qualified Data.Primitive as PM
@@ -246,16 +248,16 @@
 
 goCString :: Addr# -> MutableByteArray# s -> Int# -> Int# -> Commits s
   -> State# s -> (# State# s, MutableByteArray# s, Int#, Int#, Commits s #)
-goCString addr buf0 off0 len0 cs0 s0 = case Exts.indexWord8OffAddr# addr 0# of
+goCString addr buf0 off0 len0 cs0 s0 = case C.word8ToWord# (Exts.indexWord8OffAddr# addr 0#) of
   0## -> (# s0, buf0, off0, len0, cs0 #)
   w -> case len0 of
     0# -> case Exts.newByteArray# 4080# s0 of
-      (# s1, buf1 #) -> case Exts.writeWord8Array# buf1 0# w s1 of
+      (# s1, buf1 #) -> case Exts.writeWord8Array# buf1 0# (C.wordToWord8# w) s1 of
         s2 -> goCString
           (Exts.plusAddr# addr 1# ) buf1 1# (4080# -# 1# )
           (Mutable buf0 off0 cs0)
           s2
-    _ -> case Exts.writeWord8Array# buf0 off0 w s0 of
+    _ -> case Exts.writeWord8Array# buf0 off0 (C.wordToWord8# w) s0 of
       s1 -> goCString (Exts.plusAddr# addr 1# ) buf0 (off0 +# 1# ) (len0 -# 1# ) cs0 s1
 
 fromEffect ::
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -255,6 +255,16 @@
         runConcat 1 (naturalDec y)
         ===
         pack (show y)
+    , testGroup "leb128-encoding"
+      [ THU.testCase "16" $
+          Chunks.concat (run 16 (word64LEB128 16))
+          @=?
+          Latin1.fromString "\x10"
+      , THU.testCase "deadbeef-smile" $ do
+        let inp = Latin1.fromString "\xDE\xAD\xBE\xEF"
+        (Chunks.concat . run 16) (sevenEightSmile inp)
+          @=?Latin1.fromString "\x6F\x2B\x37\x6E\x0F"
+      ]
     , testGroup "seven/eight encoding"
       [ THU.testCase "deadbeef" $ do
         let inp = Latin1.fromString "\xDE\xAD\xBE\xEF"
