diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,16 @@
 # Changelog for `primal`
 
-## 0.1.0.0
+## 0.2.0
+
+* Addition of `offToCount`, `offForType`, `countToOff` and `countForType`
+* Renamed `offAsProxy` -> `offForProxyTypeOf` and `countAsProxy` -> `countForProxyTypeOf`
+* Rename `fromCount` -> `unCountBytes`, `fromCount#` -> `unCountBytes#`, `fromOff#` ->
+  `unOffBytes#`. Addition of `unOffBytes`
+* Fix a big in `readOffAddr#` and `writeOffAddr#` for tuples
+* Fix a big in `writeOffAddr#` for `Either`
+* Fix an overflow bug in functions that use `memcmp`: `memcmpAddr#`,
+  `memcmpAddrByteArray#`, `memcmpByteArray#` and `memcmpByteArrayAddr#`
+
+## 0.1.0
 
 * Initial release
diff --git a/cbits/primal.c b/cbits/primal.c
--- a/cbits/primal.c
+++ b/cbits/primal.c
@@ -6,7 +6,7 @@
   return ptr1 == ptr2;
 }
 
-HsInt8 primal_memcmp(HsWord8 *ptr1, HsInt offset1, HsWord8 *ptr2, HsInt offset2, HsInt n){
+HsInt primal_memcmp(HsWord8 *ptr1, HsInt offset1, HsWord8 *ptr2, HsInt offset2, HsInt n){
   return memcmp(ptr1 + offset1, ptr2 + offset2, n);
 }
 
diff --git a/primal.cabal b/primal.cabal
--- a/primal.cabal
+++ b/primal.cabal
@@ -1,5 +1,5 @@
 name:                primal
-version:             0.1.0.0
+version:             0.2.0.0
 synopsis:            Primeval world of Haskell.
 description:         Please see the README on GitHub at <https://github.com/lehins/primal#readme>
 homepage:            https://github.com/lehins/primal
@@ -63,6 +63,8 @@
         if impl(ghc < 8.2)
            include-dirs: cbits
            install-includes: primal_compat.h
+           if impl(ghc < 8.0)
+              build-depends: semigroups >= 0.18
   if !os(solaris)
       cc-options: -ftree-vectorize
   if arch(i386) || arch(x86_64)
diff --git a/src/Data/Prim.hs b/src/Data/Prim.hs
--- a/src/Data/Prim.hs
+++ b/src/Data/Prim.hs
@@ -28,20 +28,30 @@
   , alignment
   , alignmentType
   , alignmentProxy
+  -- * Size
   , Size(..)
+  -- * Count
   , Count(..)
-  , fromCount
+  , unCountBytes
   , toByteCount
-  , fromCount#
+  , unCountBytes#
   , fromByteCount
   , fromByteCountRem
-  , countAsProxy
+  , countToOff
+  , countToByteOff
+  , countForType
+  , countForProxyTypeOf
+  -- * Offset
   , Off(..)
+  , unOffBytes
   , toByteOff
-  , fromOff#
+  , unOffBytes#
   , fromByteOff
   , fromByteOffRem
-  , offAsProxy
+  , offToCount
+  , offToByteCount
+  , offForType
+  , offForProxyTypeOf
   -- * Prefetch
   , prefetchValue0
   , prefetchValue1
@@ -54,30 +64,38 @@
   , ForeignPtr
   , Typeable
   , Proxy(..)
+  , module Data.Semigroup
   , module Data.Monoid
   , module Data.Coerce
   ) where
 
 import Control.DeepSeq
 import Control.Prim.Monad
+import Data.Coerce
+import Data.Int
+import Data.Monoid hiding (First(..), Last(..), (<>))
 import Data.Prim.Atom
 import Data.Prim.Atomic
 import Data.Prim.Class
-import GHC.Base (quotInt,  quotRemInt)
-import GHC.Exts
+import Data.Semigroup
+import Data.Typeable
 import Data.Word
-import Data.Int
 import Foreign.ForeignPtr (ForeignPtr)
-import Data.Monoid
-import Data.Coerce
-import Data.Typeable
+import GHC.Base (quotInt, quotRemInt)
+import GHC.Exts
 
 newtype Size = Size { unSize :: Int }
   deriving (Show, Eq, Ord, Num, Real, Integral, Bounded, Enum)
 
 -- | Get the size of the data type in bytes. Argument is not evaluated.
-byteCount :: forall a . Prim a => a -> Count Word8
-byteCount _ = coerce (I# (sizeOf# (proxy# :: Proxy# a)))
+--
+-- >>> import Data.Prim
+-- >>> byteCount (Just 'a')
+-- Count {unCount = 5}
+--
+-- @since 0.1.0
+byteCount :: forall e . Prim e => e -> Count Word8
+byteCount _ = coerce (I# (sizeOf# (proxy# :: Proxy# e)))
 {-# INLINE byteCount #-}
 
 -- | Same as `sizeOf`, except that the type can be supplied as a type level argument
@@ -87,8 +105,9 @@
 -- >>> byteCountType @Int64
 -- Count {unCount = 8}
 --
-byteCountType :: forall a . Prim a => Count Word8
-byteCountType = coerce (I# (sizeOf# (proxy# :: Proxy# a)))
+-- @since 0.1.0
+byteCountType :: forall e . Prim e => Count Word8
+byteCountType = coerce (I# (sizeOf# (proxy# :: Proxy# e)))
 {-# INLINE byteCountType #-}
 
 -- | Same as `sizeOf`, but argument is a `Proxy` of @a@, instead of the type itself.
@@ -98,15 +117,18 @@
 -- >>> byteCountProxy (Proxy :: Proxy Int64)
 -- Count {unCount = 8}
 --
-byteCountProxy :: forall proxy a . Prim a => proxy a -> Count Word8
-byteCountProxy _ = coerce (I# (sizeOf# (proxy# :: Proxy# a)))
+-- @since 0.1.0
+byteCountProxy :: forall proxy e . Prim e => proxy e -> Count Word8
+byteCountProxy _ = coerce (I# (sizeOf# (proxy# :: Proxy# e)))
 {-# INLINE byteCountProxy #-}
 
 
 
 -- | Get the alignemnt of the type in bytes. Argument is not evaluated.
-alignment :: forall a . Prim a => a -> Int
-alignment _ = I# (alignment# (proxy# :: Proxy# a))
+--
+-- @since 0.1.0
+alignment :: forall e . Prim e => e -> Int
+alignment _ = I# (alignment# (proxy# :: Proxy# e))
 {-# INLINE alignment #-}
 
 -- | Same as `alignment`, except that the type can be supplied with @TypeApplications@
@@ -116,8 +138,9 @@
 -- >>> alignmentType @Int32
 -- 4
 --
-alignmentType :: forall a . Prim a => Int
-alignmentType = I# (alignment# (proxy# :: Proxy# a))
+-- @since 0.1.0
+alignmentType :: forall e . Prim e => Int
+alignmentType = I# (alignment# (proxy# :: Proxy# e))
 {-# INLINE alignmentType #-}
 
 -- | Same as `alignment`, but argument is a `Proxy` of @a@, instead of the type itself.
@@ -126,64 +149,87 @@
 -- >>> alignmentProxy (Proxy :: Proxy Int64)
 -- 8
 --
-alignmentProxy :: forall proxy a . Prim a => proxy a -> Int
-alignmentProxy _ = I# (alignment# (proxy# :: Proxy# a))
+-- @since 0.1.0
+alignmentProxy :: forall proxy e . Prim e => proxy e -> Int
+alignmentProxy _ = I# (alignment# (proxy# :: Proxy# e))
 {-# INLINE alignmentProxy #-}
 
 
 
 -- | Number of elements
-newtype Count a = Count
+newtype Count e = Count
   { unCount :: Int
   } deriving (Eq, Show, Ord, Enum, Bounded, Num, Integral, Real, NFData)
 
-instance Prim (Count a) where
-  type PrimBase (Count a) = Int
+instance Prim (Count e) where
+  type PrimBase (Count e) = Int
 
-fromCountWord8# :: Count Word8 -> Int#
-fromCountWord8# (Count (I# n#)) = n#
-{-# INLINE fromCountWord8# #-}
-fromCountInt8# :: Count Int8 -> Int#
-fromCountInt8# (Count (I# n#)) = n#
-{-# INLINE fromCountInt8# #-}
+unCountWord8# :: Count Word8 -> Int#
+unCountWord8# (Count (I# n#)) = n#
+{-# INLINE unCountWord8# #-}
+unCountInt8# :: Count Int8 -> Int#
+unCountInt8# (Count (I# n#)) = n#
+{-# INLINE unCountInt8# #-}
 
-fromCount# :: Prim a => Count a -> Int#
-fromCount# c@(Count (I# n#)) =
+unCountBytes# :: Prim e => Count e -> Int#
+unCountBytes# c@(Count (I# n#)) =
   case coerce (byteCountProxy c) of
     I# sz# -> sz# *# n#
-{-# INLINE[0] fromCount# #-}
+{-# INLINE[0] unCountBytes# #-}
 {-# RULES
-"fromCountWord8#" fromCount# = fromCountWord8#
-"fromCountInt8#" fromCount# = fromCountInt8#
+"unCountWord8#" unCountBytes# = unCountWord8#
+"unCountInt8#" unCountBytes# = unCountInt8#
   #-}
 
--- | Covert to number of bytes as an `Int`
+-- | Covert an element count to number of bytes it coresponds to as an `Int`. See
+-- `toByteCount` for preserving the `Count` wrapper.
 --
 -- @since 0.1.0
-fromCount :: Prim a => Count a -> Int
-fromCount c = I# (fromCount# c)
-{-# INLINE fromCount #-}
+unCountBytes :: Prim e => Count e -> Int
+unCountBytes c = I# (unCountBytes# c)
+{-# INLINE unCountBytes #-}
 
+
 -- | Covert to the `Count` of bytes
 --
 -- @since 0.1.0
-toByteCount :: Prim a => Count a -> Count Word8
-toByteCount = Count . fromCount
+toByteCount :: Prim e => Count e -> Count Word8
+toByteCount = Count . unCountBytes
 {-# INLINE toByteCount #-}
 
+-- | Cast a count to an offset of the same type
+--
+-- @since 0.2.0
+countToOff :: Count e -> Off e
+countToOff = coerce
 
+countToByteOff :: Prim e => Count e -> Off Word8
+countToByteOff = countToOff . toByteCount
+{-# INLINE countToByteOff #-}
+
 -- | Helper noop function that restricts `Count` to the type of proxy
 --
--- @since 0.1.0
-countAsProxy :: proxy a -> Count a -> Count a
-countAsProxy _ = id
+-- @since 0.2.0
+countForProxyTypeOf :: Count e -> proxy e -> Count e
+countForProxyTypeOf count _ = count
 
+-- | Restrict type argument of `Count` to the same type as the second argument, which
+-- itself is not evaluated
+--
+-- @since 0.2.0
+countForType :: Count e -> e -> Count e
+countForType count _ = count
+
 fromByteCountInt8 :: Count Word8 -> Count Int8
 fromByteCountInt8 = coerce
 {-# INLINE fromByteCountInt8 #-}
 
-fromByteCount :: forall a . Prim a => Count Word8 -> Count a
-fromByteCount sz = coerce (quotSizeOfWith (proxy# :: Proxy# a) (coerce sz) 0 quotInt)
+
+-- | Compute how many elements of type @e@ can fit in the supplied number of bytes.
+--
+-- @since 0.1.0
+fromByteCount :: forall e . Prim e => Count Word8 -> Count e
+fromByteCount sz = coerce (quotSizeOfWith (proxy# :: Proxy# e) (coerce sz) 0 quotInt)
 {-# INLINE[0] fromByteCount #-}
 {-# RULES
 "fromByteCount" fromByteCount = id
@@ -199,15 +245,15 @@
 {-# INLINE fromByteCountRemInt8 #-}
 
 
-fromByteCountRem :: forall a . Prim a => Count Word8 -> (Count a, Count Word8)
-fromByteCountRem sz = coerce (quotSizeOfWith (proxy# :: Proxy# a) (coerce sz) (0, 0) quotRemInt)
+fromByteCountRem :: forall e . Prim e => Count Word8 -> (Count e, Count Word8)
+fromByteCountRem sz = coerce (quotSizeOfWith (proxy# :: Proxy# e) (coerce sz) (0, 0) quotRemInt)
 {-# INLINE[0] fromByteCountRem #-}
 {-# RULES
 "fromByteCountRemWord8" fromByteCountRem = fromByteCountRemWord8
 "fromByteCountRemInt8"  fromByteCountRem = fromByteCountRemInt8
   #-}
 
-quotSizeOfWith :: forall a b. Prim a => Proxy# a -> Int -> b -> (Int -> Int -> b) -> b
+quotSizeOfWith :: forall e b. Prim e => Proxy# e -> Int -> b -> (Int -> Int -> b) -> b
 quotSizeOfWith px# sz onZero quotWith
   | tySize <= 0 = onZero
   | otherwise = sz `quotWith` tySize
@@ -217,21 +263,46 @@
 
 
 -- | Offset in number of elements
-newtype Off a = Off
+newtype Off e = Off
   { unOff :: Int
   } deriving (Eq, Show, Ord, Enum, Bounded, Num, Integral, Real, NFData)
 
-instance Prim (Off a) where
-  type PrimBase (Off a) = Int
+instance Prim (Off e) where
+  type PrimBase (Off e) = Int
 
 
 -- | Helper noop function that restricts `Off`set to the type of proxy
 --
--- @since 0.1.0
-offAsProxy :: proxy a -> Off a -> Off a
-offAsProxy _ = id
+-- @since 0.2.0
+offForProxyTypeOf :: Off e -> proxy e -> Off e
+offForProxyTypeOf off _ = off
 
+-- | Restrict type argument of `Off` to the same type as the second argument, which itself
+-- is not evaluated
+--
+-- @since 0.2.0
+offForType :: Off e -> e -> Off e
+offForType c _ = c
 
+-- | Cast an offset to count. Useful for dealing with regions.
+--
+-- >>> import Data.Prim
+-- >>> totalCount = Count 10 :: Count Word
+-- >>> startOffset = Off 4 :: Off Word
+-- >>> totalCount - offToCount startOffset
+-- Count {unCount = 6}
+--
+-- @since 0.2.0
+offToCount :: Off e -> Count e
+offToCount = coerce
+
+-- | Convert an offset in elements to count in bytres.
+--
+-- @since 0.2.0
+offToByteCount :: Prim e => Off e -> Count Word8
+offToByteCount = offToCount . toByteOff
+{-# INLINE offToByteCount #-}
+
 -- | Compute byte offset from an offset of `Prim` type
 --
 -- >>> toByteOff (10 :: Off Word64)
@@ -239,25 +310,39 @@
 --
 -- @since 0.1.0
 toByteOff :: Prim e => Off e -> Off Word8
-toByteOff off = Off (I# (fromOff# off))
+toByteOff off = Off (I# (unOffBytes# off))
 {-# INLINE toByteOff #-}
 
-fromOffWord8# :: Off Word8 -> Int#
-fromOffWord8# (Off (I# o#)) = o#
-{-# INLINE fromOffWord8# #-}
-fromOffInt8# :: Off Int8 -> Int#
-fromOffInt8# (Off (I# o#)) = o#
-{-# INLINE fromOffInt8# #-}
 
+-- | Convert an offset for some type @e@ with `Prim` instance to the number of bytes as an
+-- `Int`.
+--
+-- >>> unOffBytes (10 :: Off Word64)
+-- 80
+--
+-- @since 0.2.0
+unOffBytes :: Prim e => Off e -> Int
+unOffBytes off = I# (unOffBytes# off)
+{-# INLINE unOffBytes #-}
+
+
+
+unOffWord8# :: Off Word8 -> Int#
+unOffWord8# (Off (I# o#)) = o#
+{-# INLINE unOffWord8# #-}
+unOffInt8# :: Off Int8 -> Int#
+unOffInt8# (Off (I# o#)) = o#
+{-# INLINE unOffInt8# #-}
+
 -- | Convert offset of some type into number of bytes
-fromOff# :: Prim a => Off a -> Int#
-fromOff# o@(Off (I# o#)) =
+unOffBytes# :: Prim e => Off e -> Int#
+unOffBytes# o@(Off (I# o#)) =
   case coerce (byteCountProxy o) of
     I# sz# -> sz# *# o#
-{-# INLINE[0] fromOff# #-}
+{-# INLINE[0] unOffBytes# #-}
 {-# RULES
-"fromOffWord8#" fromOff# = fromOffWord8#
-"fromOffInt8#" fromOff# = fromOffInt8#
+"unOffWord8#" unOffBytes# = unOffWord8#
+"unOffInt8#" unOffBytes# = unOffInt8#
   #-}
 
 
@@ -266,8 +351,8 @@
 fromByteOffInt8 = coerce
 {-# INLINE fromByteOffInt8 #-}
 
-fromByteOff :: forall a . Prim a => Off Word8 -> Off a
-fromByteOff sz = coerce (quotSizeOfWith (proxy# :: Proxy# a) (coerce sz) 0 quotInt)
+fromByteOff :: forall e . Prim e => Off Word8 -> Off e
+fromByteOff sz = coerce (quotSizeOfWith (proxy# :: Proxy# e) (coerce sz) 0 quotInt)
 {-# INLINE[0] fromByteOff #-}
 {-# RULES
 "fromByteOff" fromByteOff = id
@@ -283,8 +368,8 @@
 {-# INLINE fromByteOffRemInt8 #-}
 
 
-fromByteOffRem :: forall a . Prim a => Off Word8 -> (Off a, Off Word8)
-fromByteOffRem sz = coerce (quotSizeOfWith (proxy# :: Proxy# a) (coerce sz) (0, 0) quotRemInt)
+fromByteOffRem :: forall e . Prim e => Off Word8 -> (Off e, Off Word8)
+fromByteOffRem sz = coerce (quotSizeOfWith (proxy# :: Proxy# e) (coerce sz) (0, 0) quotRemInt)
 {-# INLINE[0] fromByteOffRem #-}
 {-# RULES
 "fromByteOffRemWord8" fromByteOffRem = fromByteOffRemWord8
diff --git a/src/Data/Prim/Class.hs b/src/Data/Prim/Class.hs
--- a/src/Data/Prim/Class.hs
+++ b/src/Data/Prim/Class.hs
@@ -6,6 +6,7 @@
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE MagicHash #-}
+{-# LANGUAGE PolyKinds #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE TypeOperators #-}
@@ -57,9 +58,9 @@
 import qualified Data.Functor.Product as Functor
 import Data.Monoid
 import System.IO
+import Data.Semigroup
 #if __GLASGOW_HASKELL__ >= 800
 import Data.Functor.Const
-import Data.Semigroup
 #endif /* __GLASGOW_HASKELL__ >= 800 */
 
 #if __GLASGOW_HASKELL__ < 802
@@ -971,9 +972,6 @@
   type PrimBase CRLim = HTYPE_RLIM_T
 #endif
 
-#if __GLASGOW_HASKELL__ >= 800
-
-
 instance Prim a => Prim (Max a) where
   type PrimBase (Max a) = a
 instance Prim a => Prim (Min a) where
@@ -1052,8 +1050,6 @@
 #endif /* __GLASGOW_HASKELL__ >= 802 */
 
 
-#endif /* __GLASGOW_HASKELL__ >= 800 */
-
 instance (Prim (f a), Prim (g a)) => Prim (Functor.Product f g a) where
   type PrimBase (Functor.Product f g a) = (f a, g a)
   toPrimBase (Functor.Pair fa ga) = (fa, ga)
@@ -1268,7 +1264,7 @@
   indexOffAddr# addr# i# =
     let addr0# = addr# `plusAddr#` (i# *# sizeOf# (proxy# :: Proxy# (a, b)))
         addr1# = addr0# `plusAddr#` sizeOf# (proxy# :: Proxy# a)
-     in ( indexOffAddr# addr0# 0#, indexOffAddr# addr1# 0#)
+     in (indexOffAddr# addr0# 0#, indexOffAddr# addr1# 0#)
   {-# INLINE indexOffAddr# #-}
   readMutableByteArray# mba# i# =
     let i0# = i# *# sizeOf# (proxy# :: Proxy# (a, b))
@@ -1283,7 +1279,7 @@
   {-# INLINE readByteOffMutableByteArray# #-}
   readOffAddr# addr# i# s =
     let addr0# = addr# `plusAddr#` (i# *# sizeOf# (proxy# :: Proxy# (a, b)))
-        addr1# = addr# `plusAddr#` sizeOf# (proxy# :: Proxy# a)
+        addr1# = addr0# `plusAddr#` sizeOf# (proxy# :: Proxy# a)
     in case readOffAddr# addr0# 0# s of
          (# s', a0 #) ->
            case readOffAddr# addr1# 0# s' of
@@ -1300,7 +1296,7 @@
   writeOffAddr# addr# i# (a0, a1) s =
     let addr0# = addr# `plusAddr#` (i# *# sizeOf# (proxy# :: Proxy# (a, b)))
         addr1# = addr0# `plusAddr#` sizeOf# (proxy# :: Proxy# a)
-    in writeOffAddr# addr0# 0# a1 (writeOffAddr# addr1# 0# a0 s)
+    in writeOffAddr# addr1# 0# a1 (writeOffAddr# addr0# 0# a0 s)
   {-# INLINE writeOffAddr# #-}
   setMutableByteArray# = setMutableByteArrayLoop#
     -- TODO: optimize with rewrite rules?
@@ -1360,7 +1356,7 @@
   readOffAddr# addr# i# s =
     let addr0# = addr#  `plusAddr#` (i# *# sizeOf# (proxy# :: Proxy# (a, b, c)))
         addr1# = addr0# `plusAddr#` sizeOf# (proxy# :: Proxy# a)
-        addr2# = addr0# `plusAddr#` sizeOf# (proxy# :: Proxy# b)
+        addr2# = addr1# `plusAddr#` sizeOf# (proxy# :: Proxy# b)
     in case readOffAddr# addr0# 0# s  of { (# s0, a0 #) ->
        case readOffAddr# addr1# 0# s0 of { (# s1, a1 #) ->
        case readOffAddr# addr2# 0# s1 of { (# s2, a2 #) ->
@@ -1381,10 +1377,10 @@
   writeOffAddr# addr# i# (a0, a1, a2) s =
     let addr0# = addr#  `plusAddr#` (i# *# sizeOf# (proxy# :: Proxy# (a, b, c)))
         addr1# = addr0# `plusAddr#` sizeOf# (proxy# :: Proxy# a)
-        addr2# = addr0# `plusAddr#` sizeOf# (proxy# :: Proxy# b)
-    in writeOffAddr# addr0# 0# a2
+        addr2# = addr1# `plusAddr#` sizeOf# (proxy# :: Proxy# b)
+    in writeOffAddr# addr2# 0# a2
        (writeOffAddr# addr1# 0# a1
-        (writeOffAddr# addr2# 0# a0 s))
+        (writeOffAddr# addr0# 0# a0 s))
   {-# INLINE writeOffAddr# #-}
   setMutableByteArray# = setMutableByteArrayLoop#
     --  | a0 == a1 && a1 == a2 = setMutableByteArray# mba# (o# *# 3#) (n# *# 3#) a0 s
@@ -1393,7 +1389,7 @@
     --  | a0 == a1 && a1 == a2 = setOffAddr# addr# (o# *# 3#) (n# *# 3#) a0 s
   {-# INLINE setOffAddr# #-}
 
--- TODO: Write optimized versions for higher tuples
+-- TODO: Write optimized versions for larger tuples
 instance (Prim a, Prim b, Prim c, Prim d) => Prim (a, b, c, d) where
   type PrimBase (a, b, c, d) = ((a, b), (c, d))
   toPrimBase (a, b, c, d) = ((a, b), (c, d))
@@ -1513,12 +1509,12 @@
       _       ->  setOffAddrLoop# addr# o# n# mVal s
   {-# INLINE setOffAddr# #-}
 
-max# :: Int# -> Int# -> Int#
-max# x# y# =
+maxInt# :: Int# -> Int# -> Int#
+maxInt# x# y# =
   case x# <# y# of
     0# -> x#
     _  -> y#
-{-# INLINE max# #-}
+{-# INLINE maxInt# #-}
 
 type family MaxOrdering (o :: Ordering) (x :: Nat) (y :: Nat) where
   MaxOrdering 'LT x y = y
@@ -1530,9 +1526,9 @@
   type PrimBase (Either a b) = Either a b
   type SizeOf (Either a b) = 1 + MaxOf (SizeOf a) (SizeOf b)
   type Alignment (Either a b) = 1 + MaxOf (Alignment a) (Alignment b)
-  sizeOf# _ = 1# +# max# (sizeOf# (proxy# :: Proxy# a)) (sizeOf# (proxy# :: Proxy# b))
+  sizeOf# _ = 1# +# maxInt# (sizeOf# (proxy# :: Proxy# a)) (sizeOf# (proxy# :: Proxy# b))
   {-# INLINE sizeOf# #-}
-  alignment# _ = 1# +# max# (alignment# (proxy# :: Proxy# a)) (alignment# (proxy# :: Proxy# b))
+  alignment# _ = 1# +# maxInt# (alignment# (proxy# :: Proxy# a)) (alignment# (proxy# :: Proxy# b))
   {-# INLINE alignment# #-}
   indexByteOffByteArray# ba# i# =
     case indexInt8Array# ba# i# of
@@ -1573,10 +1569,10 @@
         i1# = i# +# 1#
     in case eVal of
          Left a -> -- TODO: Optimize duplication away
-           setByteArray# mba# (i1# +# a#) (max# 0# (b# -# a#)) 0#
+           setByteArray# mba# (i1# +# a#) (maxInt# 0# (b# -# a#)) 0#
            (writeByteOffMutableByteArray# mba# i1# a (writeInt8Array# mba# i# 0# s))
          Right b ->
-           setByteArray# mba# (i1# +# b#) (max# 0# (a# -# b#)) 0#
+           setByteArray# mba# (i1# +# b#) (maxInt# 0# (a# -# b#)) 0#
            (writeByteOffMutableByteArray# mba# i1# b (writeInt8Array# mba# i# 1# s))
   {-# INLINE writeByteOffMutableByteArray# #-}
   writeMutableByteArray# mba# i# eVal s =
@@ -1587,14 +1583,15 @@
   writeOffAddr# addr# i# eVal s =
     let a# = sizeOf# (proxy# :: Proxy# a)
         b# = sizeOf# (proxy# :: Proxy# b)
-        addr0# = addr# `plusAddr#` (i# *# (1# +# a# +# b#))
+        k# = sizeOf# (proxy# :: Proxy# (Either a b))
+        addr0# = addr# `plusAddr#` (i# *# k#)
         addr1# = addr0# `plusAddr#` 1#
     in case eVal of
          Left a  ->
-           setOffAddr# addr1# a# (max# 0# (b# -# a#)) (I8# 0#)
+           setOffAddr# addr1# a# (maxInt# 0# (b# -# a#)) (I8# 0#)
            (writeOffAddr# addr1# 0# a (writeInt8OffAddr# addr0# 0# 0# s))
          Right b ->
-           setOffAddr# addr1# b# (max# 0# (a# -# b#)) (I8# 0#)
+           setOffAddr# addr1# b# (maxInt# 0# (a# -# b#)) (I8# 0#)
            (writeOffAddr# addr1# 0# b (writeInt8OffAddr# addr0# 0# 1# s))
   {-# INLINE writeOffAddr# #-}
   setMutableByteArray# = setMutableByteArrayLoop#
diff --git a/src/Foreign/Prim/C/LtGHC802.hs b/src/Foreign/Prim/C/LtGHC802.hs
--- a/src/Foreign/Prim/C/LtGHC802.hs
+++ b/src/Foreign/Prim/C/LtGHC802.hs
@@ -14,12 +14,13 @@
 --
 module Foreign.Prim.C.LtGHC802
   (
+  -- ** GHC-8.4
+    compareByteArrays#
   -- ** GHC-8.2
-    CBool(..)
+  , CBool(..)
   , isByteArrayPinned#
   , isMutableByteArrayPinned#
   -- ** GHC-8.0
-  , compareByteArrays#
   , getSizeofMutableByteArray#
   ) where
 
@@ -49,10 +50,6 @@
 foreign import ccall unsafe "primal_compat.c primal_is_byte_array_pinned"
   isMutableByteArrayPinned# :: MutableByteArray# s -> Int#
 
--- | This is equivalent to @memcmp@ in C
-foreign import ccall unsafe "primal.c primal_memcmp"
-  compareByteArrays# :: ByteArray# -> Int# -> ByteArray# -> Int# -> Int# -> Int#
-
 #if __GLASGOW_HASKELL__ < 800
 -- | Compatibility function for ghc-7.10 version
 getSizeofMutableByteArray# :: MutableByteArray# s -> State# s -> (# State# s, Int# #)
@@ -66,3 +63,12 @@
 import Foreign.C.Types (CBool(..))
 
 #endif /* __GLASGOW_HASKELL__ < 802 */
+
+
+#if __GLASGOW_HASKELL__ < 804
+
+-- | This is equivalent to @memcmp@ in C
+foreign import ccall unsafe "primal.c primal_memcmp"
+  compareByteArrays# :: ByteArray# -> Int# -> ByteArray# -> Int# -> Int# -> Int#
+
+#endif /* __GLASGOW_HASKELL__ < 804 */
diff --git a/src/Foreign/Prim/Ptr.hs b/src/Foreign/Prim/Ptr.hs
--- a/src/Foreign/Prim/Ptr.hs
+++ b/src/Foreign/Prim/Ptr.hs
@@ -129,7 +129,7 @@
 
 
 plusOffPtr :: Prim e => Ptr e -> Off e -> Ptr e
-plusOffPtr (Ptr addr#) off = Ptr (addr# `plusAddr#` fromOff# off)
+plusOffPtr (Ptr addr#) off = Ptr (addr# `plusAddr#` unOffBytes# off)
 {-# INLINE plusOffPtr #-}
 
 -- | Find the offset in bytes that is between the two pointers by subtracting one address
@@ -163,7 +163,7 @@
   copyBytes
     (dstPtr `plusOffPtr` dstOff)
     (srcPtr `plusOffPtr` srcOff)
-    (fromCount c)
+    (unCountBytes c)
 {-# INLINE copyPtrToPtr #-}
 
 copyByteOffPtrToPtr ::
@@ -179,7 +179,7 @@
   copyBytes
     (dstPtr `plusPtr` dstOff)
     (srcPtr `plusPtr` srcOff)
-    (fromCount c)
+    (unCountBytes c)
 {-# INLINE copyByteOffPtrToPtr #-}
 
 movePtrToPtr :: (MonadPrim s m, Prim e) => Ptr e -> Off e -> Ptr e -> Off e -> Count e -> m ()
@@ -196,21 +196,21 @@
   -> Count e
   -> m ()
 moveByteOffPtrToPtr (Ptr srcAddr#) (Off (I# srcOff#)) (Ptr dstAddr#) (Off (I# dstOff#)) c =
-  unsafeIOToPrim $ memmoveAddr# srcAddr# srcOff# dstAddr# dstOff# (fromCount# c)
+  unsafeIOToPrim $ memmoveAddr# srcAddr# srcOff# dstAddr# dstOff# (unCountBytes# c)
 {-# INLINE moveByteOffPtrToPtr #-}
 
 -- | Compare memory between two pointers. Offsets and count is in number of elements,
 -- instead of byte count. Use `compareByteOffPtrToPtr` when offset in bytes is required.
 comparePtrToPtr :: Prim e => Ptr e -> Off e -> Ptr e -> Off e -> Count e -> Ordering
 comparePtrToPtr (Ptr addr1#) off1 (Ptr addr2#) off2 c =
-  toOrdering# (memcmpAddr# addr1# (fromOff# off1) addr2# (fromOff# off2) (fromCount# c))
+  toOrdering# (memcmpAddr# addr1# (unOffBytes# off1) addr2# (unOffBytes# off2) (unCountBytes# c))
 {-# INLINE comparePtrToPtr #-}
 
 -- | Same as `comparePtrToPtr`, except offset is in bytes instead of number of elements.
 compareByteOffPtrToPtr ::
      Prim e => Ptr e -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> Ordering
 compareByteOffPtrToPtr (Ptr addr1#) (Off (I# off1#)) (Ptr addr2#) (Off (I# off2#)) c =
-  toOrdering# (memcmpAddr# addr1# off1# addr2# off2# (fromCount# c))
+  toOrdering# (memcmpAddr# addr1# off1# addr2# off2# (unCountBytes# c))
 {-# INLINE compareByteOffPtrToPtr #-}
 
 
@@ -583,19 +583,19 @@
 {-# INLINE prefetchPtr3 #-}
 
 prefetchOffPtr0 :: (MonadPrim s m, Prim e) => Ptr e -> Off e -> m ()
-prefetchOffPtr0 (Ptr b#) off = prim_ (prefetchAddr0# b# (fromOff# off))
+prefetchOffPtr0 (Ptr b#) off = prim_ (prefetchAddr0# b# (unOffBytes# off))
 {-# INLINE prefetchOffPtr0 #-}
 
 prefetchOffPtr1 :: (MonadPrim s m, Prim e) => Ptr e -> Off e -> m ()
-prefetchOffPtr1 (Ptr b#) off = prim_ (prefetchAddr1# b# (fromOff# off))
+prefetchOffPtr1 (Ptr b#) off = prim_ (prefetchAddr1# b# (unOffBytes# off))
 {-# INLINE prefetchOffPtr1 #-}
 
 prefetchOffPtr2 :: (MonadPrim s m, Prim e) => Ptr e -> Off e -> m ()
-prefetchOffPtr2 (Ptr b#) off = prim_ (prefetchAddr2# b# (fromOff# off))
+prefetchOffPtr2 (Ptr b#) off = prim_ (prefetchAddr2# b# (unOffBytes# off))
 {-# INLINE prefetchOffPtr2 #-}
 
 prefetchOffPtr3 :: (MonadPrim s m, Prim e) => Ptr e -> Off e -> m ()
-prefetchOffPtr3 (Ptr b#) off = prim_ (prefetchAddr3# b# (fromOff# off))
+prefetchOffPtr3 (Ptr b#) off = prim_ (prefetchAddr3# b# (unOffBytes# off))
 {-# INLINE prefetchOffPtr3 #-}
 
 -- | Same as `GHC.freeHaskellFunPtr`
