diff --git a/CHANGES.markdown b/CHANGES.markdown
--- a/CHANGES.markdown
+++ b/CHANGES.markdown
@@ -1,3 +1,9 @@
+## Changes in 0.12.2 [2022.08.11]
+ - Sync with `base-4.17`/GHC 9.4
+ - Backport `(.^.)`, `(.>>.)`, `(.<<.)`, `(!>>.)`, `(!<<.)`, `oneBits` to
+   `Data.Bits.Compat`
+ - Backport `pattern TypeRep` to `Type.Reflection.Compat`
+
 ## Changes in 0.12.1 [2021.10.30]
  - Backport `Solo` to `Data.Tuple.Compat` when building with `ghc-prim-0.7.0`
    or later
diff --git a/README.markdown b/README.markdown
--- a/README.markdown
+++ b/README.markdown
@@ -117,8 +117,9 @@
  * `Text.Read.Compat.readMaybe`
  * `Text.Read.Compat.readEither`
  * `Data.Monoid.Compat.<>`
- * Added `bitDefault`, `testBitDefault`, and `popCountDefault` to `Data.Bits.Compat`
- * Added `toIntegralSized` to `Data.Bits.Compat` (if using `base-4.7`)
+ * Added `bitDefault`, `testBitDefault`, `popCountDefault`, `(.^.)`, `(.>>.)`,
+   `(.<<.)`, `(!>>.)`, and `(!<<.)` to `Data.Bits.Compat`
+ * Added `toIntegralSized` and `oneBits` to `Data.Bits.Compat` (if using `base-4.7` or later)
  * Added `bool` function to `Data.Bool.Compat`
  * Added `isLeft`, `isRight`, `fromLeft`, and `fromRight` to `Data.Either.Compat`
  * Added `forkFinally` to `Control.Concurrent.Compat`
@@ -155,6 +156,7 @@
  * `singleton` to `Data.List.Compat` and `Data.List.NonEmpty.Compat`
  * `hGetContents'`, `getContents'`, and `readFile'` to `System.IO.Compat`
  * `readBinP` to `Text.Read.Lex.Compat`
+ * `withTypeable` and `pattern TypeRep` to `Type.Reflection.Compat`
 
 ## What is not covered
 
@@ -310,6 +312,7 @@
 
 ## Supported versions of GHC/`base`
 
+ * `ghc-9.4.*`  / `base-4.17.*`
  * `ghc-9.2.*`  / `base-4.16.*`
  * `ghc-9.0.*`  / `base-4.15.*`
  * `ghc-8.10.*` / `base-4.14.*`
diff --git a/base-compat.cabal b/base-compat.cabal
--- a/base-compat.cabal
+++ b/base-compat.cabal
@@ -1,5 +1,5 @@
 name:             base-compat
-version:          0.12.1
+version:          0.12.2
 license:          MIT
 license-file:     LICENSE
 copyright:        (c) 2012-2018 Simon Hengel,
diff --git a/src/Data/Bits/Compat.hs b/src/Data/Bits/Compat.hs
--- a/src/Data/Bits/Compat.hs
+++ b/src/Data/Bits/Compat.hs
@@ -5,14 +5,22 @@
 , bitDefault
 , testBitDefault
 , popCountDefault
+, (.^.)
+, (.>>.)
+, (.<<.)
+#if MIN_VERSION_base(4,5,0)
+, (!>>.)
+, (!<<.)
+#endif
 #if MIN_VERSION_base(4,7,0)
 , toIntegralSized
+, oneBits
 #endif
 ) where
 
 import Data.Bits as Base
 
-#if !(MIN_VERSION_base(4,8,0))
+#if !(MIN_VERSION_base(4,17,0))
 import Prelude
 #endif
 
@@ -49,7 +57,52 @@
 {-# INLINABLE popCountDefault #-}
 #endif
 
-#if MIN_VERSION_base(4,7,0) && !(MIN_VERSION_base(4,8,0))
+#if !(MIN_VERSION_base(4,17,0))
+-- | Infix version of 'xor'.
+--
+-- /Since: 4.17/
+(.^.) :: (Bits a) => a -> a -> a
+(.^.) = xor
+
+infixl 6 .^.
+
+-- | Infix version of 'shiftR'.
+--
+-- /Since: 4.17/
+(.>>.) :: (Bits a) => a -> Int -> a
+(.>>.) = shiftR
+
+infixl 8 .>>.
+
+-- | Infix version of 'shiftL'.
+--
+-- /Since: 4.17/
+(.<<.) :: (Bits a) => a -> Int -> a
+(.<<.) = shiftL
+
+infixl 8 .<<.
+
+# if MIN_VERSION_base(4,5,0)
+-- | Infix version of 'unsafeShiftR'.
+--
+-- /Since: 4.17/
+(!>>.) :: (Bits a) => a -> Int -> a
+(!>>.) = unsafeShiftR
+
+infixl 8 !>>.
+
+-- | Infix version of 'unsafeShiftL'.
+--
+-- /Since: 4.17/
+(!<<.) :: (Bits a) => a -> Int -> a
+(!<<.) = unsafeShiftL
+
+infixl 8 !<<.
+# endif
+#endif
+
+#if MIN_VERSION_base(4,7,0)
+# if !(MIN_VERSION_base(4,8,0))
 -- | Attempt to convert an 'Integral' type @a@ to an 'Integral' type @b@ using
 -- the size of the types as measured by 'Bits' methods.
 --
@@ -123,4 +176,26 @@
     yWidth  = bitSizeMaybe y
     ySigned = isSigned     y
 {-# INLINE isBitSubType #-}
+# endif
+
+# if !(MIN_VERSION_base(4,16,0))
+-- | A more concise version of @complement zeroBits@.
+--
+-- >>> complement (zeroBits :: Word) == (oneBits :: Word)
+-- True
+--
+-- >>> complement (oneBits :: Word) == (zeroBits :: Word)
+-- True
+--
+-- = Note
+--
+-- The constraint on 'oneBits' is arguably too strong. However, as some types
+-- (such as 'Natural') have undefined 'complement', this is the only safe
+-- choice.
+--
+-- /Since: 4.16/
+oneBits :: (FiniteBits a) => a
+oneBits = complement zeroBits
+{-# INLINE oneBits #-}
+# endif
 #endif
diff --git a/src/Data/Tuple/Compat.hs b/src/Data/Tuple/Compat.hs
--- a/src/Data/Tuple/Compat.hs
+++ b/src/Data/Tuple/Compat.hs
@@ -15,6 +15,6 @@
 
 import Data.Tuple
 
-#if MIN_VERSION_ghc_prim(0,7,0)
+#if !(MIN_VERSION_base(4,16,0)) && MIN_VERSION_ghc_prim(0,7,0)
 import GHC.Tuple (Solo(..))
 #endif
diff --git a/src/Type/Reflection/Compat.hs b/src/Type/Reflection/Compat.hs
--- a/src/Type/Reflection/Compat.hs
+++ b/src/Type/Reflection/Compat.hs
@@ -2,15 +2,22 @@
 #if __GLASGOW_HASKELL__ >= 702
 {-# LANGUAGE Trustworthy #-}
 #endif
-#if MIN_VERSION_base(4,10,0) && !(MIN_VERSION_base(4,11,0))
+#if MIN_VERSION_base(4,10,0)
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE PatternSynonyms #-}
+{-# LANGUAGE PolyKinds #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE ViewPatterns #-}
+# if !(MIN_VERSION_base(4,11,0))
 {-# LANGUAGE TypeInType #-}
+# endif
 #endif
 module Type.Reflection.Compat (
 #if MIN_VERSION_base(4,10,0)
   module Base
 , withTypeable
+, pattern TypeRep
 #endif
 ) where
 
@@ -20,7 +27,8 @@
 import Type.Reflection as Base hiding (withTypeable)
 #endif
 
-#if MIN_VERSION_base(4,10,0) && !(MIN_VERSION_base(4,11,0))
+#if MIN_VERSION_base(4,10,0)
+# if !(MIN_VERSION_base(4,11,0))
 import GHC.Exts (TYPE)
 import Type.Reflection (Typeable, TypeRep)
 import Unsafe.Coerce (unsafeCoerce)
@@ -34,4 +42,41 @@
 
 -- | A helper to satisfy the type checker in 'withTypeable'.
 newtype Gift a (r :: TYPE rep) = Gift (Typeable a => r)
+# endif
+
+# if !(MIN_VERSION_base(4,17,0))
+-- | A 'TypeableInstance' wraps up a 'Typeable' instance for explicit
+-- handling. For internal use: for defining 'TypeRep' pattern.
+data TypeableInstance (a :: k) where
+ TypeableInstance :: Typeable a => TypeableInstance a
+
+-- | Get a reified 'Typeable' instance from an explicit 'TypeRep'.
+--
+-- For internal use: for defining 'TypeRep' pattern.
+typeableInstance :: forall a. TypeRep a -> TypeableInstance a
+typeableInstance rep = withTypeable rep TypeableInstance
+
+-- | A explicitly bidirectional pattern synonym to construct a
+-- concrete representation of a type.
+--
+-- As an __expression__: Constructs a singleton @TypeRep a@ given a
+-- implicit 'Typeable a' constraint:
+--
+-- @
+-- TypeRep @a :: Typeable a => TypeRep a
+-- @
+--
+-- As a __pattern__: Matches on an explicit @TypeRep a@ witness bringing
+-- an implicit @Typeable a@ constraint into scope.
+--
+-- @
+-- f :: TypeRep a -> ..
+-- f TypeRep = {- Typeable a in scope -}
+-- @
+--
+-- /Since: 4.17.0.0/
+pattern TypeRep :: forall a. () => Typeable a => TypeRep a
+pattern TypeRep <- (typeableInstance -> TypeableInstance)
+  where TypeRep = typeRep
+# endif
 #endif
