diff --git a/Changes.md b/Changes.md
--- a/Changes.md
+++ b/Changes.md
@@ -1,5 +1,9 @@
 # Change log for the `llvm-tf` package
 
+## 12.1
+
+* make `IsFirstClass` superclass of `IsSized`.
+
 ## 9.2
 
 * custom `Ptr` type:
diff --git a/example/Arith.hs b/example/Arith.hs
--- a/example/Arith.hs
+++ b/example/Arith.hs
@@ -26,10 +26,9 @@
     foo <-
         createFunction InternalLinkage $ arithFunction $ \ x y ->
             exp (sin x) + y
-    let foo' = A.toArithFunction foo
     createFunction ExternalLinkage $ arithFunction $ \ x -> do
         y <- A.set $ x^3
-        sqrt (x^2 - 5 * x + 6) + foo' x x + y + log y
+        sqrt (x^2 - 5 * x + 6) + A.toArithFunction foo x x + y + log y
 
 mFib :: CodeGenModule (Function (Int32 -> IO Int32))
 mFib = A.recursiveFunction $ \ rfib n -> n %< 2 ? (1, rfib (n-1) + rfib (n-2))
diff --git a/example/Array.hs b/example/Array.hs
--- a/example/Array.hs
+++ b/example/Array.hs
@@ -1,3 +1,5 @@
+{-# OPTIONS_GHC -fsimpl-tick-factor=500 #-}
+{- ToDo: remove simplifier ticket option, cf. LLVM.Util.Memory -}
 module Main (main) where
 
 import LLVM.Util.Loop (forLoop)
diff --git a/example/List.hs b/example/List.hs
--- a/example/List.hs
+++ b/example/List.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE ForeignFunctionInterface #-}
 module Main (main) where
 
diff --git a/llvm-tf.cabal b/llvm-tf.cabal
--- a/llvm-tf.cabal
+++ b/llvm-tf.cabal
@@ -1,5 +1,5 @@
 Name:          llvm-tf
-Version:       12.0.0.1
+Version:       12.1
 License:       BSD3
 License-File:  LICENSE
 Synopsis:      Bindings to the LLVM compiler toolkit using type families.
@@ -37,7 +37,7 @@
   Location: http://code.haskell.org/~thielema/llvm-tf/
 
 Source-Repository this
-  Tag:      12.0.0.1
+  Tag:      12.1
   Type:     darcs
   Location: http://code.haskell.org/~thielema/llvm-tf/
 
diff --git a/private/LLVM/Core/CodeGen.hs b/private/LLVM/Core/CodeGen.hs
--- a/private/LLVM/Core/CodeGen.hs
+++ b/private/LLVM/Core/CodeGen.hs
@@ -4,6 +4,7 @@
 {-# LANGUAGE DeriveDataTypeable #-}
 {-# LANGUAGE Rank2Types #-}
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 module LLVM.Core.CodeGen(
     -- * Module creation
     newModule, newNamedModule, defineModule, createModule, createNamedModule,
diff --git a/private/LLVM/Core/Instructions.hs b/private/LLVM/Core/Instructions.hs
--- a/private/LLVM/Core/Instructions.hs
+++ b/private/LLVM/Core/Instructions.hs
@@ -73,7 +73,7 @@
     CodeGen.FunctionArgs, CodeGen.FunctionCodeGen, CodeGen.FunctionResult,
     AllocArg,
     GetElementPtr, ElementPtrType, IsIndexArg, IsIndexType,
-    GetValue, ValueType,
+    GetValue, ValueType, ArrayIndex,
     GetField, FieldType,
     ) where
 
@@ -566,24 +566,23 @@
 
 instance (GetField as i, Dec.Natural i) => GetValue (Struct as) (Proxy i) where
     type ValueType (Struct as) (Proxy i) = FieldType as i
-    getIx _ n = Dec.integralFromProxy n
-
-instance (IsFirstClass a, Dec.Natural n) => GetValue (Array n a) Word where
-    type ValueType (Array n a) Word = a
-    getIx _ n = fromIntegral n
-
-instance (IsFirstClass a, Dec.Natural n) => GetValue (Array n a) Word32 where
-    type ValueType (Array n a) Word32 = a
-    getIx _ n = fromIntegral n
+    getIx _ = Dec.integralFromProxy
 
-instance (IsFirstClass a, Dec.Natural n) => GetValue (Array n a) Word64 where
-    type ValueType (Array n a) Word64 = a
-    getIx _ n = fromIntegral n
+class (Dec.Natural n) => ArrayIndex n ix where
+    cuIntFromArrayIndex :: proxy (Array n a) -> ix -> CUInt
 
+instance (Dec.Natural n) => ArrayIndex n Word where
+    cuIntFromArrayIndex _ = fromIntegral
+instance (Dec.Natural n) => ArrayIndex n Word32 where
+    cuIntFromArrayIndex _ = fromIntegral
+instance (Dec.Natural n) => ArrayIndex n Word64 where
+    cuIntFromArrayIndex _ = fromIntegral
+instance (Dec.Natural n, Dec.Natural i, i :<: n) => ArrayIndex n (Proxy i) where
+    cuIntFromArrayIndex _ = Dec.integralFromProxy
 
-instance (IsFirstClass a, Dec.Natural n, Dec.Natural i, i :<: n) => GetValue (Array n a) (Proxy i) where
-    type ValueType (Array n a) (Proxy i) = a
-    getIx _ n = Dec.integralFromProxy n
+instance (IsFirstClass a, ArrayIndex n ix) => GetValue (Array n a) ix where
+    type ValueType (Array n a) ix = a
+    getIx = cuIntFromArrayIndex
 
 
 -- | Get a value from an aggregate.
@@ -733,7 +732,7 @@
 inttoptr = convert FFI.constIntToPtr FFI.buildIntToPtr
 
 -- | Convert between to values of the same size by just copying the bit pattern.
-bitcast :: (ValueCons value, IsFirstClass a, IsFirstClass b, IsSized a, IsSized b, SizeOf a ~ SizeOf b)
+bitcast :: (ValueCons value, IsSized a, IsSized b, SizeOf a ~ SizeOf b)
         => value a -> CodeGenFunction r (value b)
 bitcast = convert FFI.constBitCast FFI.buildBitCast
 
@@ -895,7 +894,7 @@
 -}
 
 -- |Acceptable arguments to 'call'.
-class (f ~ CalledFunction g, r ~ CodeResult g, g ~ CallerFunction r f) =>
+class (r ~ CodeResult g, f ~ CalledFunction g, g ~ CallerFunction r f) =>
          CallArgs r f g where
     type CalledFunction g
     type CallerFunction r f
@@ -907,14 +906,14 @@
     doCall f a = doCall (applyCall f a)
 
 instance
-    (r ~ r', Value a ~ a') =>
+    (Value a ~ a', r ~ r') =>
         CallArgs r (IO a) (CodeGenFunction r' a') where
     type CalledFunction (CodeGenFunction r' a') = IO (UnValue a')
     type CallerFunction r (IO a) = CodeGenFunction r (Value a)
     doCall = runCall
 
-doCallDef :: Caller -> [FFI.ValueRef] -> b -> CodeGenFunction r (Value a)
-doCallDef mkCall args _ =
+doCallDef :: Caller -> [FFI.ValueRef] -> CodeGenFunction r (Value a)
+doCallDef mkCall args =
     withCurrentBuilder $ \ bld ->
       liftM Value $ mkCall bld (reverse args)
 
@@ -935,7 +934,7 @@
 applyCall (Call mkCall args) (Value arg) = Call mkCall (arg:args)
 
 runCall :: Call (IO a) -> CodeGenFunction r (Value a)
-runCall (Call mkCall args) = doCallDef mkCall args ()
+runCall (Call mkCall args) = doCallDef mkCall args
 
 
 invokeFromFunction ::
diff --git a/private/LLVM/Core/Instructions/Guided.hs b/private/LLVM/Core/Instructions/Guided.hs
--- a/private/LLVM/Core/Instructions/Guided.hs
+++ b/private/LLVM/Core/Instructions/Guided.hs
@@ -257,7 +257,7 @@
 
 -- | Convert between to values of the same size by just copying the bit pattern.
 bitcast ::
-    (ValueCons value, IsFirstClass a, IsFirstClass bv,
+    (ValueCons value, IsFirstClass bv,
      IsPrimitive a, IsPrimitive b, Type shape a ~ av, Type shape b ~ bv,
      IsSized a, IsSized b, SizeOf a ~ SizeOf b) =>
     Guide shape (a,b) -> value av -> CodeGenFunction r (value bv)
diff --git a/private/LLVM/Core/Type.hs b/private/LLVM/Core/Type.hs
--- a/private/LLVM/Core/Type.hs
+++ b/private/LLVM/Core/Type.hs
@@ -217,7 +217,7 @@
 --  used to find signedness in Arithmetic
 -- |Integral types.
 class (IsArithmetic a, IsIntegerOrPointer a) => IsInteger a where
-   type Signed a :: *
+   type Signed a
 
 -- Usage:
 --  icmp
@@ -257,7 +257,7 @@
 data VectorShape n
 
 class Shape shape where
-    type ShapedType shape a :: *
+    type ShapedType shape a
 
 instance Shape ScalarShape where
     type ShapedType ScalarShape a = a
@@ -267,13 +267,12 @@
 
 -- |Number of elements for instructions that handle both primitive and vector types
 class (IsFirstClass a) => IsScalarOrVector a where
-    type ShapeOf a :: *
+    type ShapeOf a
 
 
 -- Usage:
 --  Precondition for function args and result.
 --  Used by some instructions, like ret and phi.
---  XXX IsSized as precondition?
 -- |First class types, i.e., the types that can be passed as arguments, etc.
 class IsType a => IsFirstClass a
 
@@ -281,8 +280,8 @@
 --  Context for Array being a type
 --  thus, allocation instructions
 -- |Types with a fixed size.
-class (IsType a, Dec.Natural (SizeOf a)) => IsSized a where
-    type SizeOf a :: *
+class (IsFirstClass a, Dec.Natural (SizeOf a)) => IsSized a where
+    type SizeOf a
 
 sizeOf :: TypeDesc -> Integer
 sizeOf TDFloat  = 32
@@ -330,13 +329,13 @@
 instance IsType Word32 where typeDesc _ = TDInt False 32
 instance IsType Word64 where typeDesc _ = TDInt False 64
 instance IsType Word   where
-   typeDesc _ = TDInt False (toInteger$bitSize(0::Word))
+   typeDesc _ = TDInt False (toInteger $ bitSize(0::Word))
 instance IsType Int8   where typeDesc _ = TDInt True   8
 instance IsType Int16  where typeDesc _ = TDInt True  16
 instance IsType Int32  where typeDesc _ = TDInt True  32
 instance IsType Int64  where typeDesc _ = TDInt True  64
 instance IsType Int    where
-   typeDesc _ = TDInt True  (toInteger$bitSize(0::Int))
+   typeDesc _ = TDInt True  (toInteger $ bitSize(0::Int))
 
 -- Sequence types
 instance (Dec.Natural n, IsSized a) => IsType (Array n a)
@@ -535,12 +534,13 @@
 instance IsFirstClass Label
 instance IsFirstClass () -- XXX This isn't right, but () can be returned
 instance (StructFields as) => IsFirstClass (Struct as)
+instance (StructFields as) => IsFirstClass (PackedStruct as)
 
 
 {- |
 Types where LLVM and 'Foreign.Storable' memory layout are compatible.
 -}
-class (Foreign.Storable a, IsFirstClass a, IsSized a) => Storable a
+class (Foreign.Storable a, IsSized a) => Storable a
 instance Storable Float
 instance Storable Double
 instance Storable Int
diff --git a/private/LLVM/Core/UnaryVector.hs b/private/LLVM/Core/UnaryVector.hs
--- a/private/LLVM/Core/UnaryVector.hs
+++ b/private/LLVM/Core/UnaryVector.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 module LLVM.Core.UnaryVector (
    T, vector, cyclicVector,
    FixedLength.fromFixedList, FixedLength.toFixedList, FixedLength.head,
diff --git a/private/LLVM/Core/Vector.hs b/private/LLVM/Core/Vector.hs
--- a/private/LLVM/Core/Vector.hs
+++ b/private/LLVM/Core/Vector.hs
@@ -1,6 +1,7 @@
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE Rank2Types #-}
 module LLVM.Core.Vector (MkVector(..), vector, cyclicVector, consVector) where
 
diff --git a/src/LLVM/Util/Arithmetic.hs b/src/LLVM/Util/Arithmetic.hs
--- a/src/LLVM/Util/Arithmetic.hs
+++ b/src/LLVM/Util/Arithmetic.hs
@@ -5,6 +5,7 @@
 {-# LANGUAGE UndecidableInstances #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 module LLVM.Util.Arithmetic(
     TValue,
     (%==), (%/=), (%<), (%<=), (%>), (%>=),
diff --git a/src/LLVM/Util/Memory.hs b/src/LLVM/Util/Memory.hs
--- a/src/LLVM/Util/Memory.hs
+++ b/src/LLVM/Util/Memory.hs
@@ -1,4 +1,10 @@
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# OPTIONS_GHC -fsimpl-tick-factor=500 #-}
+{-
+ToDo: remove simplifier ticket option
+
+Necessary for GHC-9.4 because of bug https://gitlab.haskell.org/ghc/ghc/-/issues/22716
+-}
 module LLVM.Util.Memory (
     memcpy,
     memmove,
diff --git a/test/Test/Marshal.hs b/test/Test/Marshal.hs
--- a/test/Test/Marshal.hs
+++ b/test/Test/Marshal.hs
@@ -276,5 +276,5 @@
 testsExtract =
    map (mapFst ("Extract." ++)) $
       testsVector ++
-      map (mapPair (("Struct." ++), ($False))) testsStruct ++
-      map (mapPair (("StructByte." ++), ($True))) testsStruct
+      map (mapPair (("Struct." ++), ($ False))) testsStruct ++
+      map (mapPair (("StructByte." ++), ($ True))) testsStruct
