diff --git a/Changes.md b/Changes.md
--- a/Changes.md
+++ b/Changes.md
@@ -1,5 +1,22 @@
 # Change log for the `llvm-extra` package
 
+## 0.10
+
+* `Memory`: Attention!
+  Memory layout is no longer compatible with `Foreign.Storable`.
+  E.g. `Bool` now takes 1 byte space like LLVM does,
+  but no longer 4 byte like `Foreign.Storable`.
+  A `Foreign.Storable`-compliant layout
+  is provided by `LLVM.Extra.Storable` now.
+
+* `Marshal`: Now based on `Memory.load` and `Memory.store`.
+  Does not need `Proxy` anymore.
+
+* `Class` -> `Tuple`,
+  `Tuple.Vector` class added.
+  Pro: `valueOf vector` is no longer restricted to `IsPrimitive` elements.
+  Cons: type inference works less well than before
+
 ## 0.9
 
 * `Extension`: Move to new package `llvm-extension`.
diff --git a/llvm-extra.cabal b/llvm-extra.cabal
--- a/llvm-extra.cabal
+++ b/llvm-extra.cabal
@@ -1,6 +1,6 @@
 Cabal-Version:  2.2
 Name:           llvm-extra
-Version:        0.9.1
+Version:        0.10
 License:        BSD-3-Clause
 License-File:   LICENSE
 Author:         Henning Thielemann <haskell@henning-thielemann.de>
@@ -21,9 +21,15 @@
   * a type class for loading and storing sets of values with one command (macro)
     in "LLVM.Extra.Memory",
   .
-  * support instance declarations of LLVM classes
-    in "LLVM.Extra.Class",
+  * storing and reading Haskell values in an LLVM compatible format
+    in "LLVM.Extra.Marshal",
   .
+  * LLVM functions for loading and storing values in Haskell's @Storable@ format
+    in "LLVM.Extra.Storable",
+  .
+  * support value tuples and instance declarations of LLVM classes
+    in "LLVM.Extra.Tuple",
+  .
   * handling of termination by a custom monad on top of @CodeGenFunction@
     in "LLVM.Extra.MaybeContinuation"
   .
@@ -55,7 +61,7 @@
   default:     False
 
 Source-Repository this
-  Tag:         0.9.1
+  Tag:         0.10
   Type:        darcs
   Location:    http://code.haskell.org/~thielema/llvm-extra/
 
@@ -66,17 +72,20 @@
 Library
   Build-Depends:
     private,
-    llvm-tf >=9.1 && <9.2,
+    llvm-tf >=9.2 && <9.3,
     tfp >=1.0 && <1.1,
     non-empty >=0.2.1 && <0.4,
+    fixed-length >=0.2.1 && <0.3,
     containers >=0.1 && <0.7,
     enumset >=0.0.5 && <0.1,
+    storable-record >=0.0.5 && <0.1,
     storable-enum >=0.0 && <0.1,
     bool8 >=0.0 && <0.1,
     transformers >=0.1.1 && <0.6,
     tagged >=0.7 && <0.9,
-    utility-ht >=0.0.11 && <0.1,
+    utility-ht >=0.0.15 && <0.1,
     prelude-compat >=0.0 && <0.0.1,
+    base-orphans >= 0.5 && <1,
     base >=3 && <5
 
   Default-Language: Haskell98
@@ -87,10 +96,11 @@
     LLVM.Extra.Monad
     LLVM.Extra.Memory
     LLVM.Extra.Marshal
+    LLVM.Extra.Storable
     LLVM.Extra.Maybe
     LLVM.Extra.MaybeContinuation
     LLVM.Extra.Either
-    LLVM.Extra.Class
+    LLVM.Extra.Tuple
     LLVM.Extra.Control
     LLVM.Extra.Array
     LLVM.Extra.Scalar
@@ -100,13 +110,14 @@
     LLVM.Extra.Iterator
     LLVM.Extra.Multi.Iterator
     LLVM.Extra.Multi.Value
-    LLVM.Extra.Multi.Value.Memory
     LLVM.Extra.Multi.Value.Vector
     LLVM.Extra.Multi.Vector
-    LLVM.Extra.Multi.Vector.Memory
     LLVM.Extra.Multi.Vector.Instance
     LLVM.Extra.Multi.Class
   Other-Modules:
+    LLVM.Extra.Storable.Array
+    LLVM.Extra.Storable.Private
+    LLVM.Extra.TuplePrivate
     LLVM.Extra.MaybePrivate
     LLVM.Extra.EitherPrivate
     LLVM.Extra.MemoryPrivate
@@ -152,6 +163,7 @@
     llvm-extra,
     llvm-tf,
     tfp,
+    storable-record,
     utility-ht >=0.0.1 && <0.1,
     base >=3 && <5
   Default-Language: Haskell98
@@ -159,5 +171,6 @@
   Hs-Source-Dirs: test
   Main-Is: Main.hs
   Other-Modules:
+    Test.Storable
     Test.Vector
     LLVM.Extra.VectorAlt
diff --git a/private/LLVM/Extra/ArithmeticPrivate.hs b/private/LLVM/Extra/ArithmeticPrivate.hs
--- a/private/LLVM/Extra/ArithmeticPrivate.hs
+++ b/private/LLVM/Extra/ArithmeticPrivate.hs
@@ -10,7 +10,6 @@
     IsConst, IsPrimitive, IsArithmetic, IsInteger, IsFloating,
     getElementPtr, )
 
-import Foreign.Ptr (Ptr, )
 import Data.Word (Word32, )
 import Data.Int (Int32, )
 
@@ -39,14 +38,14 @@
 dec x = sub x (valueOf 1)
 
 advanceArrayElementPtr ::
-   Value (Ptr a) ->
-   CodeGenFunction r (Value (Ptr a))
+   Value (LLVM.Ptr a) ->
+   CodeGenFunction r (Value (LLVM.Ptr a))
 advanceArrayElementPtr p =
    getElementPtr p (valueOf 1 :: Value Word32, ())
 
 decreaseArrayElementPtr ::
-   Value (Ptr a) ->
-   CodeGenFunction r (Value (Ptr a))
+   Value (LLVM.Ptr a) ->
+   CodeGenFunction r (Value (LLVM.Ptr a))
 decreaseArrayElementPtr p =
    getElementPtr p (valueOf (-1) :: Value Int32, ())
 
diff --git a/private/LLVM/Extra/ScalarOrVectorPrivate.hs b/private/LLVM/Extra/ScalarOrVectorPrivate.hs
--- a/private/LLVM/Extra/ScalarOrVectorPrivate.hs
+++ b/private/LLVM/Extra/ScalarOrVectorPrivate.hs
@@ -14,7 +14,7 @@
     IsConst, IsInteger, CodeGenFunction)
 
 import qualified Data.NonEmpty as NonEmpty
-import Data.Word (Word8, Word16, Word32, Word64)
+import Data.Word (Word8, Word16, Word32, Word64, Word)
 import Data.Int  (Int8,  Int16,  Int32,  Int64)
 
 import Prelude hiding (replicate)
@@ -26,10 +26,12 @@
 type instance Scalar Double = Double
 type instance Scalar FP128  = FP128
 type instance Scalar Bool   = Bool
+type instance Scalar Int    = Int
 type instance Scalar Int8   = Int8
 type instance Scalar Int16  = Int16
 type instance Scalar Int32  = Int32
 type instance Scalar Int64  = Int64
+type instance Scalar Word   = Word
 type instance Scalar Word8  = Word8
 type instance Scalar Word16 = Word16
 type instance Scalar Word32 = Word32
@@ -48,10 +50,12 @@
 instance Replicate Double where replicate = return; replicateConst = id;
 instance Replicate FP128  where replicate = return; replicateConst = id;
 instance Replicate Bool   where replicate = return; replicateConst = id;
+instance Replicate Int    where replicate = return; replicateConst = id;
 instance Replicate Int8   where replicate = return; replicateConst = id;
 instance Replicate Int16  where replicate = return; replicateConst = id;
 instance Replicate Int32  where replicate = return; replicateConst = id;
 instance Replicate Int64  where replicate = return; replicateConst = id;
+instance Replicate Word   where replicate = return; replicateConst = id;
 instance Replicate Word8  where replicate = return; replicateConst = id;
 instance Replicate Word16 where replicate = return; replicateConst = id;
 instance Replicate Word32 where replicate = return; replicateConst = id;
diff --git a/src/Array.hs b/src/Array.hs
--- a/src/Array.hs
+++ b/src/Array.hs
@@ -7,17 +7,18 @@
 import qualified LLVM.Extra.Vector as Vector
 
 import qualified LLVM.Extra.Iterator as Iter
-import qualified LLVM.Extra.Class as Class
+import qualified LLVM.Extra.Tuple as Tuple
 import qualified LLVM.Extra.Arithmetic as A
-import LLVM.Extra.Control (arrayLoop, )
+import LLVM.Extra.Storable (arrayLoop, store)
+import LLVM.Extra.Control (ret)
 
 import qualified LLVM.ExecutionEngine as EE
 import qualified LLVM.Core as LLVM
 import LLVM.ExecutionEngine (simpleFunction, )
 import LLVM.Core
          (Value, valueOf, value, constOf, undef, zero, add, sub, mul, frem,
-          createFunction, Function, Linkage(ExternalLinkage), ret,
-          CodeGenModule, CodeGenFunction, store,
+          createFunction, Function, Linkage(ExternalLinkage),
+          CodeGenModule, CodeGenFunction,
           Vector, extractelement, insertelement, shufflevector, )
 import qualified System.IO as IO
 
@@ -42,7 +43,7 @@
 constVec ::
    Float -> CodeGenFunction r (Value (Vector D4 Float))
 constVec x =
-   return $ valueOf $ LLVM.toVector (x,x,x,x)
+   return $ valueOf $ LLVM.consVector x x x x
 
 constVecInsert ::
    Float -> CodeGenFunction r (Value (Vector D4 Float))
@@ -68,7 +69,7 @@
 This call
 
     fill (fromIntegral len) ptr
-       (LLVM.toVector (0.01003, 0.01001, 0.00999, 0.00997)) >>
+       (LLVM.consVector 0.01003 0.01001 0.00999 0.00997) >>
 
 would not work, because Vector is not of type Generic.
 -}
@@ -164,7 +165,7 @@
       liftA2
         (\ptri phase ->
           flip store ptri =<< mixGeneric =<< add const1 =<< mul const2 phase)
-        (Iter.arrayPtrs ptr)
+        (Iter.storableArrayPtrs ptr)
         (Iter.iterate (Vector.fraction <=< A.add freq) (value (zero :: Vec)))
     ret (value zero :: Value Float)
 
@@ -174,7 +175,8 @@
   A.sub (valueOf 1) =<<
   A.mul (valueOf 2) t
 
-osciSaw :: Value Float -> Value Float -> CodeGenFunction r (Value Float, Value Float)
+osciSaw ::
+  Value Float -> Value Float -> CodeGenFunction r (Value Float, Value Float)
 osciSaw freq phase =
   liftM2 (,) (waveSaw phase) (SoV.incPhase freq phase)
 
@@ -184,7 +186,7 @@
       (Word32 -> Ptr Float -> Float -> Float -> Float -> Float -> IO Float))
 mChorus =
   createFunction ExternalLinkage $ \ size ptr f0 f1 f2 f3 -> do
-    s <- arrayLoop size ptr Class.zeroTuple $
+    s <- arrayLoop size ptr Tuple.zero $
          \ ptri ((phase0, phase1), (phase2, phase3)) -> do
       (y0, phase0') <- osciSaw f0 phase0
       (y1, phase1') <- osciSaw f1 phase1
@@ -230,7 +232,7 @@
       (Word32 -> Ptr Float -> Float -> Float -> Float -> Float -> IO Float))
 mChorusMonadic =
   createFunction ExternalLinkage $ \ size ptr f0 f1 f2 f3 -> do
-    s <- arrayLoop size ptr Class.zeroTuple $
+    s <- arrayLoop size ptr Tuple.zero $
          \ ptri phases -> do
       (y, phases') <-
          flip runStateT phases $
diff --git a/src/LLVM/Extra/Arithmetic.hs b/src/LLVM/Extra/Arithmetic.hs
--- a/src/LLVM/Extra/Arithmetic.hs
+++ b/src/LLVM/Extra/Arithmetic.hs
@@ -29,7 +29,7 @@
 import LLVM.Extra.ArithmeticPrivate
    (inc, dec, advanceArrayElementPtr, decreaseArrayElementPtr, )
 
-import qualified LLVM.Extra.Class as Class
+import qualified LLVM.Extra.Tuple as Tuple
 import qualified LLVM.Extra.ScalarOrVector as SoV
 import qualified LLVM.Core as LLVM
 import LLVM.Core
@@ -58,7 +58,7 @@
 Disadvantage: You cannot use constant values directly,
 but you have to convert them all to 'Value'.
 -}
-class (Class.Zero a) => Additive a where
+class (Tuple.Zero a) => Additive a where
    zero :: a
    add :: a -> a -> CodeGenFunction r a
    sub :: a -> a -> CodeGenFunction r a
diff --git a/src/LLVM/Extra/Array.hs b/src/LLVM/Extra/Array.hs
--- a/src/LLVM/Extra/Array.hs
+++ b/src/LLVM/Extra/Array.hs
@@ -5,7 +5,7 @@
    map,
    ) where
 
-import qualified LLVM.Extra.Class as Class
+import qualified LLVM.Extra.Tuple as Tuple
 
 import qualified LLVM.Core as LLVM
 import LLVM.Core (Value, Array, CodeGenFunction, )
@@ -44,7 +44,7 @@
    (TypeNum.Natural n, LLVM.IsFirstClass a, LLVM.IsSized a) =>
    [Value a] -> CodeGenFunction r (Value (Array n a))
 assemble =
-   foldM (\v (k,x) -> LLVM.insertvalue v x (k::Word32)) Class.undefTuple .
+   foldM (\v (k,x) -> LLVM.insertvalue v x (k::Word32)) Tuple.undef .
    List.zip [0..]
 
 {- |
diff --git a/src/LLVM/Extra/Class.hs b/src/LLVM/Extra/Class.hs
deleted file mode 100644
--- a/src/LLVM/Extra/Class.hs
+++ /dev/null
@@ -1,220 +0,0 @@
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE FlexibleContexts #-}
-module LLVM.Extra.Class where
-
-import qualified LLVM.Extra.EitherPrivate as Either
-import qualified LLVM.Extra.MaybePrivate as Maybe
-import qualified LLVM.Core as LLVM
-import LLVM.Core
-   (Value, value, valueOf, undef,
-    ConstValue,
-    Vector,
-    IsConst, IsType, IsFirstClass, IsPrimitive,
-    CodeGenFunction, BasicBlock, )
-import LLVM.Util.Loop (Phi, phis, addPhis, )
-import qualified Type.Data.Num.Decimal as TypeNum
-
-import qualified Control.Applicative as App
-import Control.Applicative (pure, liftA2, )
-
-import qualified Data.Foldable as Fold
-import qualified Data.Traversable as Trav
-
-import Foreign.StablePtr (StablePtr, )
-import Foreign.Ptr (FunPtr, Ptr, )
-
-import Data.Word (Word8, Word16, Word32, Word64, )
-import Data.Int  (Int8,  Int16,  Int32,  Int64, )
-
-import Prelude2010 hiding (and, iterate, map, zipWith, writeFile, )
-import Prelude ()
-
-
--- * class for tuples of undefined values
-
-class Undefined a where
-   undefTuple :: a
-
-instance Undefined () where
-   undefTuple = ()
-
-instance (IsFirstClass a) => Undefined (Value a) where
-   undefTuple = value undef
-
-instance (IsFirstClass a) => Undefined (ConstValue a) where
-   undefTuple = undef
-
-instance (Undefined a, Undefined b) => Undefined (a, b) where
-   undefTuple = (undefTuple, undefTuple)
-
-instance (Undefined a, Undefined b, Undefined c) => Undefined (a, b, c) where
-   undefTuple = (undefTuple, undefTuple, undefTuple)
-
-instance (Undefined a) => Undefined (Maybe.T a) where
-   undefTuple = Maybe.Cons undefTuple undefTuple
-
-instance (Undefined a, Undefined b) => Undefined (Either.T a b) where
-   undefTuple = Either.Cons undefTuple undefTuple undefTuple
-
-
--- * class for tuples of zero values
-
-class Zero a where
-   zeroTuple :: a
-
-instance Zero () where
-   zeroTuple = ()
-
-instance (LLVM.IsFirstClass a) => Zero (Value a) where
-   zeroTuple = LLVM.value LLVM.zero
-
-instance (LLVM.IsFirstClass a) => Zero (ConstValue a) where
-   zeroTuple = LLVM.zero
-
-instance (Zero a, Zero b) => Zero (a, b) where
-   zeroTuple = (zeroTuple, zeroTuple)
-
-instance (Zero a, Zero b, Zero c) => Zero (a, b, c) where
-   zeroTuple = (zeroTuple, zeroTuple, zeroTuple)
-
-zeroTuplePointed ::
-   (Zero a, App.Applicative f) =>
-   f a
-zeroTuplePointed =
-   pure zeroTuple
-
-
--- * class for creating tuples of constant values
-
-class (Undefined (ValueTuple haskellValue)) =>
-      MakeValueTuple haskellValue where
-   type ValueTuple haskellValue :: *
-   valueTupleOf :: haskellValue -> ValueTuple haskellValue
-
-instance (MakeValueTuple ah, MakeValueTuple bh) =>
-      MakeValueTuple (ah,bh) where
-   type ValueTuple (ah,bh) = (ValueTuple ah, ValueTuple bh)
-   valueTupleOf ~(a,b) = (valueTupleOf a, valueTupleOf b)
-
-instance (MakeValueTuple ah, MakeValueTuple bh, MakeValueTuple ch) =>
-      MakeValueTuple (ah,bh,ch) where
-   type ValueTuple (ah,bh,ch) = (ValueTuple ah, ValueTuple bh, ValueTuple ch)
-   valueTupleOf ~(a,b,c) = (valueTupleOf a, valueTupleOf b, valueTupleOf c)
-
-instance (MakeValueTuple a) => MakeValueTuple (Maybe a) where
-   type ValueTuple (Maybe a) = Maybe.T (ValueTuple a)
-   valueTupleOf = maybe (Maybe.nothing undefTuple) (Maybe.just . valueTupleOf)
-
-instance
-   (MakeValueTuple a, MakeValueTuple b) =>
-      MakeValueTuple (Either a b) where
-   type ValueTuple (Either a b) = Either.T (ValueTuple a) (ValueTuple b)
-   valueTupleOf =
-      either
-         (Either.left undefTuple . valueTupleOf)
-         (Either.right undefTuple . valueTupleOf)
-
-instance MakeValueTuple Float  where type ValueTuple Float  = Value Float  ; valueTupleOf = valueOf
-instance MakeValueTuple Double where type ValueTuple Double = Value Double ; valueTupleOf = valueOf
--- instance MakeValueTuple FP128  where type ValueTuple FP128  = Value FP128  ; valueTupleOf = valueOf
-instance MakeValueTuple Bool   where type ValueTuple Bool   = Value Bool   ; valueTupleOf = valueOf
-instance MakeValueTuple Int8   where type ValueTuple Int8   = Value Int8   ; valueTupleOf = valueOf
-instance MakeValueTuple Int16  where type ValueTuple Int16  = Value Int16  ; valueTupleOf = valueOf
-instance MakeValueTuple Int32  where type ValueTuple Int32  = Value Int32  ; valueTupleOf = valueOf
-instance MakeValueTuple Int64  where type ValueTuple Int64  = Value Int64  ; valueTupleOf = valueOf
-instance MakeValueTuple Word8  where type ValueTuple Word8  = Value Word8  ; valueTupleOf = valueOf
-instance MakeValueTuple Word16 where type ValueTuple Word16 = Value Word16 ; valueTupleOf = valueOf
-instance MakeValueTuple Word32 where type ValueTuple Word32 = Value Word32 ; valueTupleOf = valueOf
-instance MakeValueTuple Word64 where type ValueTuple Word64 = Value Word64 ; valueTupleOf = valueOf
-instance MakeValueTuple ()     where type ValueTuple ()     = ()           ; valueTupleOf = id
-
-{-
-I'm not sure about this instance.
-Maybe it is better to convert the pointer target type
-according to a class that maps Haskell tuples to LLVM structs.
--}
-instance IsType a => MakeValueTuple (Ptr a) where
-   type ValueTuple (Ptr a) = Value (Ptr a)
-   valueTupleOf = valueOf
-
-instance LLVM.IsFunction a => MakeValueTuple (FunPtr a) where
-   type ValueTuple (FunPtr a) = Value (FunPtr a)
-   valueTupleOf = valueOf
-
-instance MakeValueTuple (StablePtr a) where
-   type ValueTuple (StablePtr a) = Value (StablePtr a)
-   valueTupleOf = valueOf
-
-{-
-instance (MakeValueTuple haskellValue llvmValue, Memory llvmValue llvmStruct) =>
-         MakeValueTuple (Ptr haskellValue) (Value (Ptr llvmStruct)) where
-   valueTupleOf = valueOf . castTuplePtr
-
-instance (Pos n) => MakeValueTuple (IntN n) where
-   type ValueTuple (IntN n) = (Value (IntN n))
-instance (Pos n) => MakeValueTuple (WordN n) where
-   type ValueTuple (WordN n) = (Value (WordN n))
--}
-instance (TypeNum.Positive n, IsPrimitive a, IsConst a) =>
-         MakeValueTuple (Vector n a) where
-   type ValueTuple (Vector n a) = Value (Vector n a)
-   valueTupleOf = valueOf
-
-
--- * default methods for LLVM classes
-
-{-
-buildTupleTraversable ::
-   (Undefined a, Trav.Traversable f, App.Applicative f) =>
-   FunctionRef -> State Int (f a)
-buildTupleTraversable f =
-   Trav.sequence (pure (buildTuple f))
--}
-{-
-buildTupleTraversable ::
-   (Trav.Traversable f, App.Applicative f) =>
-   State Int a ->
-   State Int (f a)
-buildTupleTraversable build =
-   Trav.sequence (pure build)
--}
-{- this is the version I used
-buildTupleTraversable ::
-   (Monad m, Trav.Traversable f, App.Applicative f) =>
-   m a ->
-   m (f a)
-buildTupleTraversable build =
-   Trav.sequence (pure build)
--}
-
-undefTuplePointed ::
-   (Undefined a, App.Applicative f) =>
-   f a
-undefTuplePointed =
-   pure undefTuple
-
-valueTupleOfFunctor ::
-   (MakeValueTuple h, Functor f) =>
-   f h -> f (ValueTuple h)
-valueTupleOfFunctor =
-   fmap valueTupleOf
-
-{-
-tupleDescFoldable ::
-   (IsTuple a, Fold.Foldable f) =>
-   f a -> [TypeDesc]
-tupleDescFoldable =
-   Fold.foldMap tupleDesc
--}
-
-phisTraversable ::
-   (Phi a, Trav.Traversable f) =>
-   BasicBlock -> f a -> CodeGenFunction r (f a)
-phisTraversable bb x =
-   Trav.mapM (phis bb) x
-
-addPhisFoldable ::
-   (Phi a, Fold.Foldable f, App.Applicative f) =>
-   BasicBlock -> f a -> f a -> CodeGenFunction r ()
-addPhisFoldable bb x y =
-   Fold.sequence_ (liftA2 (addPhis bb) x y)
diff --git a/src/LLVM/Extra/Control.hs b/src/LLVM/Extra/Control.hs
--- a/src/LLVM/Extra/Control.hs
+++ b/src/LLVM/Extra/Control.hs
@@ -16,13 +16,15 @@
    Select(select),
    selectTraversable,
    ifThenSelect,
+   ret,
+   retVoid,
    ) where
 
-import LLVM.Extra.ArithmeticPrivate
-   (cmp, sub, dec, advanceArrayElementPtr, )
 import qualified LLVM.Extra.ArithmeticPrivate as A
+import qualified LLVM.Extra.TuplePrivate as Tuple
+import LLVM.Extra.ArithmeticPrivate (cmp, sub, dec, advanceArrayElementPtr)
+
 import qualified LLVM.Core as LLVM
-import LLVM.Util.Loop (Phi, phis, addPhis, )
 import LLVM.Core
    (getCurrentBasicBlock, newBasicBlock, defineBasicBlock,
     br, condBr,
@@ -33,8 +35,6 @@
     CodeGenFunction,
     CodeGenModule, newModule, defineModule, writeBitcodeToFile, )
 
-import Foreign.Ptr (Ptr, )
-
 import qualified Control.Applicative as App
 import qualified Data.Traversable as Trav
 import Control.Monad (liftM3, liftM2, )
@@ -46,14 +46,14 @@
 -- * control structures
 
 {-
-I had to export Phi's methods in llvm-0.6.8
+I had to export Tuple.Phi's methods in llvm-0.6.8
 in order to be able to implement this function.
 -}
 arrayLoop ::
-   (Phi a, IsType b,
+   (Tuple.Phi a, IsType b,
     Num i, IsConst i, IsInteger i, CmpRet i, IsPrimitive i) =>
-   Value i -> Value (Ptr b) -> a ->
-   (Value (Ptr b) -> a -> CodeGenFunction r a) ->
+   Value i -> Value (LLVM.Ptr b) -> a ->
+   (Value (LLVM.Ptr b) -> a -> CodeGenFunction r a) ->
    CodeGenFunction r a
 arrayLoop len ptr start loopBody =
    fmap snd $
@@ -63,10 +63,10 @@
          (loopBody p s)
 
 arrayLoop2 ::
-   (Phi s, IsType a, IsType b,
+   (Tuple.Phi s, IsType a, IsType b,
     Num i, IsConst i, IsInteger i, CmpRet i, IsPrimitive i) =>
-   Value i -> Value (Ptr a) -> Value (Ptr b) -> s ->
-   (Value (Ptr a) -> Value (Ptr b) -> s -> CodeGenFunction r s) ->
+   Value i -> Value (LLVM.Ptr a) -> Value (LLVM.Ptr b) -> s ->
+   (Value (LLVM.Ptr a) -> Value (LLVM.Ptr b) -> s -> CodeGenFunction r s) ->
    CodeGenFunction r s
 arrayLoop2 len ptrA ptrB start loopBody =
    fmap snd $
@@ -78,10 +78,10 @@
 
 
 arrayLoopWithExit ::
-   (Phi s, IsType a,
+   (Tuple.Phi s, IsType a,
     Num i, IsConst i, IsInteger i, CmpRet i, IsPrimitive i) =>
-   Value i -> Value (Ptr a) -> s ->
-   (Value (Ptr a) -> s -> CodeGenFunction r (Value Bool, s)) ->
+   Value i -> Value (LLVM.Ptr a) -> s ->
+   (Value (LLVM.Ptr a) -> s -> CodeGenFunction r (Value Bool, s)) ->
    CodeGenFunction r (Value i, s)
 arrayLoopWithExit len ptr start loopBody = do
    ((_, vars), (i,_)) <-
@@ -106,10 +106,10 @@
 than manual decrement, zero test and conditional branch.
 -}
 _arrayLoopWithExitDecLoop ::
-   (Phi a, IsType b,
+   (Tuple.Phi a, IsType b,
     Num i, IsConst i, IsInteger i, CmpRet i, IsPrimitive i) =>
-   Value i -> Value (Ptr b) -> a ->
-   (Value (Ptr b) -> a -> CodeGenFunction r (Value Bool, a)) ->
+   Value i -> Value (LLVM.Ptr b) -> a ->
+   (Value (LLVM.Ptr b) -> a -> CodeGenFunction r (Value Bool, a)) ->
    CodeGenFunction r (Value i, a)
 _arrayLoopWithExitDecLoop len ptr start loopBody = do
    top <- getCurrentBasicBlock
@@ -126,14 +126,14 @@
    defineBasicBlock checkEnd
    i <- phi [(len, top)]
    p <- phi [(ptr, top)]
-   vars <- phis top start
+   vars <- Tuple.phi top start
    t <- phi [(t0, top)]
    condBr t loop exit
 
    defineBasicBlock loop
 
    (cont, vars') <- loopBody p vars
-   addPhis next vars vars'
+   Tuple.addPhi next vars vars'
    condBr cont next exit
 
    defineBasicBlock next
@@ -152,10 +152,10 @@
 
 
 arrayLoop2WithExit ::
-   (Phi s, IsType a, IsType b,
+   (Tuple.Phi s, IsType a, IsType b,
     Num i, IsConst i, IsInteger i, CmpRet i, IsPrimitive i) =>
-   Value i -> Value (Ptr a) -> Value (Ptr b) -> s ->
-   (Value (Ptr a) -> Value (Ptr b) -> s -> CodeGenFunction r (Value Bool, s)) ->
+   Value i -> Value (LLVM.Ptr a) -> Value (LLVM.Ptr b) -> s ->
+   (Value (LLVM.Ptr a) -> Value (LLVM.Ptr b) -> s -> CodeGenFunction r (Value Bool, s)) ->
    CodeGenFunction r (Value i, s)
 arrayLoop2WithExit len ptrA ptrB start loopBody =
    fmap (mapSnd snd) $
@@ -167,7 +167,7 @@
 
 
 fixedLengthLoop ::
-   (Phi s,
+   (Tuple.Phi s,
     Num i, IsConst i, IsInteger i, CmpRet i, IsPrimitive i) =>
    Value i -> s ->
    (s -> CodeGenFunction r s) ->
@@ -180,7 +180,7 @@
 
 
 whileLoop, _whileLoop ::
-   Phi a =>
+   Tuple.Phi a =>
    a ->
    (a -> CodeGenFunction r (Value Bool)) ->
    (a -> CodeGenFunction r a) ->
@@ -198,13 +198,13 @@
    br loop
 
    defineBasicBlock loop
-   state <- phis top start
+   state <- Tuple.phi top start
    b <- check state
    condBr b cont exit
    defineBasicBlock cont
    res <- body state
    cont' <- getCurrentBasicBlock
-   addPhis cont' state res
+   Tuple.addPhi cont' state res
    br loop
 
    defineBasicBlock exit
@@ -216,7 +216,7 @@
 The @Bool@ value indicates whether the loop shall be continued.
 -}
 loopWithExit ::
-   Phi a =>
+   Tuple.Phi a =>
    a ->
    (a -> CodeGenFunction r (Value Bool, b)) ->
    (b -> CodeGenFunction r a) ->
@@ -229,13 +229,13 @@
    br loop
 
    defineBasicBlock loop
-   state <- phis top start
+   state <- Tuple.phi top start
    (contB,b) <- check state
    condBr contB cont exit
    defineBasicBlock cont
    a <- body b
    cont' <- getCurrentBasicBlock
-   addPhis cont' state a
+   Tuple.addPhi cont' state a
    br loop
 
    defineBasicBlock exit
@@ -248,7 +248,7 @@
 for both loop condition and loop body.
 -}
 whileLoopShared ::
-   Phi a =>
+   Tuple.Phi a =>
    a ->
    (a ->
       (CodeGenFunction r (Value Bool),
@@ -264,7 +264,7 @@
 so be prepared when continueing after an 'ifThenElse'.
 -}
 ifThenElse ::
-   Phi a =>
+   Tuple.Phi a =>
    Value Bool ->
    CodeGenFunction r a ->
    CodeGenFunction r a ->
@@ -286,13 +286,13 @@
    br mergeBlock
 
    defineBasicBlock mergeBlock
-   a2 <- phis thenBlock' a0
-   addPhis elseBlock' a2 a1
+   a2 <- Tuple.phi thenBlock' a0
+   Tuple.addPhi elseBlock' a2 a1
    return a2
 
 
 ifThen ::
-   Phi a =>
+   Tuple.Phi a =>
    Value Bool ->
    a ->
    CodeGenFunction r a ->
@@ -309,12 +309,12 @@
    br mergeBlock
 
    defineBasicBlock mergeBlock
-   a1 <- phis defltBlock deflt
-   addPhis thenBlock' a1 a0
+   a1 <- Tuple.phi defltBlock deflt
+   Tuple.addPhi thenBlock' a1 a0
    return a1
 
 
-class Phi a => Select a where
+class Tuple.Phi a => Select a where
    select :: Value Bool -> a -> a -> CodeGenFunction r a
 
 instance (CmpRet a, IsPrimitive a) => Select (Value a) where
@@ -359,6 +359,15 @@
 ifThenSelect cond deflt thenCode = do
    thenResult <- thenCode
    select cond thenResult deflt
+
+
+-- * return with better type inference
+
+ret :: Value a -> CodeGenFunction a ()
+ret = LLVM.ret
+
+retVoid :: CodeGenFunction () ()
+retVoid = LLVM.ret ()
 
 
 -- * debugging
diff --git a/src/LLVM/Extra/Either.hs b/src/LLVM/Extra/Either.hs
--- a/src/LLVM/Extra/Either.hs
+++ b/src/LLVM/Extra/Either.hs
@@ -13,11 +13,11 @@
    ) where
 
 import qualified LLVM.Extra.EitherPrivate as Either
-import LLVM.Extra.Class (Undefined, undefTuple, )
+import qualified LLVM.Extra.Tuple as Tuple
 
 
-left :: (Undefined b) => a -> Either.T a b
-left = Either.left undefTuple
+left :: (Tuple.Undefined b) => a -> Either.T a b
+left = Either.left Tuple.undef
 
-right :: (Undefined a) => b -> Either.T a b
-right = Either.right undefTuple
+right :: (Tuple.Undefined a) => b -> Either.T a b
+right = Either.right Tuple.undef
diff --git a/src/LLVM/Extra/EitherPrivate.hs b/src/LLVM/Extra/EitherPrivate.hs
--- a/src/LLVM/Extra/EitherPrivate.hs
+++ b/src/LLVM/Extra/EitherPrivate.hs
@@ -1,11 +1,11 @@
 {-# LANGUAGE TypeFamilies #-}
 module LLVM.Extra.EitherPrivate where
 
+import qualified LLVM.Extra.TuplePrivate as Tuple
 import LLVM.Extra.Control (ifThenElse, )
 
 import qualified LLVM.Core as LLVM
 import LLVM.Core (Value, valueOf, CodeGenFunction, )
-import LLVM.Util.Loop (Phi, phis, addPhis, )
 
 import Control.Monad (liftM3, )
 
@@ -19,17 +19,23 @@
 data T a b = Cons {isRight :: Value Bool, fromLeft :: a, fromRight :: b}
 
 
-instance (Phi a, Phi b) => Phi (T a b) where
-   phis bb (Cons r a b) = liftM3 Cons (phis bb r) (phis bb a) (phis bb b)
-   addPhis bb (Cons r0 a0 b0) (Cons r1 a1 b1) =
-      addPhis bb r0 r1 >> addPhis bb a0 a1 >> addPhis bb b0 b1
+instance
+   (Tuple.Undefined a, Tuple.Undefined b) =>
+      Tuple.Undefined (T a b) where
+   undef = Cons Tuple.undef Tuple.undef Tuple.undef
 
+instance (Tuple.Phi a, Tuple.Phi b) => Tuple.Phi (T a b) where
+   phi bb (Cons r a b) =
+      liftM3 Cons (Tuple.phi bb r) (Tuple.phi bb a) (Tuple.phi bb b)
+   addPhi bb (Cons r0 a0 b0) (Cons r1 a1 b1) =
+      Tuple.addPhi bb r0 r1 >> Tuple.addPhi bb a0 a1 >> Tuple.addPhi bb b0 b1
 
+
 {- |
 counterpart to 'either'
 -}
 run ::
-   (Phi c) =>
+   (Tuple.Phi c) =>
    T a b ->
    (a -> CodeGenFunction r c) ->
    (b -> CodeGenFunction r c) ->
diff --git a/src/LLVM/Extra/FastMath.hs b/src/LLVM/Extra/FastMath.hs
--- a/src/LLVM/Extra/FastMath.hs
+++ b/src/LLVM/Extra/FastMath.hs
@@ -1,4 +1,6 @@
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE UndecidableInstances #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 module LLVM.Extra.FastMath ( 
@@ -36,7 +38,7 @@
 import qualified LLVM.Extra.Multi.Vector as MultiVector
 import qualified LLVM.Extra.Multi.Value.Private as MV
 import qualified LLVM.Extra.Arithmetic as A
-import qualified LLVM.Extra.Class as Class
+import qualified LLVM.Extra.Tuple as Tuple
 import qualified LLVM.Core as LLVM
 import LLVM.Util.Proxy (Proxy(Proxy))
 
@@ -91,13 +93,16 @@
 getNumber :: flags -> Number flags a -> a
 getNumber _ (Number a) = a
 
+instance (Tuple.Value a) => Tuple.Value (Number flags a) where
+   type ValueOf (Number flags a) = Tuple.ValueOf a
+   valueOf = Tuple.valueOf . deconsNumber
+
 instance MultiValue a => MV.C (Number flags a) where
-   type Repr f (Number flags a) = MV.Repr f a
    cons = mvNumber . MV.cons . deconsNumber
    undef = mvNumber MV.undef
    zero = mvNumber MV.zero
-   phis bb = fmap mvNumber . MV.phis bb . mvDenumber
-   addPhis bb a b = MV.addPhis bb (mvDenumber a) (mvDenumber b)
+   phi bb = fmap mvNumber . MV.phi bb . mvDenumber
+   addPhi bb a b = MV.addPhi bb (mvDenumber a) (mvDenumber b)
 
 mvNumber :: MV.T a -> MV.T (Number flags a)
 mvNumber (MV.Cons a) = MV.Cons a
@@ -281,12 +286,16 @@
    attachMultiVectorFlags $
       Monad.lift mvecNumber $ f (mvecDenumber a) (mvecDenumber b)
 
+instance (Tuple.VectorValue n a) => Tuple.VectorValue n (Number flags a) where
+   type VectorValueOf n (Number flags a) = Tuple.VectorValueOf n a
+   vectorValueOf = Tuple.vectorValueOf . fmap deconsNumber
+
 instance (Flags flags, MultiVector a) => MultiVector.C (Number flags a) where
    cons = mvecNumber . MultiVector.cons . fmap deconsNumber
    undef = mvecNumber MultiVector.undef
    zero = mvecNumber MultiVector.zero
-   phis bb = fmap mvecNumber . MultiVector.phis bb . mvecDenumber
-   addPhis bb a b = MultiVector.addPhis bb (mvecDenumber a) (mvecDenumber b)
+   phi bb = fmap mvecNumber . MultiVector.phi bb . mvecDenumber
+   addPhi bb a b = MultiVector.addPhi bb (mvecDenumber a) (mvecDenumber b)
    shuffle ks a b =
       fmap mvecNumber $ MultiVector.shuffle ks (mvecDenumber a) (mvecDenumber b)
    extract k = fmap mvNumber . MultiVector.extract k . mvecDenumber
@@ -390,9 +399,9 @@
 proxyFromContext (Context _) = Proxy
 
 instance
-   (Flags flags, Class.Zero a, Tuple a) =>
-      Class.Zero (Context flags a) where
-   zeroTuple = Context Class.zeroTuple
+   (Flags flags, Tuple.Zero a, Tuple a) =>
+      Tuple.Zero (Context flags a) where
+   zero = Context Tuple.zero
 
 instance
    (Flags flags, Tuple a, A.Additive a) =>
diff --git a/src/LLVM/Extra/Iterator.hs b/src/LLVM/Extra/Iterator.hs
--- a/src/LLVM/Extra/Iterator.hs
+++ b/src/LLVM/Extra/Iterator.hs
@@ -15,6 +15,7 @@
    iterate,
    countDown,
    arrayPtrs,
+   storableArrayPtrs,
    -- * modifiers
    mapM,
    mapMaybe,
@@ -33,11 +34,11 @@
 import qualified LLVM.Extra.MaybeContinuation as MaybeCont
 import qualified LLVM.Extra.Maybe as Maybe
 
+import qualified LLVM.Extra.Storable as Storable
 import qualified LLVM.Extra.ArithmeticPrivate as A
-import qualified LLVM.Extra.Class as Class
+import qualified LLVM.Extra.Tuple as Tuple
 import qualified LLVM.Extra.Control as C
 import qualified LLVM.Core as LLVM
-import LLVM.Util.Loop (Phi, )
 import LLVM.Core
    (CodeGenFunction, Value, value, valueOf,
     CmpRet, IsInteger, IsType, IsConst, IsPrimitive)
@@ -60,8 +61,8 @@
 Simulates a non-strict list.
 -}
 data T r a =
-   forall s. (Phi s, Class.Undefined s) =>
-   Cons s (forall z. (Phi z) => s -> MaybeCont.T r z (a,s))
+   forall s. (Tuple.Phi s, Tuple.Undefined s) =>
+   Cons s (forall z. (Tuple.Phi z) => s -> MaybeCont.T r z (a,s))
 
 mapM_ :: (a -> CodeGenFunction r ()) -> T r a -> CodeGenFunction r ()
 mapM_ f (Cons s next) =
@@ -74,7 +75,7 @@
       return
 
 mapState_ ::
-   (Phi t) =>
+   (Tuple.Phi t) =>
    (a -> t -> CodeGenFunction r t) ->
    T r a -> t -> CodeGenFunction r t
 mapState_ f (Cons s next) t =
@@ -87,7 +88,7 @@
       return
 
 mapStateM_ ::
-   (Phi t) =>
+   (Tuple.Phi t) =>
    (a -> MS.StateT t (CodeGenFunction r) ()) ->
    T r a -> MS.StateT t (CodeGenFunction r) ()
 mapStateM_ f xs =
@@ -96,7 +97,7 @@
 
 
 mapWhileState_ ::
-   (Phi t) =>
+   (Tuple.Phi t) =>
    (a -> t -> CodeGenFunction r (Value Bool, t)) ->
    T r a -> t -> CodeGenFunction r t
 mapWhileState_ f (Cons s next) t =
@@ -118,7 +119,7 @@
       (valueOf True)
       (\running -> MaybeCont.guard running >> return (a, valueOf False))
 
-cons :: (Phi a, Class.Undefined a) => a -> T r a -> T r a
+cons :: (Tuple.Phi a, Tuple.Undefined a) => a -> T r a -> T r a
 cons a0 (Cons s next) =
    Cons Maybe.nothing
       (fmap (mapSnd Maybe.just) .
@@ -154,11 +155,11 @@
 mapM f (Cons s next) = Cons s (MaybeCont.lift . FuncHT.mapFst f <=< next)
 
 mapMaybe ::
-   (Phi b, Class.Undefined b) =>
+   (Tuple.Phi b, Tuple.Undefined b) =>
    (a -> CodeGenFunction r (Maybe.T b)) -> T r a -> T r b
 mapMaybe f = catMaybes . mapM f
 
-catMaybes :: (Phi a, Class.Undefined a) => T r (Maybe.T a) -> T r a
+catMaybes :: (Tuple.Phi a, Tuple.Undefined a) => T r (Maybe.T a) -> T r a
 catMaybes (Cons s next) =
    Cons s
       (\s0 ->
@@ -188,12 +189,12 @@
 make sure that accessing one more pointer is legal.
 -}
 iterate ::
-   (Phi a, Class.Undefined a) => (a -> CodeGenFunction r a) -> a -> T r a
+   (Tuple.Phi a, Tuple.Undefined a) => (a -> CodeGenFunction r a) -> a -> T r a
 iterate f a = Cons a (\a0 -> MaybeCont.lift $ fmap ((,) a0) $ f a0)
 
 
 cartesianAux ::
-   (Phi a, Phi b, Class.Undefined a, Class.Undefined b) =>
+   (Tuple.Phi a, Tuple.Phi b, Tuple.Undefined a, Tuple.Undefined b) =>
    T r a -> T r b -> T r (Maybe.T (a,b))
 cartesianAux (Cons sa nextA) (Cons sb nextB) =
    Cons (Maybe.nothing,sa,sb)
@@ -209,7 +210,7 @@
                   return (Maybe.just (a1,b1), (Maybe.just a1, sa1, sb1))))
 
 cartesian ::
-   (Phi a, Phi b, Class.Undefined a, Class.Undefined b) =>
+   (Tuple.Phi a, Tuple.Phi b, Tuple.Undefined a, Tuple.Undefined b) =>
    T r a -> T r b -> T r (a,b)
 cartesian as bs = catMaybes $ cartesianAux as bs
 
@@ -224,14 +225,17 @@
    Value i -> T r a -> T r a
 take len xs = liftA2 const xs (countDown len)
 
-arrayPtrs :: (IsType a) => Value (Ptr a) -> T r (Value (Ptr a))
+arrayPtrs :: (IsType a) => Value (LLVM.Ptr a) -> T r (Value (LLVM.Ptr a))
 arrayPtrs = iterate A.advanceArrayElementPtr
 
+storableArrayPtrs :: (Storable.C a) => Value (Ptr a) -> T r (Value (Ptr a))
+storableArrayPtrs = iterate Storable.incrementPtr
 
+
 -- * examples
 
 fixedLengthLoop ::
-   (Phi s, Num i, IsConst i, IsInteger i, CmpRet i, IsPrimitive i) =>
+   (Tuple.Phi s, Num i, IsConst i, IsInteger i, CmpRet i, IsPrimitive i) =>
    Value i -> s ->
    (s -> CodeGenFunction r s) ->
    CodeGenFunction r s
@@ -239,17 +243,17 @@
    mapState_ (const loopBody) (countDown len) start
 
 arrayLoop ::
-   (Phi a, IsType b, Num i, IsConst i, IsInteger i, CmpRet i, IsPrimitive i) =>
-   Value i -> Value (Ptr b) -> a ->
-   (Value (Ptr b) -> a -> CodeGenFunction r a) ->
+   (Tuple.Phi a, IsType b, Num i, IsConst i, IsInteger i, CmpRet i, IsPrimitive i) =>
+   Value i -> Value (LLVM.Ptr b) -> a ->
+   (Value (LLVM.Ptr b) -> a -> CodeGenFunction r a) ->
    CodeGenFunction r a
 arrayLoop len ptr start loopBody =
    mapState_ loopBody (take len $ arrayPtrs ptr) start
 
 arrayLoopWithExit ::
-   (Phi s, IsType a, Num i, IsConst i, IsInteger i, CmpRet i, IsPrimitive i) =>
-   Value i -> Value (Ptr a) -> s ->
-   (Value (Ptr a) -> s -> CodeGenFunction r (Value Bool, s)) ->
+   (Tuple.Phi s, IsType a, Num i, IsConst i, IsInteger i, CmpRet i, IsPrimitive i) =>
+   Value i -> Value (LLVM.Ptr a) -> s ->
+   (Value (LLVM.Ptr a) -> s -> CodeGenFunction r (Value Bool, s)) ->
    CodeGenFunction r (Value i, s)
 arrayLoopWithExit len ptr0 start loopBody = do
    (i, end) <-
@@ -261,9 +265,9 @@
    return (pos, end)
 
 arrayLoop2 ::
-   (Phi s, IsType a, IsType b, Num i, IsConst i, IsInteger i, CmpRet i, IsPrimitive i) =>
-   Value i -> Value (Ptr a) -> Value (Ptr b) -> s ->
-   (Value (Ptr a) -> Value (Ptr b) -> s -> CodeGenFunction r s) ->
+   (Tuple.Phi s, IsType a, IsType b, Num i, IsConst i, IsInteger i, CmpRet i, IsPrimitive i) =>
+   Value i -> Value (LLVM.Ptr a) -> Value (LLVM.Ptr b) -> s ->
+   (Value (LLVM.Ptr a) -> Value (LLVM.Ptr b) -> s -> CodeGenFunction r s) ->
    CodeGenFunction r s
 arrayLoop2 len ptrA ptrB start loopBody =
    mapState_ (uncurry loopBody)
diff --git a/src/LLVM/Extra/Marshal.hs b/src/LLVM/Extra/Marshal.hs
--- a/src/LLVM/Extra/Marshal.hs
+++ b/src/LLVM/Extra/Marshal.hs
@@ -1,180 +1,264 @@
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE UndecidableInstances #-}
 {- |
 Transfer values between Haskell and JIT generated code
 in an LLVM-compatible format.
-E.g. 'Bool' is stored as 'i1' and Haskell tuples are stored as LLVM structs.
+E.g. 'Bool' is stored as 'i1' and occupies a byte,
+@'Vector' n 'Bool'@ is stored as a bit vector,
+@'Vector' n 'Word8'@ is stored in an order depending on machine endianess,
+and Haskell tuples are stored as LLVM structs.
 -}
-module LLVM.Extra.Marshal where
+module LLVM.Extra.Marshal (
+   C(..),
+   Struct,
+   peek,
+   poke,
+   MV,
 
-import qualified LLVM.Extra.Class as Class
-import qualified LLVM.Util.Proxy as LP
+   VectorStruct,
+   Vector(..),
+
+   with,
+   EE.alloca,
+   ) where
+
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Memory as Memory
+import qualified LLVM.Extra.Tuple as Tuple
 import qualified LLVM.ExecutionEngine as EE
 import qualified LLVM.Core as LLVM
-import LLVM.Core (CodeGenFunction, Value)
 
 import qualified Type.Data.Num.Decimal as TypeNum
 
+import qualified Control.Functor.HT as FuncHT
 import Control.Applicative (liftA2, liftA3, (<$>))
 
-import Foreign.Marshal.Alloc (allocaBytes)
-import Foreign.Ptr (Ptr)
+import Foreign.Storable (Storable)
+import Foreign.StablePtr (StablePtr)
+import Foreign.Ptr (FunPtr, Ptr)
 
-import Data.Tuple.HT (fst3, snd3, thd3)
-import Data.Word (Word8, Word16, Word32, Word64, )
-import Data.Int  (Int8,  Int16,  Int32,  Int64, )
+import Data.Word (Word8, Word16, Word32, Word64, Word)
+import Data.Int  (Int8,  Int16,  Int32,  Int64)
 
 
 
-peek :: (C a, Struct a ~ struct, EE.Marshal struct) => Ptr struct -> IO a
+peek ::
+   (C a, Struct a ~ struct, EE.Marshal struct) => LLVM.Ptr struct -> IO a
 peek ptr = unpack <$> EE.peek ptr
 
-poke :: (C a, Struct a ~ struct, EE.Marshal struct) => Ptr struct -> a -> IO ()
+poke ::
+   (C a, Struct a ~ struct, EE.Marshal struct) => LLVM.Ptr struct -> a -> IO ()
 poke ptr = EE.poke ptr . pack
 
-load ::
-   (C a, Struct a ~ struct, EE.Marshal struct) =>
-   LP.Proxy a ->
-   Value (Ptr struct) -> CodeGenFunction r (Class.ValueTuple a)
-load proxy ptr  =  decompose proxy =<< LLVM.load ptr
 
-store ::
-   (C a, Struct a ~ struct, EE.Marshal struct) =>
-   LP.Proxy a ->
-   Class.ValueTuple a -> Value (Ptr struct) -> CodeGenFunction r ()
-store proxy tuple ptr  =  flip LLVM.store ptr =<< compose proxy tuple
-
+type Struct a = Memory.Struct (Tuple.ValueOf a)
 
 class
-   (Class.MakeValueTuple a, EE.Marshal (Struct a), LLVM.IsSized (Struct a)) =>
+   (Tuple.Value a, Memory.C (Tuple.ValueOf a),
+    EE.Marshal (Struct a), LLVM.IsSized (Struct a)) =>
       C a where
-   type Struct a
    pack :: a -> Struct a
    unpack :: Struct a -> a
-   compose ::
-      LP.Proxy a ->
-      Class.ValueTuple a -> CodeGenFunction r (Value (Struct a))
-   decompose ::
-      LP.Proxy a ->
-      Value (Struct a) -> CodeGenFunction r (Class.ValueTuple a)
 
-instance C Bool where
-   type Struct Bool = Bool
-   pack   = id; compose   LP.Proxy = return
-   unpack = id; decompose LP.Proxy = return
+instance C Bool   where pack = id; unpack = id
+instance C Float  where pack = id; unpack = id
+instance C Double where pack = id; unpack = id
+instance C Word   where pack = id; unpack = id
+instance C Word8  where pack = id; unpack = id
+instance C Word16 where pack = id; unpack = id
+instance C Word32 where pack = id; unpack = id
+instance C Word64 where pack = id; unpack = id
+instance C Int    where pack = id; unpack = id
+instance C Int8   where pack = id; unpack = id
+instance C Int16  where pack = id; unpack = id
+instance C Int32  where pack = id; unpack = id
+instance C Int64  where pack = id; unpack = id
 
-instance C Float where
-   type Struct Float = Float
-   pack   = id; compose   LP.Proxy = return
-   unpack = id; decompose LP.Proxy = return
+instance (Storable a)        => C (Ptr a)       where pack = id; unpack = id
+instance (LLVM.IsType a)     => C (LLVM.Ptr a)  where pack = id; unpack = id
+instance (LLVM.IsFunction a) => C (FunPtr a)    where pack = id; unpack = id
+instance                        C (StablePtr a) where pack = id; unpack = id
 
-instance C Double where
-   type Struct Double = Double
-   pack   = id; compose   LP.Proxy = return
-   unpack = id; decompose LP.Proxy = return
+instance C () where
+   pack = LLVM.Struct
+   unpack (LLVM.Struct unit) = unit
 
-instance C Word8 where
-   type Struct Word8 = Word8
-   pack   = id; compose   LP.Proxy = return
-   unpack = id; decompose LP.Proxy = return
+instance
+   (LLVM.IsSized (Struct a), LLVM.IsSized (Struct b), C a, C b) =>
+      C (a,b) where
+   pack (a,b) = LLVM.consStruct (pack a) (pack b)
+   unpack = LLVM.uncurryStruct $ \a b -> (unpack a, unpack b)
 
-instance C Word16 where
-   type Struct Word16 = Word16
-   pack   = id; compose   LP.Proxy = return
-   unpack = id; decompose LP.Proxy = return
+instance
+   (LLVM.IsSized (Struct a), LLVM.IsSized (Struct b), LLVM.IsSized (Struct c),
+    C a, C b, C c) =>
+      C (a,b,c) where
+   pack (a,b,c) = LLVM.consStruct (pack a) (pack b) (pack c)
+   unpack = LLVM.uncurryStruct $ \a b c -> (unpack a, unpack b, unpack c)
 
-instance C Word32 where
-   type Struct Word32 = Word32
-   pack   = id; compose   LP.Proxy = return
-   unpack = id; decompose LP.Proxy = return
+instance
+   (LLVM.IsSized (Struct a), LLVM.IsSized (Struct b),
+    LLVM.IsSized (Struct c), LLVM.IsSized (Struct d),
+    C a, C b, C c, C d) =>
+      C (a,b,c,d) where
+   pack (a,b,c,d) = LLVM.consStruct (pack a) (pack b) (pack c) (pack d)
+   unpack =
+      LLVM.uncurryStruct $ \a b c d -> (unpack a, unpack b, unpack c, unpack d)
 
-instance C Word64 where
-   type Struct Word64 = Word64
-   pack   = id; compose   LP.Proxy = return
-   unpack = id; decompose LP.Proxy = return
 
-instance C Int8 where
-   type Struct Int8 = Int8
-   pack   = id; compose   LP.Proxy = return
-   unpack = id; decompose LP.Proxy = return
 
-instance C Int16 where
-   type Struct Int16 = Int16
-   pack   = id; compose   LP.Proxy = return
-   unpack = id; decompose LP.Proxy = return
-
-instance C Int32 where
-   type Struct Int32 = Int32
-   pack   = id; compose   LP.Proxy = return
-   unpack = id; decompose LP.Proxy = return
-
-instance C Int64 where
-   type Struct Int64 = Int64
-   pack   = id; compose   LP.Proxy = return
-   unpack = id; decompose LP.Proxy = return
+type VectorStruct n a = Memory.Struct (Tuple.VectorValueOf n a)
 
-instance (LLVM.IsType a) => C (Ptr a) where
-   type Struct (Ptr a) = Ptr a
-   pack   = id; compose   LP.Proxy = return
-   unpack = id; decompose LP.Proxy = return
+class
+   (TypeNum.Positive n,
+    Tuple.VectorValue n a, Memory.C (Tuple.VectorValueOf n a),
+    EE.Marshal (VectorStruct n a), LLVM.IsSized (VectorStruct n a)) =>
+      Vector n a where
+   packVector :: LLVM.Vector n a -> VectorStruct n a
+   unpackVector :: VectorStruct n a -> LLVM.Vector n a
 
 instance
    (TypeNum.Positive n, TypeNum.Natural (n TypeNum.:*: LLVM.SizeOf a),
-    EE.Marshal a, LLVM.IsConst a, LLVM.IsPrimitive a, LLVM.IsSized a) =>
+    Vector n a) =>
       C (LLVM.Vector n a) where
-   type Struct (LLVM.Vector n a) = LLVM.Vector n a
-   pack   = id; compose   LP.Proxy = return
-   unpack = id; decompose LP.Proxy = return
+   pack = packVector; unpack = unpackVector
 
-instance C () where
-   type Struct () = LLVM.Struct ()
-   pack = LLVM.Struct
-   unpack (LLVM.Struct unit) = unit
-   compose LP.Proxy () = return $ LLVM.valueOf $ LLVM.Struct ()
-   decompose LP.Proxy _ = return ()
 
 instance
-   (LLVM.IsSized (Struct a), LLVM.IsSized (Struct b), C a, C b) =>
-      C (a,b) where
-   type Struct (a,b) = LLVM.Struct (Struct a, (Struct b, ()))
-   pack (a,b) = LLVM.Struct (pack a, (pack b, ()))
-   unpack (LLVM.Struct (a,(b,()))) = (unpack a, unpack b)
-   compose proxy (a,b) = do
-      ac <- compose (fst <$> proxy) a
-      bc <- compose (snd <$> proxy) b
-      struct0 <- LLVM.insertvalue (LLVM.value LLVM.undef) ac TypeNum.d0
-      LLVM.insertvalue struct0 bc TypeNum.d1
-   decompose proxy struct =
-      liftA2 (,)
-         (decompose (fst <$> proxy) =<< LLVM.extractvalue struct TypeNum.d0)
-         (decompose (snd <$> proxy) =<< LLVM.extractvalue struct TypeNum.d1)
+   (TypeNum.Positive n, TypeNum.Natural (n TypeNum.:*: TypeNum.D1)) =>
+      Vector n Bool where
+   packVector = id
+   unpackVector = id
 
 instance
+   (TypeNum.Positive n, TypeNum.Natural (n TypeNum.:*: TypeNum.D32)) =>
+      Vector n Float where
+   packVector = id
+   unpackVector = id
+
+instance
+   (TypeNum.Positive n, TypeNum.Natural (n TypeNum.:*: TypeNum.D64)) =>
+      Vector n Double where
+   packVector = id
+   unpackVector = id
+
+instance
+   (TypeNum.Positive n, TypeNum.Natural (n TypeNum.:*: LLVM.IntSize)) =>
+      Vector n Word where
+   packVector = id
+   unpackVector = id
+
+instance
+   (TypeNum.Positive n, TypeNum.Natural (n TypeNum.:*: TypeNum.D8)) =>
+      Vector n Word8 where
+   packVector = id
+   unpackVector = id
+
+instance
+   (TypeNum.Positive n, TypeNum.Natural (n TypeNum.:*: TypeNum.D16)) =>
+      Vector n Word16 where
+   packVector = id
+   unpackVector = id
+
+instance
+   (TypeNum.Positive n, TypeNum.Natural (n TypeNum.:*: TypeNum.D32)) =>
+      Vector n Word32 where
+   packVector = id
+   unpackVector = id
+
+instance
+   (TypeNum.Positive n, TypeNum.Natural (n TypeNum.:*: TypeNum.D64)) =>
+      Vector n Word64 where
+   packVector = id
+   unpackVector = id
+
+instance
+   (TypeNum.Positive n, TypeNum.Natural (n TypeNum.:*: LLVM.IntSize)) =>
+      Vector n Int where
+   packVector = id
+   unpackVector = id
+
+instance
+   (TypeNum.Positive n, TypeNum.Natural (n TypeNum.:*: TypeNum.D8)) =>
+      Vector n Int8 where
+   packVector = id
+   unpackVector = id
+
+instance
+   (TypeNum.Positive n, TypeNum.Natural (n TypeNum.:*: TypeNum.D16)) =>
+      Vector n Int16 where
+   packVector = id
+   unpackVector = id
+
+instance
+   (TypeNum.Positive n, TypeNum.Natural (n TypeNum.:*: TypeNum.D32)) =>
+      Vector n Int32 where
+   packVector = id
+   unpackVector = id
+
+instance
+   (TypeNum.Positive n, TypeNum.Natural (n TypeNum.:*: TypeNum.D64)) =>
+      Vector n Int64 where
+   packVector = id
+   unpackVector = id
+
+instance (Vector n a, Vector n b) => Vector n (a,b) where
+   packVector x =
+      case FuncHT.unzip x of
+         (a,b) -> LLVM.consStruct (packVector a) (packVector b)
+   unpackVector = LLVM.uncurryStruct $ \a b ->
+      liftA2 (,) (unpackVector a) (unpackVector b)
+
+instance (Vector n a, Vector n b, Vector n c) => Vector n (a,b,c) where
+   packVector x =
+      case FuncHT.unzip3 x of
+         (a,b,c) -> LLVM.consStruct (packVector a) (packVector b) (packVector c)
+   unpackVector = LLVM.uncurryStruct $ \a b c ->
+      liftA3 (,,) (unpackVector a) (unpackVector b) (unpackVector c)
+
+
+
+class (C a, MultiValue.C a) => MV a where
+
+instance MV Float  where
+instance MV Double where
+instance MV Word   where
+instance MV Word8  where
+instance MV Word16 where
+instance MV Word32 where
+instance MV Word64 where
+instance MV Int    where
+instance MV Int8   where
+instance MV Int16  where
+instance MV Int32  where
+instance MV Int64  where
+
+instance (Storable a)        => MV (Ptr a)       where
+instance (LLVM.IsType a)     => MV (LLVM.Ptr a)  where
+instance (LLVM.IsFunction a) => MV (FunPtr a)    where
+instance                        MV (StablePtr a) where
+
+instance MV () where
+
+instance
+   (LLVM.IsSized (Struct a), LLVM.IsSized (Struct b), MV a, MV b) =>
+      MV (a,b) where
+
+instance
    (LLVM.IsSized (Struct a), LLVM.IsSized (Struct b), LLVM.IsSized (Struct c),
-    C a, C b, C c) =>
-      C (a,b,c) where
-   type Struct (a,b,c) = LLVM.Struct (Struct a, (Struct b, (Struct c, ())))
-   pack (a,b,c) = LLVM.Struct (pack a, (pack b, (pack c, ())))
-   unpack (LLVM.Struct (a,(b,(c,())))) = (unpack a, unpack b, unpack c)
-   compose proxy (a,b,c) = do
-      ac <- compose (fst3 <$> proxy) a
-      bc <- compose (snd3 <$> proxy) b
-      cc <- compose (thd3 <$> proxy) c
-      struct0 <- LLVM.insertvalue (LLVM.value LLVM.undef) ac TypeNum.d0
-      struct1 <- LLVM.insertvalue struct0 bc TypeNum.d1
-      LLVM.insertvalue struct1 cc TypeNum.d2
-   decompose proxy struct =
-      liftA3 (,,)
-         (decompose (fst3 <$> proxy) =<< LLVM.extractvalue struct TypeNum.d0)
-         (decompose (snd3 <$> proxy) =<< LLVM.extractvalue struct TypeNum.d1)
-         (decompose (thd3 <$> proxy) =<< LLVM.extractvalue struct TypeNum.d2)
+    MV a, MV b, MV c) =>
+      MV (a,b,c) where
 
+instance
+   (LLVM.IsSized (Struct a), LLVM.IsSized (Struct b),
+    LLVM.IsSized (Struct c), LLVM.IsSized (Struct d),
+    MV a, MV b, MV c, MV d) =>
+      MV (a,b,c,d) where
 
-with :: (C a) => a -> (Ptr (Struct a) -> IO b) -> IO b
-with a act = alloca LP.Proxy $ \ptr -> poke ptr a >> act ptr
 
-alloca ::
-   (LLVM.IsType struct) => LP.Proxy struct -> (Ptr struct -> IO b) -> IO b
-alloca proxy = allocaBytes (EE.sizeOf proxy)
+with :: (C a) => a -> (LLVM.Ptr (Struct a) -> IO b) -> IO b
+with a act = EE.alloca $ \ptr -> poke ptr a >> act ptr
diff --git a/src/LLVM/Extra/Maybe.hs b/src/LLVM/Extra/Maybe.hs
--- a/src/LLVM/Extra/Maybe.hs
+++ b/src/LLVM/Extra/Maybe.hs
@@ -21,20 +21,19 @@
    loopWithExit,
    ) where
 
+import qualified LLVM.Extra.Tuple as Tuple
 import qualified LLVM.Extra.MaybePrivate as Maybe
 import qualified LLVM.Extra.Control as C
-import LLVM.Extra.Class (Undefined, undefTuple, )
 
-import LLVM.Util.Loop (Phi, )
 import LLVM.Core (CodeGenFunction, )
 
 
-nothing :: (Undefined a) => Maybe.T a
-nothing = Maybe.nothing undefTuple
+nothing :: (Tuple.Undefined a) => Maybe.T a
+nothing = Maybe.nothing Tuple.undef
 
 
 loopWithExit ::
-   Phi a =>
+   Tuple.Phi a =>
    a ->
    (a -> CodeGenFunction r (Maybe.T c, b)) ->
    ((c,b) -> CodeGenFunction r a) ->
diff --git a/src/LLVM/Extra/MaybeContinuation.hs b/src/LLVM/Extra/MaybeContinuation.hs
--- a/src/LLVM/Extra/MaybeContinuation.hs
+++ b/src/LLVM/Extra/MaybeContinuation.hs
@@ -5,23 +5,21 @@
 module LLVM.Extra.MaybeContinuation where
 
 import qualified LLVM.Extra.Maybe as Maybe
+import qualified LLVM.Extra.Tuple as Tuple
 import qualified LLVM.Extra.Arithmetic as A
 import qualified LLVM.Extra.Control as C
 import LLVM.Extra.Control (ifThenElse, )
-import LLVM.Extra.Class (Undefined, undefTuple, )
 
 import qualified LLVM.Core as LLVM
 import LLVM.Core
    (CodeGenFunction, Value, value, valueOf,
     IsConst, IsType, IsPrimitive, IsInteger, CmpRet)
-import LLVM.Util.Loop (Phi, ) -- (phis, addPhis, )
 
 import qualified Control.Monad as M
 import qualified Control.Applicative as App
 import Control.Monad.IO.Class (MonadIO(liftIO), )
 import Control.Monad.HT ((<=<), )
 
-import Foreign.Ptr (Ptr, )
 import Data.Tuple.HT (mapSnd, )
 
 import Prelude hiding (map, )
@@ -62,7 +60,7 @@
 counterpart to Data.Maybe.HT.toMaybe
 -}
 withBool ::
-   (Phi z) =>
+   (Tuple.Phi z) =>
    Value Bool -> CodeGenFunction r a -> T r z a
 withBool b a =
    guard b >> lift a
@@ -72,7 +70,7 @@
 -}
 
 fromBool ::
-   (Phi z) =>
+   (Tuple.Phi z) =>
    CodeGenFunction r (Value Bool, a) ->
    T r z a
 fromBool m = do
@@ -81,20 +79,20 @@
    return a
 
 toBool ::
-   (Undefined a) =>
+   (Tuple.Undefined a) =>
    T r (Value Bool, a) a -> CodeGenFunction r (Value Bool, a)
 toBool (Cons m) =
-   m (return (valueOf False, undefTuple)) (return . (,) (valueOf True))
+   m (return (valueOf False, Tuple.undef)) (return . (,) (valueOf True))
 
 
-fromPlainMaybe :: (Phi z) => Maybe.T a -> T r z a
+fromPlainMaybe :: (Tuple.Phi z) => Maybe.T a -> T r z a
 fromPlainMaybe (Maybe.Cons b a) = guard b >> return a
 
-fromMaybe :: (Phi z) => CodeGenFunction r (Maybe.T a) -> T r z a
+fromMaybe :: (Tuple.Phi z) => CodeGenFunction r (Maybe.T a) -> T r z a
 fromMaybe m = lift m >>= fromPlainMaybe
 
 toMaybe ::
-   (Undefined a) =>
+   (Tuple.Undefined a) =>
    T r (Maybe.T a) a -> CodeGenFunction r (Maybe.T a)
 toMaybe (Cons m) =
    m (return Maybe.nothing) (return . Maybe.just)
@@ -109,7 +107,7 @@
 lift a = Cons $ \ _n j -> j =<< a
 
 guard ::
-   (Phi z) =>
+   (Tuple.Phi z) =>
    Value Bool -> T r z ()
 guard b = Cons $ \n j ->
    ifThenElse b (j ()) n
@@ -140,14 +138,14 @@
 If both actions fail, then the composed action fails, too.
 -}
 alternative ::
-   (Phi z, Undefined a) =>
+   (Tuple.Phi z, Tuple.Undefined a) =>
    T r (Maybe.T a) a -> T r (Maybe.T a) a -> T r z a
 alternative x y =
    fromMaybe $ resolve x (toMaybe y) (return . Maybe.just)
 
 
 fixedLengthLoop ::
-   (Phi s, Undefined s,
+   (Tuple.Phi s, Tuple.Undefined s,
     Num i, IsConst i, IsInteger i, CmpRet i, IsPrimitive i) =>
    Value i -> s ->
    (s -> T r (Maybe.T s) s) ->
@@ -172,11 +170,11 @@
 then returned final state is 'Maybe.nothing'.
 -}
 arrayLoop ::
-   (Phi s, Undefined s, IsType a,
+   (Tuple.Phi s, Tuple.Undefined s, IsType a,
     Num i, IsConst i, IsInteger i, CmpRet i, IsPrimitive i) =>
    Value i ->
-   Value (Ptr a) -> s ->
-   (Value (Ptr a) -> s -> T r (Maybe.T (Value (Ptr a), s)) s) ->
+   Value (LLVM.Ptr a) -> s ->
+   (Value (LLVM.Ptr a) -> s -> T r (Maybe.T (Value (LLVM.Ptr a), s)) s) ->
    CodeGenFunction r (Value i, Maybe.T s)
 arrayLoop len ptr start loopBody =
    fmap (mapSnd (fmap snd)) $
@@ -187,12 +185,12 @@
 
 
 arrayLoop2 ::
-   (Phi s, Undefined s, IsType a, IsType b,
+   (Tuple.Phi s, Tuple.Undefined s, IsType a, IsType b,
     Num i, IsConst i, IsInteger i, CmpRet i, IsPrimitive i) =>
    Value i ->
-   Value (Ptr a) -> Value (Ptr b) -> s ->
-   (Value (Ptr a) -> Value (Ptr b) -> s ->
-      T r (Maybe.T (Value (Ptr a), (Value (Ptr b), s))) s) ->
+   Value (LLVM.Ptr a) -> Value (LLVM.Ptr b) -> s ->
+   (Value (LLVM.Ptr a) -> Value (LLVM.Ptr b) -> s ->
+      T r (Maybe.T (Value (LLVM.Ptr a), (Value (LLVM.Ptr b), s))) s) ->
    CodeGenFunction r (Value i, Maybe.T s)
 arrayLoop2 len ptrA ptrB start loopBody =
    fmap (mapSnd (fmap snd)) $
@@ -208,7 +206,7 @@
 and we could just propagate a Nothing.
 
 whileLoop ::
-   Phi a =>
+   Tuple.Phi a =>
    a ->
    (a -> T r z a) ->
    CodeGenFunction r a
@@ -220,13 +218,13 @@
    br loop
 
    defineBasicBlock loop
-   state <- phis top start
+   state <- phi top start
    b <- check state
    condBr b cont exit
    defineBasicBlock cont
    res <- body state
    cont' <- getCurrentBasicBlock
-   addPhis cont' state res
+   addPhi cont' state res
    br loop
 
    defineBasicBlock exit
diff --git a/src/LLVM/Extra/MaybePrivate.hs b/src/LLVM/Extra/MaybePrivate.hs
--- a/src/LLVM/Extra/MaybePrivate.hs
+++ b/src/LLVM/Extra/MaybePrivate.hs
@@ -1,12 +1,12 @@
 {-# LANGUAGE TypeFamilies #-}
 module LLVM.Extra.MaybePrivate where
 
+import qualified LLVM.Extra.TuplePrivate as Tuple
 import qualified LLVM.Extra.Control as C
 import LLVM.Extra.Control (ifThenElse, )
 
 import qualified LLVM.Core as LLVM
 import LLVM.Core (Value, valueOf, CodeGenFunction, )
-import LLVM.Util.Loop (Phi, phis, addPhis, )
 
 import qualified Control.Monad as Monad
 
@@ -22,17 +22,20 @@
 instance Functor T where
    fmap f (Cons b a) = Cons b (f a)
 
-instance (Phi a) => Phi (T a) where
-   phis bb (Cons b a) = Monad.liftM2 Cons (phis bb b) (phis bb a)
-   addPhis bb (Cons b0 a0) (Cons b1 a1) =
-      addPhis bb b0 b1 >> addPhis bb a0 a1
+instance (Tuple.Undefined a) => Tuple.Undefined (T a) where
+   undef = Cons Tuple.undef Tuple.undef
 
+instance (Tuple.Phi a) => Tuple.Phi (T a) where
+   phi bb (Cons b a) = Monad.liftM2 Cons (Tuple.phi bb b) (Tuple.phi bb a)
+   addPhi bb (Cons b0 a0) (Cons b1 a1) =
+      Tuple.addPhi bb b0 b1 >> Tuple.addPhi bb a0 a1
 
+
 {- |
 counterpart to 'maybe'
 -}
 run ::
-   (Phi b) =>
+   (Tuple.Phi b) =>
    T a ->
    CodeGenFunction r b ->
    (a -> CodeGenFunction r b) ->
@@ -106,7 +109,7 @@
 
 
 maybeArg ::
-   (Phi b) =>
+   (Tuple.Phi b) =>
    b ->
    (a -> CodeGenFunction r (T b)) ->
    T a -> CodeGenFunction r (T b)
diff --git a/src/LLVM/Extra/Memory.hs b/src/LLVM/Extra/Memory.hs
--- a/src/LLVM/Extra/Memory.hs
+++ b/src/LLVM/Extra/Memory.hs
@@ -1,34 +1,31 @@
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE UndecidableInstances #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE FlexibleContexts #-}
 module LLVM.Extra.Memory (
-   C(load, store, decompose, compose), modify, castStorablePtr, castTuplePtr,
+   C(load, store, decompose, compose), modify,
    Struct,
    Record, Element, element,
    loadRecord, storeRecord, decomposeRecord, composeRecord,
    loadNewtype, storeNewtype, decomposeNewtype, composeNewtype,
-   FirstClass, Stored,
    ) where
 
-import LLVM.Extra.Class (MakeValueTuple, ValueTuple, Undefined, )
 import LLVM.Extra.MemoryPrivate (decomposeFromLoad, composeFromStore, )
 
-import qualified LLVM.Extra.Multi.Vector.Memory as MultiVectorMemory
-import qualified LLVM.Extra.Multi.Value.Memory as MultiValueMemory
 import qualified LLVM.Extra.Multi.Vector as MultiVector
 import qualified LLVM.Extra.Multi.Value as MultiValue
 import qualified LLVM.Extra.ArithmeticPrivate as A
 import qualified LLVM.Extra.Vector as Vector
 import qualified LLVM.Extra.Scalar as Scalar
 import qualified LLVM.Extra.Array as Array
+import qualified LLVM.Extra.Tuple as Tuple
 import qualified LLVM.Extra.Either as Either
 import qualified LLVM.Extra.Maybe as Maybe
 
 import qualified LLVM.Util.Proxy as LP
 import qualified LLVM.Core as LLVM
-import LLVM.Util.Loop (Phi, )
 import LLVM.Core
    (getElementPtr0,
     extractvalue, insertvalue,
@@ -37,27 +34,30 @@
     CodeGenFunction, )
 
 import qualified Type.Data.Num.Decimal as TypeNum
-import Type.Data.Num.Decimal (d0, d1, d2, )
+import qualified Type.Data.Num.Unary as Unary
+import Type.Data.Num.Decimal (d0, d1, d2, d3)
 import Type.Base.Proxy (Proxy(Proxy), )
 
 import Foreign.StablePtr (StablePtr, )
-import Foreign.Ptr (FunPtr, Ptr, castPtr, )
+import Foreign.Ptr (FunPtr)
 
-import Data.Word (Word8, Word16, Word32, Word64, )
+import qualified Data.Traversable as Trav
+import qualified Data.Foldable as Fold
+import qualified Data.FixedLength as FixedLength
+import Data.Tuple.HT (fst3, snd3, thd3, )
+import Data.Word (Word8, Word16, Word32, Word64, Word)
 import Data.Int  (Int8,  Int16,  Int32,  Int64, )
 
-import qualified Control.Applicative as App
-import Control.Monad (ap, )
-import Control.Applicative (pure, liftA2, liftA3, )
-
-import Data.Tuple.HT (fst3, snd3, thd3, )
+import qualified Control.Applicative.HT as App
+import Control.Monad (ap, (<=<))
+import Control.Applicative (Applicative, pure, liftA2, liftA3, (<*>))
 
 import Prelude2010 hiding (maybe, either, )
 import Prelude ()
 
 
 {- |
-An implementation of both 'MakeValueTuple' and 'Memory.C'
+An implementation of both 'Tuple.Value' and 'Memory.C'
 must ensure that @haskellValue@ is compatible
 with @Stored (Struct haskellValue)@ (which we want to call @llvmStruct@).
 That is, writing and reading @llvmStruct@ by LLVM
@@ -66,13 +66,13 @@
 
 We use a functional dependency in order to let type inference work nicely.
 -}
-class (Phi llvmValue, Undefined llvmValue, IsType (Struct llvmValue), IsSized (Struct llvmValue)) =>
+class (Tuple.Phi llvmValue, Tuple.Undefined llvmValue, IsType (Struct llvmValue), IsSized (Struct llvmValue)) =>
       C llvmValue where
    {-# MINIMAL (load|decompose), (store|compose) #-}
    type Struct llvmValue :: *
-   load :: Value (Ptr (Struct llvmValue)) -> CodeGenFunction r llvmValue
+   load :: Value (LLVM.Ptr (Struct llvmValue)) -> CodeGenFunction r llvmValue
    load ptr  =  decompose =<< LLVM.load ptr
-   store :: llvmValue -> Value (Ptr (Struct llvmValue)) -> CodeGenFunction r ()
+   store :: llvmValue -> Value (LLVM.Ptr (Struct llvmValue)) -> CodeGenFunction r ()
    store r ptr  =  flip LLVM.store ptr =<< compose r
    decompose :: Value (Struct llvmValue) -> CodeGenFunction r llvmValue
    decompose = decomposeFromLoad load
@@ -82,7 +82,7 @@
 modify ::
    (C llvmValue) =>
    (llvmValue -> CodeGenFunction r llvmValue) ->
-   Value (Ptr (Struct llvmValue)) -> CodeGenFunction r ()
+   Value (LLVM.Ptr (Struct llvmValue)) -> CodeGenFunction r ()
 modify f ptr =
    flip store ptr =<< f =<< load ptr
 
@@ -99,8 +99,8 @@
 
 data Element r o v x =
    Element {
-      loadElement :: Value (Ptr o) -> CodeGenFunction r x,
-      storeElement :: Value (Ptr o) -> v -> CodeGenFunction r (),
+      loadElement :: Value (LLVM.Ptr o) -> CodeGenFunction r x,
+      storeElement :: Value (LLVM.Ptr o) -> v -> CodeGenFunction r (),
       extractElement :: Value o -> CodeGenFunction r x,
       insertElement :: v -> Value o -> CodeGenFunction r (Value o)
          -- State.Monoid
@@ -128,7 +128,7 @@
          insertElement = insertElement m
       }
 
-instance App.Applicative (Element r o v) where
+instance Applicative (Element r o v) where
    pure x =
       Element {
          loadElement = \ _ptr -> return x,
@@ -147,12 +147,12 @@
 
 loadRecord ::
    Record r o llvmValue ->
-   Value (Ptr o) -> CodeGenFunction r llvmValue
+   Value (LLVM.Ptr o) -> CodeGenFunction r llvmValue
 loadRecord = loadElement
 
 storeRecord ::
    Record r o llvmValue ->
-   llvmValue -> Value (Ptr o) -> CodeGenFunction r ()
+   llvmValue -> Value (LLVM.Ptr o) -> CodeGenFunction r ()
 storeRecord m y ptr = storeElement m ptr y
 
 decomposeRecord ::
@@ -204,16 +204,58 @@
    compose = composeRecord triple
 
 
+quadruple ::
+   (C a, C b, C c, C d) =>
+   Record r
+      (LLVM.Struct (Struct a, (Struct b, (Struct c, (Struct d, ())))))
+      (a, b, c, d)
+quadruple =
+   App.lift4 (,,,)
+      (element (\(x,_,_,_) -> x) d0)
+      (element (\(_,x,_,_) -> x) d1)
+      (element (\(_,_,x,_) -> x) d2)
+      (element (\(_,_,_,x) -> x) d3)
+
+instance (C a, C b, C c, C d) => C (a, b, c, d) where
+   type Struct (a, b, c, d) =
+           LLVM.Struct (Struct a, (Struct b, (Struct c, (Struct d, ()))))
+   load = loadRecord quadruple
+   store = storeRecord quadruple
+   decompose = decomposeRecord quadruple
+   compose = composeRecord quadruple
+
+
+instance
+   (Unary.Natural n, C a,
+    TypeNum.Natural (TypeNum.FromUnary n),
+    TypeNum.Natural (TypeNum.FromUnary n TypeNum.:*: LLVM.SizeOf (Struct a)),
+    LLVM.IsFirstClass (Struct a)) =>
+      C (FixedLength.T n a) where
+   type Struct (FixedLength.T n a) =
+            LLVM.Array (TypeNum.FromUnary n) (Struct a)
+   compose xs =
+      Fold.foldlM
+         (\arr (x,i) -> compose x >>= \xc -> LLVM.insertvalue arr xc i)
+         (LLVM.value LLVM.undef) $
+      FixedLength.zipWith (,) xs $ iterateTrav (1+) (0::Word64)
+   decompose arr =
+      Trav.mapM (decompose <=< LLVM.extractvalue arr) $
+      iterateTrav (1+) (0::Word64)
+
+iterateTrav :: (Applicative t, Trav.Traversable t) => (a -> a) -> a -> t a
+iterateTrav f a0 = snd $ Trav.mapAccumL (\a () -> (f a, a)) a0 $ pure ()
+
+
 maybe ::
    (C a) =>
-   Record r (LLVM.Struct (Word32, (Struct a, ()))) (Maybe.T a)
+   Record r (LLVM.Struct (Bool, (Struct a, ()))) (Maybe.T a)
 maybe =
    liftA2 Maybe.Cons
       (element Maybe.isJust d0)
       (element Maybe.fromJust d1)
 
 instance (C a) => C (Maybe.T a) where
-   type Struct (Maybe.T a) = LLVM.Struct (Word32, (Struct a, ()))
+   type Struct (Maybe.T a) = LLVM.Struct (Bool, (Struct a, ()))
    load = loadRecord maybe
    store = storeRecord maybe
    decompose = decomposeRecord maybe
@@ -222,7 +264,7 @@
 
 either ::
    (C a, C b) =>
-   Record r (LLVM.Struct (Word32, (Struct a, (Struct b, ())))) (Either.T a b)
+   Record r (LLVM.Struct (Bool, (Struct a, (Struct b, ())))) (Either.T a b)
 either =
    liftA3 Either.Cons
       (element Either.isRight d0)
@@ -230,7 +272,7 @@
       (element Either.fromRight d2)
 
 instance (C a, C b) => C (Either.T a b) where
-   type Struct (Either.T a b) = LLVM.Struct (Word32, (Struct a, (Struct b, ())))
+   type Struct (Either.T a b) = LLVM.Struct (Bool, (Struct a, (Struct b, ())))
    load = loadRecord either
    store = storeRecord either
    decompose = decomposeRecord either
@@ -246,17 +288,12 @@
    compose = composeNewtype Scalar.decons
 
 
-{-
-This would not work for Booleans,
-since on x86 LLVM's @i1@ type uses one byte in memory,
-whereas Storable uses 4 byte and 4 byte alignment.
-
-instance (LLVM.IsFirstClass a) => C (Value a) a where
+instance (IsSized a, LLVM.IsFirstClass a) => C (Value a) where
+   type Struct (Value a) = a
    load = LLVM.load
    store = LLVM.store
    decompose = return
    compose = return
--}
 
 
 class (LLVM.IsFirstClass llvmType, IsType (Stored llvmType)) =>
@@ -267,10 +304,12 @@
 
 instance FirstClass Float  where type Stored Float  = Float  ; fromStorable = return; toStorable = return
 instance FirstClass Double where type Stored Double = Double ; fromStorable = return; toStorable = return
+instance FirstClass Int    where type Stored Int    = Int    ; fromStorable = return; toStorable = return
 instance FirstClass Int8   where type Stored Int8   = Int8   ; fromStorable = return; toStorable = return
 instance FirstClass Int16  where type Stored Int16  = Int16  ; fromStorable = return; toStorable = return
 instance FirstClass Int32  where type Stored Int32  = Int32  ; fromStorable = return; toStorable = return
 instance FirstClass Int64  where type Stored Int64  = Int64  ; fromStorable = return; toStorable = return
+instance FirstClass Word   where type Stored Word   = Word   ; fromStorable = return; toStorable = return
 instance FirstClass Word8  where type Stored Word8  = Word8  ; fromStorable = return; toStorable = return
 instance FirstClass Word16 where type Stored Word16 = Word16 ; fromStorable = return; toStorable = return
 instance FirstClass Word32 where type Stored Word32 = Word32 ; fromStorable = return; toStorable = return
@@ -293,8 +332,8 @@
    fromStorable = Array.map fromStorable
    toStorable = Array.map toStorable
 
-instance (IsType a) => FirstClass (Ptr a) where
-   type Stored (Ptr a) = Ptr a
+instance (IsType a) => FirstClass (LLVM.Ptr a) where
+   type Stored (LLVM.Ptr a) = LLVM.Ptr a
    fromStorable = return; toStorable = return
 instance (LLVM.IsFunction a) => FirstClass (FunPtr a) where
    type Stored (FunPtr a) = FunPtr a
@@ -367,48 +406,35 @@
       return (LLVM.value LLVM.undef)
 
 
-instance (FirstClass a, IsSized (Stored a)) => C (Value a) where
-   type Struct (Value a) = Stored a
-   decompose = fromStorable
-   compose = toStorable
-
-
-instance (MultiValueMemory.C a) => C (MultiValue.T a) where
-   type Struct (MultiValue.T a) = MultiValueMemory.Struct a
-   load      = MultiValueMemory.load
-   store     = MultiValueMemory.store
-   decompose = MultiValueMemory.decompose
-   compose   = MultiValueMemory.compose
-
-
-instance (MultiVectorMemory.C n a) => C (MultiVector.T n a) where
-   type Struct (MultiVector.T n a) = MultiVectorMemory.Struct n a
-   load      = MultiVectorMemory.load
-   store     = MultiVectorMemory.store
-   decompose = MultiVectorMemory.decompose
-   compose   = MultiVectorMemory.compose
-
+instance (MultiValue.C a, C (Tuple.ValueOf a)) => C (MultiValue.T a) where
+   type Struct (MultiValue.T a) = Struct (Tuple.ValueOf a)
+   load = fmap MultiValue.Cons . load
+   store (MultiValue.Cons a) = store a
+   decompose = fmap MultiValue.Cons . decompose
+   compose (MultiValue.Cons a) = compose a
 
-{-# DEPRECATED castStorablePtr "use castTuplePtr instead" #-}
-castStorablePtr, castTuplePtr ::
-   (MakeValueTuple haskellValue, C (ValueTuple haskellValue)) =>
-   Ptr haskellValue -> Ptr (Struct (ValueTuple haskellValue))
-castStorablePtr = castPtr
-castTuplePtr = castPtr
+instance
+   (TypeNum.Positive n, MultiVector.C a, C (Tuple.VectorValueOf n a)) =>
+      C (MultiVector.T n a) where
+   type Struct (MultiVector.T n a) = Struct (Tuple.VectorValueOf n a)
+   load = fmap MultiVector.Cons . load
+   store (MultiVector.Cons a) = store a
+   decompose = fmap MultiVector.Cons . decompose
+   compose (MultiVector.Cons a) = compose a
 
 
 
 loadNewtype ::
    (C a) =>
    (a -> llvmValue) ->
-   Value (Ptr (Struct a)) -> CodeGenFunction r llvmValue
+   Value (LLVM.Ptr (Struct a)) -> CodeGenFunction r llvmValue
 loadNewtype wrap ptr =
    fmap wrap $ load ptr
 
 storeNewtype ::
    (C a) =>
    (llvmValue -> a) ->
-   llvmValue -> Value (Ptr (Struct a)) -> CodeGenFunction r ()
+   llvmValue -> Value (LLVM.Ptr (Struct a)) -> CodeGenFunction r ()
 storeNewtype unwrap y ptr =
    store (unwrap y) ptr
 
diff --git a/src/LLVM/Extra/MemoryPrivate.hs b/src/LLVM/Extra/MemoryPrivate.hs
--- a/src/LLVM/Extra/MemoryPrivate.hs
+++ b/src/LLVM/Extra/MemoryPrivate.hs
@@ -3,12 +3,10 @@
 import qualified LLVM.Core as LLVM
 import LLVM.Core (CodeGenFunction, Value, )
 
-import Foreign.Ptr (Ptr, )
 
-
 decomposeFromLoad ::
    LLVM.IsSized struct =>
-   (Value (Ptr struct) -> CodeGenFunction r a) ->
+   (Value (LLVM.Ptr struct) -> CodeGenFunction r a) ->
    Value struct -> CodeGenFunction r a
 decomposeFromLoad loadStruct struct = do
    ptr <- LLVM.alloca
@@ -17,7 +15,7 @@
 
 composeFromStore ::
    LLVM.IsSized struct =>
-   (a -> Value (Ptr struct) -> CodeGenFunction r ()) ->
+   (a -> Value (LLVM.Ptr struct) -> CodeGenFunction r ()) ->
    a -> CodeGenFunction r (Value struct)
 composeFromStore storeStruct x = do
    ptr <- LLVM.alloca
diff --git a/src/LLVM/Extra/Multi/Iterator.hs b/src/LLVM/Extra/Multi/Iterator.hs
--- a/src/LLVM/Extra/Multi/Iterator.hs
+++ b/src/LLVM/Extra/Multi/Iterator.hs
@@ -9,10 +9,10 @@
 import qualified LLVM.Extra.Multi.Value as MultiValue
 import qualified LLVM.Extra.Iterator as Iter
 import qualified LLVM.Extra.ScalarOrVector as SoV
+import qualified LLVM.Extra.Tuple as Tuple
 import qualified LLVM.Extra.MaybePrivate as Maybe
 import qualified LLVM.Extra.Arithmetic as A
 import qualified LLVM.Extra.Control as C
-import LLVM.Extra.Class (undefTuple)
 
 import qualified LLVM.Core as LLVM
 import LLVM.Core (CodeGenFunction)
@@ -67,7 +67,7 @@
    -}
    enumFromTo from to =
       Iter.takeWhileJust $
-      Iter.iterate (Maybe.maybeArg undefTuple (succMax to)) (Maybe.just from)
+      Iter.iterate (Maybe.maybeArg Tuple.undef (succMax to)) (Maybe.just from)
 
 succMax ::
    (LLVM.IsInteger w, SoV.IntegerConstant w, Num w,
@@ -77,7 +77,7 @@
    LLVM.CodeGenFunction r (Maybe.T (MultiValue.T (Enum.T w e)))
 succMax to e = do
    MultiValue.Cons less <- MultiValue.cmpEnum A.CmpLT e to
-   C.ifThen less (Maybe.nothing undefTuple) $
+   C.ifThen less (Maybe.nothing Tuple.undef) $
       fmap Maybe.just $ MultiValue.succ e
 
 {- |
diff --git a/src/LLVM/Extra/Multi/Value/Memory.hs b/src/LLVM/Extra/Multi/Value/Memory.hs
deleted file mode 100644
--- a/src/LLVM/Extra/Multi/Value/Memory.hs
+++ /dev/null
@@ -1,257 +0,0 @@
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE FlexibleContexts #-}
-module LLVM.Extra.Multi.Value.Memory where
-
-import qualified LLVM.Extra.Multi.Value as MultiValue
-import LLVM.Extra.ArithmeticPrivate as A
-import LLVM.Extra.MemoryPrivate (decomposeFromLoad, composeFromStore, )
-
-import qualified LLVM.Core as LLVM
-import LLVM.Core (CodeGenFunction, Value, )
-
-import qualified Type.Data.Num.Decimal as TypeNum
-
-import Foreign.StablePtr (StablePtr, )
-import Foreign.Ptr (Ptr, FunPtr, castPtr, )
-
-import Data.Tagged (Tagged)
-import Data.Complex (Complex, )
-import Data.Word (Word8, Word16, Word32, Word64, )
-import Data.Int (Int8, Int16, Int32, Int64, )
-import Data.Bool8 (Bool8)
-
-import Control.Applicative (pure, liftA2, liftA3, (<*>), )
-
-import Prelude2010
-import Prelude ()
-
-class (MultiValue.C a, LLVM.IsSized (Struct a)) => C a where
-   {-# MINIMAL (load|decompose), (store|compose) #-}
-   type Struct a :: *
-   load :: Value (Ptr (Struct a)) -> CodeGenFunction r (MultiValue.T a)
-   load ptr  =  decompose =<< LLVM.load ptr
-   store :: MultiValue.T a -> Value (Ptr (Struct a)) -> CodeGenFunction r ()
-   store r ptr  =  flip LLVM.store ptr =<< compose r
-   decompose :: Value (Struct a) -> CodeGenFunction r (MultiValue.T a)
-   decompose = decomposeFromLoad load
-   compose :: MultiValue.T a -> CodeGenFunction r (Value (Struct a))
-   compose = composeFromStore store
-
-instance C Bool8 where
-   type Struct Bool8 = Word8
-   decompose = fmap MultiValue.Cons . A.cmp LLVM.CmpNE (LLVM.valueOf 0)
-   compose (MultiValue.Cons b) = LLVM.select b (LLVM.valueOf 1) (LLVM.valueOf 0)
-
-instance C Float where
-   type Struct Float = Float
-   load = loadPrimitive
-   store = storePrimitive
-   decompose = decomposePrimitive
-   compose = composePrimitive
-
-instance C Double where
-   type Struct Double = Double
-   load = loadPrimitive
-   store = storePrimitive
-   decompose = decomposePrimitive
-   compose = composePrimitive
-
-instance C Word8 where
-   type Struct Word8 = Word8
-   load = loadPrimitive
-   store = storePrimitive
-   decompose = decomposePrimitive
-   compose = composePrimitive
-
-instance C Word16 where
-   type Struct Word16 = Word16
-   load = loadPrimitive
-   store = storePrimitive
-   decompose = decomposePrimitive
-   compose = composePrimitive
-
-instance C Word32 where
-   type Struct Word32 = Word32
-   load = loadPrimitive
-   store = storePrimitive
-   decompose = decomposePrimitive
-   compose = composePrimitive
-
-instance C Word64 where
-   type Struct Word64 = Word64
-   load = loadPrimitive
-   store = storePrimitive
-   decompose = decomposePrimitive
-   compose = composePrimitive
-
-instance C Int8 where
-   type Struct Int8 = Int8
-   load = loadPrimitive
-   store = storePrimitive
-   decompose = decomposePrimitive
-   compose = composePrimitive
-
-instance C Int16 where
-   type Struct Int16 = Int16
-   load = loadPrimitive
-   store = storePrimitive
-   decompose = decomposePrimitive
-   compose = composePrimitive
-
-instance C Int32 where
-   type Struct Int32 = Int32
-   load = loadPrimitive
-   store = storePrimitive
-   decompose = decomposePrimitive
-   compose = composePrimitive
-
-instance C Int64 where
-   type Struct Int64 = Int64
-   load = loadPrimitive
-   store = storePrimitive
-   decompose = decomposePrimitive
-   compose = composePrimitive
-
-instance (LLVM.IsType a) => C (Ptr a) where
-   type Struct (Ptr a) = Ptr a
-   load = loadPrimitive
-   store = storePrimitive
-   decompose = decomposePrimitive
-   compose = composePrimitive
-
-instance (LLVM.IsFunction a) => C (FunPtr a) where
-   type Struct (FunPtr a) = FunPtr a
-   load = loadPrimitive
-   store = storePrimitive
-   decompose = decomposePrimitive
-   compose = composePrimitive
-
-instance C (StablePtr a) where
-   type Struct (StablePtr a) = StablePtr a
-   load = loadPrimitive
-   store = storePrimitive
-   decompose = decomposePrimitive
-   compose = composePrimitive
-
-
-loadPrimitive ::
-   (MultiValue.Repr Value a ~ Value al) =>
-   Value (Ptr al) -> CodeGenFunction r (MultiValue.T a)
-loadPrimitive = fmap MultiValue.Cons . LLVM.load
-
-storePrimitive ::
-   (MultiValue.Repr Value a ~ Value al) =>
-   MultiValue.T a -> Value (Ptr al) -> CodeGenFunction r ()
-storePrimitive (MultiValue.Cons a) = LLVM.store a
-
-decomposePrimitive ::
-   (MultiValue.Repr Value a ~ Value al) =>
-   Value al -> CodeGenFunction r (MultiValue.T a)
-decomposePrimitive = return . MultiValue.Cons
-
-composePrimitive ::
-   (MultiValue.Repr Value a ~ Value al) =>
-   MultiValue.T a -> CodeGenFunction r (Value al)
-composePrimitive (MultiValue.Cons a) = return a
-
-
-instance C () where
-   type Struct () = LLVM.Struct ()
-   load = loadUnit
-   store = storeUnit
-   decompose = decomposeUnit
-   compose = composeUnit
-
-loadUnit ::
-   (MultiValue.Repr Value a ~ ()) =>
-   Value (Ptr (LLVM.Struct ())) -> CodeGenFunction r (MultiValue.T a)
-loadUnit _ = return $ MultiValue.Cons ()
-
-storeUnit ::
-   MultiValue.T a -> Value (Ptr (LLVM.Struct ())) -> CodeGenFunction r ()
-storeUnit _ _ = return ()
-
-decomposeUnit ::
-   (MultiValue.Repr Value a ~ ()) =>
-   Value (LLVM.Struct ()) -> CodeGenFunction r (MultiValue.T a)
-decomposeUnit _ = return $ MultiValue.Cons ()
-
-composeUnit ::
-   MultiValue.T a -> CodeGenFunction r (Value (LLVM.Struct ()))
-composeUnit _ = return (LLVM.value $ LLVM.constStruct ())
-
-
-instance (C a) => C (Tagged tag a) where
-   type Struct (Tagged tag a) = Struct a
-   decompose = fmap MultiValue.tag . decompose
-   compose = compose . MultiValue.untag
-
-instance (C a) => C (Complex a) where
-   type Struct (Complex a) = LLVM.Struct (Struct a, (Struct a, ()))
-   decompose c =
-      liftA2 MultiValue.consComplex
-         (decompose =<< LLVM.extractvalue c TypeNum.d0)
-         (decompose =<< LLVM.extractvalue c TypeNum.d1)
-   compose c =
-      case MultiValue.deconsComplex c of
-         (r,i) -> do
-            sr <- compose r
-            si <- compose i
-            rr <- LLVM.insertvalue (LLVM.value LLVM.undef) sr TypeNum.d0
-            LLVM.insertvalue rr si TypeNum.d1
-
-
-instance (C a, C b) => C (a,b) where
-   type Struct (a,b) = LLVM.Struct (Struct a, (Struct b, ()))
-   decompose ab =
-      liftA2 MultiValue.zip
-         (decompose =<< LLVM.extractvalue ab TypeNum.d0)
-         (decompose =<< LLVM.extractvalue ab TypeNum.d1)
-   compose ab =
-      case MultiValue.unzip ab of
-         (a,b) -> do
-            sa <- compose a
-            sb <- compose b
-            ra <- LLVM.insertvalue (LLVM.value LLVM.undef) sa TypeNum.d0
-            LLVM.insertvalue ra sb TypeNum.d1
-
-instance (C a, C b, C c) => C (a,b,c) where
-   type Struct (a,b,c) = LLVM.Struct (Struct a, (Struct b, (Struct c, ())))
-   decompose abc =
-      liftA3 MultiValue.zip3
-         (decompose =<< LLVM.extractvalue abc TypeNum.d0)
-         (decompose =<< LLVM.extractvalue abc TypeNum.d1)
-         (decompose =<< LLVM.extractvalue abc TypeNum.d2)
-   compose abc =
-      case MultiValue.unzip3 abc of
-         (a,b,c) -> do
-            sa <- compose a
-            sb <- compose b
-            sc <- compose c
-            ra <- LLVM.insertvalue (LLVM.value LLVM.undef) sa TypeNum.d0
-            rb <- LLVM.insertvalue ra sb TypeNum.d1
-            LLVM.insertvalue rb sc TypeNum.d2
-
-instance (C a, C b, C c, C d) => C (a,b,c,d) where
-   type Struct (a,b,c,d) = LLVM.Struct (Struct a, (Struct b, (Struct c, (Struct d, ()))))
-   decompose abcd =
-      pure MultiValue.zip4
-         <*> (decompose =<< LLVM.extractvalue abcd TypeNum.d0)
-         <*> (decompose =<< LLVM.extractvalue abcd TypeNum.d1)
-         <*> (decompose =<< LLVM.extractvalue abcd TypeNum.d2)
-         <*> (decompose =<< LLVM.extractvalue abcd TypeNum.d3)
-   compose abcd =
-      case MultiValue.unzip4 abcd of
-         (a,b,c,d) -> do
-            sa <- compose a
-            sb <- compose b
-            sc <- compose c
-            sd <- compose d
-            ra <- LLVM.insertvalue (LLVM.value LLVM.undef) sa TypeNum.d0
-            rb <- LLVM.insertvalue ra sb TypeNum.d1
-            rc <- LLVM.insertvalue rb sc TypeNum.d2
-            LLVM.insertvalue rc sd TypeNum.d3
-
-
-castStructPtr :: Ptr a -> Ptr (Struct a)
-castStructPtr = castPtr
diff --git a/src/LLVM/Extra/Multi/Value/Private.hs b/src/LLVM/Extra/Multi/Value/Private.hs
--- a/src/LLVM/Extra/Multi/Value/Private.hs
+++ b/src/LLVM/Extra/Multi/Value/Private.hs
@@ -7,15 +7,15 @@
 import qualified LLVM.Extra.ScalarOrVector as SoV
 import qualified LLVM.Extra.Arithmetic as A
 import qualified LLVM.Extra.Control as C
-import qualified LLVM.Extra.Class as Class
+import qualified LLVM.Extra.Tuple as Tuple
+import qualified LLVM.Extra.MaybePrivate as Maybe
 
 import qualified LLVM.Core as LLVM
-import qualified LLVM.Util.Loop as Loop
-import LLVM.Util.Loop (Phi, )
 import LLVM.Core (WordN, IntN, )
 
 import qualified Type.Data.Num.Decimal.Number as Dec
 
+import qualified Foreign.Storable.Record.Tuple as StoreTuple
 import Foreign.StablePtr (StablePtr, )
 import Foreign.Ptr (Ptr, FunPtr, )
 
@@ -25,7 +25,7 @@
 import Data.Functor (Functor, )
 
 import qualified Data.Tuple.HT as TupleHT
-import qualified Data.Tuple as Tuple
+import qualified Data.Tuple as Tup
 import qualified Data.EnumBitSet as EnumBitSet
 import qualified Data.Enum.Storable as Enum
 import qualified Data.Bool8 as Bool8
@@ -35,212 +35,239 @@
 import Data.Tuple.HT (uncurry3, )
 import Data.Maybe (Maybe(Nothing,Just), )
 import Data.Bool (Bool(False,True), )
-import Data.Word (Word8, Word16, Word32, Word64, )
-import Data.Int (Int8, Int16, Int32, Int64, )
+import Data.Word (Word8, Word16, Word32, Word64, Word)
+import Data.Int (Int8, Int16, Int32, Int64, Int)
 import Data.Bool8 (Bool8)
 
 import qualified Prelude as P
 import Prelude (Float, Double, Integer, Rational, )
 
 
-newtype T a = Cons (Repr LLVM.Value a)
+newtype T a = Cons (Tuple.ValueOf a)
 
 
 class C a where
-   type Repr (f :: * -> *) a :: *
    cons :: a -> T a
    undef :: T a
    zero :: T a
-   phis :: LLVM.BasicBlock -> T a -> LLVM.CodeGenFunction r (T a)
-   addPhis :: LLVM.BasicBlock -> T a -> T a -> LLVM.CodeGenFunction r ()
+   phi :: LLVM.BasicBlock -> T a -> LLVM.CodeGenFunction r (T a)
+   addPhi :: LLVM.BasicBlock -> T a -> T a -> LLVM.CodeGenFunction r ()
 
 instance C Bool where
-   type Repr f Bool = f Bool
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
 
 instance C Float where
-   type Repr f Float = f Float
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
 
 instance C Double where
-   type Repr f Double = f Double
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
 
+instance C Word where
+   cons = consPrimitive
+   undef = undefPrimitive
+   zero = zeroPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
+
 instance C Word8 where
-   type Repr f Word8 = f Word8
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
 
 instance C Word16 where
-   type Repr f Word16 = f Word16
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
 
 instance C Word32 where
-   type Repr f Word32 = f Word32
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
 
 instance C Word64 where
-   type Repr f Word64 = f Word64
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
 
 instance (Dec.Positive n) => C (LLVM.WordN n) where
-   type Repr f (LLVM.WordN n) = f (LLVM.WordN n)
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
 
+instance C Int where
+   cons = consPrimitive
+   undef = undefPrimitive
+   zero = zeroPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
+
 instance C Int8 where
-   type Repr f Int8 = f Int8
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
 
 instance C Int16 where
-   type Repr f Int16 = f Int16
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
 
 instance C Int32 where
-   type Repr f Int32 = f Int32
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
 
 instance C Int64 where
-   type Repr f Int64 = f Int64
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
 
 instance (Dec.Positive n) => C (LLVM.IntN n) where
-   type Repr f (LLVM.IntN n) = f (LLVM.IntN n)
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
 
-instance (LLVM.IsType a) => C (Ptr a) where
-   -- Do we also have to convert the pointer target type?
-   type Repr f (Ptr a) = f (Ptr a)
+instance (LLVM.IsType a) => C (LLVM.Ptr a) where
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
 
+instance C (Ptr a) where
+   cons = consPrimitive
+   undef = undefPrimitive
+   zero = zeroPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
+
 instance (LLVM.IsFunction a) => C (FunPtr a) where
-   type Repr f (FunPtr a) = f (FunPtr a)
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
 
 instance C (StablePtr a) where
-   type Repr f (StablePtr a) = f (StablePtr a)
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
 
 
 consPrimitive ::
-   (LLVM.IsConst al, LLVM.Value al ~ Repr LLVM.Value a) =>
+   (LLVM.IsConst al, LLVM.Value al ~ Tuple.ValueOf a) =>
    al -> T a
 consPrimitive = Cons . LLVM.valueOf
 
 undefPrimitive, zeroPrimitive ::
-   (LLVM.IsType al, LLVM.Value al ~ Repr LLVM.Value a) =>
+   (LLVM.IsType al, LLVM.Value al ~ Tuple.ValueOf a) =>
    T a
 undefPrimitive = Cons $ LLVM.value LLVM.undef
 zeroPrimitive = Cons $ LLVM.value LLVM.zero
 
-phisPrimitive ::
-   (LLVM.IsFirstClass al, LLVM.Value al ~ Repr LLVM.Value a) =>
+phiPrimitive ::
+   (LLVM.IsFirstClass al, LLVM.Value al ~ Tuple.ValueOf a) =>
    LLVM.BasicBlock -> T a -> LLVM.CodeGenFunction r (T a)
-phisPrimitive bb (Cons a) = fmap Cons $ Loop.phis bb a
+phiPrimitive bb (Cons a) = fmap Cons $ Tuple.phi bb a
 
-addPhisPrimitive ::
-   (LLVM.IsFirstClass al, LLVM.Value al ~ Repr LLVM.Value a) =>
+addPhiPrimitive ::
+   (LLVM.IsFirstClass al, LLVM.Value al ~ Tuple.ValueOf a) =>
    LLVM.BasicBlock -> T a -> T a -> LLVM.CodeGenFunction r ()
-addPhisPrimitive bb (Cons a) (Cons b) = Loop.addPhis bb a b
+addPhiPrimitive bb (Cons a) (Cons b) = Tuple.addPhi bb a b
 
 
+consTuple ::
+   (Tuple.Value a) =>
+   a -> T a
+consTuple = Cons . Tuple.valueOf
+
+undefTuple ::
+   (Tuple.Value a, Tuple.ValueOf a ~ al, Tuple.Undefined al) =>
+   T a
+undefTuple = Cons Tuple.undef
+
+zeroTuple ::
+   (Tuple.Value a, Tuple.ValueOf a ~ al, Tuple.Zero al) =>
+   T a
+zeroTuple = Cons Tuple.zero
+
+phiTuple ::
+   (Tuple.Value a, Tuple.ValueOf a ~ al, Tuple.Phi al) =>
+   LLVM.BasicBlock -> T a -> LLVM.CodeGenFunction r (T a)
+phiTuple bb (Cons a) = fmap Cons $ Tuple.phi bb a
+
+addPhiTuple ::
+   (Tuple.Value a, Tuple.ValueOf a ~ al, Tuple.Phi al) =>
+   LLVM.BasicBlock -> T a -> T a -> LLVM.CodeGenFunction r ()
+addPhiTuple bb (Cons a) (Cons b) = Tuple.addPhi bb a b
+
+
 instance C () where
-   type Repr f () = ()
    cons = consUnit
    undef = undefUnit
    zero = zeroUnit
-   phis = phisUnit
-   addPhis = addPhisUnit
+   phi = phiUnit
+   addPhi = addPhiUnit
 
-consUnit :: (Repr LLVM.Value a ~ ()) => a -> T a
+consUnit :: (Tuple.ValueOf a ~ ()) => a -> T a
 consUnit _ = Cons ()
 
-undefUnit :: (Repr LLVM.Value a ~ ()) => T a
+undefUnit :: (Tuple.ValueOf a ~ ()) => T a
 undefUnit = Cons ()
 
-zeroUnit :: (Repr LLVM.Value a ~ ()) => T a
+zeroUnit :: (Tuple.ValueOf a ~ ()) => T a
 zeroUnit = Cons ()
 
-phisUnit ::
-   (Repr LLVM.Value a ~ ()) =>
+phiUnit ::
+   (Tuple.ValueOf a ~ ()) =>
    LLVM.BasicBlock -> T a -> LLVM.CodeGenFunction r (T a)
-phisUnit _bb (Cons ()) = return $ Cons ()
+phiUnit _bb (Cons ()) = return $ Cons ()
 
-addPhisUnit ::
-   (Repr LLVM.Value a ~ ()) =>
+addPhiUnit ::
+   (Tuple.ValueOf a ~ ()) =>
    LLVM.BasicBlock -> T a -> T a -> LLVM.CodeGenFunction r ()
-addPhisUnit _bb (Cons ()) (Cons ()) = return ()
+addPhiUnit _bb (Cons ()) (Cons ()) = return ()
 
 
 instance C Bool8 where
-   type Repr f Bool8 = f Bool
    cons = consPrimitive . Bool8.toBool
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
 
 boolPFrom8 :: T Bool8 -> T Bool
 boolPFrom8 (Cons b) = Cons b
@@ -259,20 +286,19 @@
 instance
    (LLVM.IsInteger w, LLVM.IsConst w, P.Num w, P.Enum e) =>
       C (Enum.T w e) where
-   type Repr f (Enum.T w e) = f w
    cons = consPrimitive . P.fromIntegral . P.fromEnum . Enum.toPlain
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
 
 toEnum ::
-   (Repr LLVM.Value w ~ LLVM.Value w) =>
+   (Tuple.ValueOf w ~ LLVM.Value w) =>
    T w -> T (Enum.T w e)
 toEnum (Cons w) = Cons w
 
 fromEnum ::
-   (Repr LLVM.Value w ~ LLVM.Value w) =>
+   (Tuple.ValueOf w ~ LLVM.Value w) =>
    T (Enum.T w e) -> T w
 fromEnum (Cons w) = Cons w
 
@@ -301,34 +327,32 @@
 
 
 instance (LLVM.IsInteger w, LLVM.IsConst w) => C (EnumBitSet.T w i) where
-   type Repr f (EnumBitSet.T w i) = f w
    cons = consPrimitive . EnumBitSet.decons
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
 
 
 instance (C a) => C (Maybe a) where
-   type Repr f (Maybe a) = (f Bool, Repr f a)
    cons Nothing = nothing
    cons (Just a) = just $ cons a
    undef = toMaybe undef undef
    zero = toMaybe (cons False) zero
-   phis bb ma =
+   phi bb ma =
       case splitMaybe ma of
-         (b,a) -> Monad.lift2 toMaybe (phis bb b) (phis bb a)
-   addPhis bb x y =
+         (b,a) -> Monad.lift2 toMaybe (phi bb b) (phi bb a)
+   addPhi bb x y =
       case (splitMaybe x, splitMaybe y) of
          ((xb,xa), (yb,ya)) ->
-            addPhis bb xb yb >>
-            addPhis bb xa ya
+            addPhi bb xb yb >>
+            addPhi bb xa ya
 
 splitMaybe :: T (Maybe a) -> (T Bool, T a)
-splitMaybe (Cons (b,a)) = (Cons b, Cons a)
+splitMaybe (Cons (Maybe.Cons b a)) = (Cons b, Cons a)
 
 toMaybe :: T Bool -> T a -> T (Maybe a)
-toMaybe (Cons b) (Cons a) = Cons (b,a)
+toMaybe (Cons b) (Cons a) = Cons (Maybe.Cons b a)
 
 nothing :: (C a) => T (Maybe a)
 nothing = toMaybe (cons False) undef
@@ -338,52 +362,49 @@
 
 
 instance (C a, C b) => C (a,b) where
-   type Repr f (a, b) = (Repr f a, Repr f b)
    cons (a,b) = zip (cons a) (cons b)
    undef = zip undef undef
    zero = zip zero zero
-   phis bb a =
+   phi bb a =
       case unzip a of
          (a0,a1) ->
-            Monad.lift2 zip (phis bb a0) (phis bb a1)
-   addPhis bb a b =
+            Monad.lift2 zip (phi bb a0) (phi bb a1)
+   addPhi bb a b =
       case (unzip a, unzip b) of
          ((a0,a1), (b0,b1)) ->
-            addPhis bb a0 b0 >>
-            addPhis bb a1 b1
+            addPhi bb a0 b0 >>
+            addPhi bb a1 b1
 
 instance (C a, C b, C c) => C (a,b,c) where
-   type Repr f (a, b, c) = (Repr f a, Repr f b, Repr f c)
    cons (a,b,c) = zip3 (cons a) (cons b) (cons c)
    undef = zip3 undef undef undef
    zero = zip3 zero zero zero
-   phis bb a =
+   phi bb a =
       case unzip3 a of
          (a0,a1,a2) ->
-            Monad.lift3 zip3 (phis bb a0) (phis bb a1) (phis bb a2)
-   addPhis bb a b =
+            Monad.lift3 zip3 (phi bb a0) (phi bb a1) (phi bb a2)
+   addPhi bb a b =
       case (unzip3 a, unzip3 b) of
          ((a0,a1,a2), (b0,b1,b2)) ->
-            addPhis bb a0 b0 >>
-            addPhis bb a1 b1 >>
-            addPhis bb a2 b2
+            addPhi bb a0 b0 >>
+            addPhi bb a1 b1 >>
+            addPhi bb a2 b2
 
 instance (C a, C b, C c, C d) => C (a,b,c,d) where
-   type Repr f (a, b, c, d) = (Repr f a, Repr f b, Repr f c, Repr f d)
    cons (a,b,c,d) = zip4 (cons a) (cons b) (cons c) (cons d)
    undef = zip4 undef undef undef undef
    zero = zip4 zero zero zero zero
-   phis bb a =
+   phi bb a =
       case unzip4 a of
          (a0,a1,a2,a3) ->
-            Monad.lift4 zip4 (phis bb a0) (phis bb a1) (phis bb a2) (phis bb a3)
-   addPhis bb a b =
+            Monad.lift4 zip4 (phi bb a0) (phi bb a1) (phi bb a2) (phi bb a3)
+   addPhi bb a b =
       case (unzip4 a, unzip4 b) of
          ((a0,a1,a2,a3), (b0,b1,b2,b3)) ->
-            addPhis bb a0 b0 >>
-            addPhis bb a1 b1 >>
-            addPhis bb a2 b2 >>
-            addPhis bb a3 b3
+            addPhi bb a0 b0 >>
+            addPhi bb a1 b1 >>
+            addPhi bb a2 b2 >>
+            addPhi bb a3 b3
 
 
 fst :: T (a,b) -> T a
@@ -396,23 +417,23 @@
 curry f a b = f $ zip a b
 
 uncurry :: (T a -> T b -> c) -> (T (a,b) -> c)
-uncurry f = Tuple.uncurry f . unzip
+uncurry f = Tup.uncurry f . unzip
 
 
 mapFst :: (T a0 -> T a1) -> T (a0,b) -> T (a1,b)
-mapFst f = Tuple.uncurry zip . TupleHT.mapFst f . unzip
+mapFst f = Tup.uncurry zip . TupleHT.mapFst f . unzip
 
 mapSnd :: (T b0 -> T b1) -> T (a,b0) -> T (a,b1)
-mapSnd f = Tuple.uncurry zip . TupleHT.mapSnd f . unzip
+mapSnd f = Tup.uncurry zip . TupleHT.mapSnd f . unzip
 
 mapFstF :: (Functor f) => (T a0 -> f (T a1)) -> T (a0,b) -> f (T (a1,b))
-mapFstF f = fmap (Tuple.uncurry zip) . FuncHT.mapFst f . unzip
+mapFstF f = fmap (Tup.uncurry zip) . FuncHT.mapFst f . unzip
 
 mapSndF :: (Functor f) => (T b0 -> f (T b1)) -> T (a,b0) -> f (T (a,b1))
-mapSndF f = fmap (Tuple.uncurry zip) . FuncHT.mapSnd f . unzip
+mapSndF f = fmap (Tup.uncurry zip) . FuncHT.mapSnd f . unzip
 
 swap :: T (a,b) -> T (b,a)
-swap = Tuple.uncurry zip . TupleHT.swap . unzip
+swap = Tup.uncurry zip . TupleHT.swap . unzip
 
 
 fst3 :: T (a,b,c) -> T a
@@ -463,13 +484,26 @@
 unzip4 (Cons (a,b,c,d)) = (Cons a, Cons b, Cons c, Cons d)
 
 
+instance (C tuple) => C (StoreTuple.Tuple tuple) where
+   cons = tuple . cons . StoreTuple.getTuple
+   undef = tuple undef
+   zero = tuple zero
+   phi bb = fmap tuple . phi bb . untuple
+   addPhi bb a b = addPhi bb (untuple a) (untuple b)
+
+tuple :: T tuple -> T (StoreTuple.Tuple tuple)
+tuple (Cons a) = Cons a
+
+untuple :: T (StoreTuple.Tuple tuple) -> T tuple
+untuple (Cons a) = Cons a
+
+
 instance C a => C (Tagged tag a) where
-   type Repr f (Tagged tag a) = Repr f a
    cons = tag . cons . unTagged
    undef = tag undef
    zero = tag zero
-   phis bb = fmap tag . phis bb . untag
-   addPhis bb a b = addPhis bb (untag a) (untag b)
+   phi bb = fmap tag . phi bb . untag
+   addPhi bb a b = addPhi bb (untag a) (untag b)
 
 tag :: T a -> T (Tagged tag a)
 tag (Cons a) = Cons a
@@ -489,19 +523,18 @@
 
 
 instance (C a) => C (Complex a) where
-   type Repr f (Complex a) = Complex (Repr f a)
    cons (a:+b) = consComplex (cons a) (cons b)
    undef = consComplex undef undef
    zero = consComplex zero zero
-   phis bb a =
+   phi bb a =
       case deconsComplex a of
          (a0,a1) ->
-            Monad.lift2 consComplex (phis bb a0) (phis bb a1)
-   addPhis bb a b =
+            Monad.lift2 consComplex (phi bb a0) (phi bb a1)
+   addPhi bb a b =
       case (deconsComplex a, deconsComplex b) of
          ((a0,a1), (b0,b1)) ->
-            addPhis bb a0 b0 >>
-            addPhis bb a1 b1
+            addPhi bb a0 b0 >>
+            addPhi bb a1 b1
 
 consComplex :: T a -> T a -> T (Complex a)
 consComplex (Cons a) (Cons b) = Cons (a:+b)
@@ -603,7 +636,7 @@
 
 instance (Compose a, Compose b) => Compose (a,b) where
    type Composed (a,b) = (Composed a, Composed b)
-   compose = Tuple.uncurry zip . TupleHT.mapPair (compose, compose)
+   compose = Tup.uncurry zip . TupleHT.mapPair (compose, compose)
 
 instance (Decompose pa, Decompose pb) => Decompose (pa,pb) where
    decompose (pa,pb) =
@@ -646,6 +679,19 @@
         (PatternTuple pa, PatternTuple pb, PatternTuple pc, PatternTuple pd)
 
 
+instance (Compose tuple) => Compose (StoreTuple.Tuple tuple) where
+   type Composed (StoreTuple.Tuple tuple) = StoreTuple.Tuple (Composed tuple)
+   compose = tuple . compose . StoreTuple.getTuple
+
+instance (Decompose p) => Decompose (StoreTuple.Tuple p) where
+   decompose (StoreTuple.Tuple p) = StoreTuple.Tuple . decompose p . untuple
+
+type instance Decomposed f (StoreTuple.Tuple p) =
+                  StoreTuple.Tuple (Decomposed f p)
+type instance PatternTuple (StoreTuple.Tuple p) =
+                  StoreTuple.Tuple (PatternTuple p)
+
+
 instance (Compose a) => Compose (Tagged tag a) where
    type Composed (Tagged tag a) = Tagged tag (Composed a)
    compose = tag . compose . unTagged
@@ -663,7 +709,7 @@
 
 instance (Decompose pa) => Decompose (Complex pa) where
    decompose (pa:+pb) =
-      Tuple.uncurry (:+) .
+      Tup.uncurry (:+) .
       TupleHT.mapPair (decompose pa, decompose pb) . deconsComplex
 
 type instance Decomposed f (Complex pa) = Complex (Decomposed f pa)
@@ -675,44 +721,44 @@
 
 
 
-lift1 :: (Repr LLVM.Value a -> Repr LLVM.Value b) -> T a -> T b
+lift1 :: (Tuple.ValueOf a -> Tuple.ValueOf b) -> T a -> T b
 lift1 f (Cons a) = Cons $ f a
 
 liftM0 ::
    (Monad m) =>
-   m (Repr LLVM.Value a) ->
+   m (Tuple.ValueOf a) ->
    m (T a)
 liftM0 f = Monad.lift Cons f
 
 liftM ::
    (Monad m) =>
-   (Repr LLVM.Value a -> m (Repr LLVM.Value b)) ->
+   (Tuple.ValueOf a -> m (Tuple.ValueOf b)) ->
    T a -> m (T b)
 liftM f (Cons a) = Monad.lift Cons $ f a
 
 liftM2 ::
    (Monad m) =>
-   (Repr LLVM.Value a -> Repr LLVM.Value b -> m (Repr LLVM.Value c)) ->
+   (Tuple.ValueOf a -> Tuple.ValueOf b -> m (Tuple.ValueOf c)) ->
    T a -> T b -> m (T c)
 liftM2 f (Cons a) (Cons b) = Monad.lift Cons $ f a b
 
 liftM3 ::
    (Monad m) =>
-   (Repr LLVM.Value a -> Repr LLVM.Value b -> Repr LLVM.Value c ->
-    m (Repr LLVM.Value d)) ->
+   (Tuple.ValueOf a -> Tuple.ValueOf b -> Tuple.ValueOf c ->
+    m (Tuple.ValueOf d)) ->
    T a -> T b -> T c -> m (T d)
 liftM3 f (Cons a) (Cons b) (Cons c) = Monad.lift Cons $ f a b c
 
 
-instance (C a) => Class.Zero (T a) where
-   zeroTuple = zero
+instance (C a) => Tuple.Zero (T a) where
+   zero = zero
 
-instance (C a) => Class.Undefined (T a) where
-   undefTuple = undef
+instance (C a) => Tuple.Undefined (T a) where
+   undef = undef
 
-instance (C a) => Phi (T a) where
-   phis = phis
-   addPhis = addPhis
+instance (C a) => Tuple.Phi (T a) where
+   phi = phi
+   addPhi = addPhi
 
 
 class (C a) => IntegerConstant a where
@@ -724,11 +770,13 @@
 instance IntegerConstant Float  where fromInteger' = Cons . LLVM.value . SoV.constFromInteger
 instance IntegerConstant Double where fromInteger' = Cons . LLVM.value . SoV.constFromInteger
 
+instance IntegerConstant Word where fromInteger' = Cons . LLVM.value . SoV.constFromInteger
 instance IntegerConstant Word8 where fromInteger' = Cons . LLVM.value . SoV.constFromInteger
 instance IntegerConstant Word16 where fromInteger' = Cons . LLVM.value . SoV.constFromInteger
 instance IntegerConstant Word32 where fromInteger' = Cons . LLVM.value . SoV.constFromInteger
 instance IntegerConstant Word64 where fromInteger' = Cons . LLVM.value . SoV.constFromInteger
 
+instance IntegerConstant Int where fromInteger' = Cons . LLVM.value . SoV.constFromInteger
 instance IntegerConstant Int8 where fromInteger' = Cons . LLVM.value . SoV.constFromInteger
 instance IntegerConstant Int16 where fromInteger' = Cons . LLVM.value . SoV.constFromInteger
 instance IntegerConstant Int32 where fromInteger' = Cons . LLVM.value . SoV.constFromInteger
@@ -769,6 +817,11 @@
    sub = liftM2 LLVM.sub
    neg = liftM LLVM.neg
 
+instance Additive Word where
+   add = liftM2 LLVM.add
+   sub = liftM2 LLVM.sub
+   neg = liftM LLVM.neg
+
 instance Additive Word8 where
    add = liftM2 LLVM.add
    sub = liftM2 LLVM.sub
@@ -789,6 +842,11 @@
    sub = liftM2 LLVM.sub
    neg = liftM LLVM.neg
 
+instance Additive Int where
+   add = liftM2 LLVM.add
+   sub = liftM2 LLVM.sub
+   neg = liftM LLVM.neg
+
 instance Additive Int8 where
    add = liftM2 LLVM.add
    sub = liftM2 LLVM.sub
@@ -841,10 +899,12 @@
 
 instance PseudoRing Float where mul = liftM2 LLVM.mul
 instance PseudoRing Double where mul = liftM2 LLVM.mul
+instance PseudoRing Word where mul = liftM2 LLVM.mul
 instance PseudoRing Word8 where mul = liftM2 LLVM.mul
 instance PseudoRing Word16 where mul = liftM2 LLVM.mul
 instance PseudoRing Word32 where mul = liftM2 LLVM.mul
 instance PseudoRing Word64 where mul = liftM2 LLVM.mul
+instance PseudoRing Int where mul = liftM2 LLVM.mul
 instance PseudoRing Int8 where mul = liftM2 LLVM.mul
 instance PseudoRing Int16 where mul = liftM2 LLVM.mul
 instance PseudoRing Int32 where mul = liftM2 LLVM.mul
@@ -913,6 +973,12 @@
    abs = liftM A.abs
    signum = liftM A.signum
 
+instance Real Word where
+   min = liftM2 A.min
+   max = liftM2 A.max
+   abs = liftM A.abs
+   signum = liftM A.signum
+
 instance Real Word8 where
    min = liftM2 A.min
    max = liftM2 A.max
@@ -937,6 +1003,12 @@
    abs = liftM A.abs
    signum = liftM A.signum
 
+instance Real Int where
+   min = liftM2 A.min
+   max = liftM2 A.max
+   abs = liftM A.abs
+   signum = liftM A.signum
+
 instance Real Int8 where
    min = liftM2 A.min
    max = liftM2 A.max
@@ -1008,17 +1080,19 @@
 
 
 class
-   (Repr LLVM.Value i ~ LLVM.Value ir,
+   (Tuple.ValueOf i ~ LLVM.Value ir,
     LLVM.IsInteger ir, SoV.IntegerConstant ir,
     LLVM.CmpRet ir, LLVM.IsPrimitive ir) =>
       NativeInteger i ir where
 
-instance NativeInteger Word8  Word8 where
+instance NativeInteger Word   Word   where
+instance NativeInteger Word8  Word8  where
 instance NativeInteger Word16 Word16 where
 instance NativeInteger Word32 Word32 where
 instance NativeInteger Word64 Word64 where
 
-instance NativeInteger Int8  Int8 where
+instance NativeInteger Int   Int   where
+instance NativeInteger Int8  Int8  where
 instance NativeInteger Int16 Int16 where
 instance NativeInteger Int32 Int32 where
 instance NativeInteger Int64 Int64 where
@@ -1027,7 +1101,7 @@
 
 
 class
-   (Repr LLVM.Value a ~ LLVM.Value ar,
+   (Tuple.ValueOf a ~ LLVM.Value ar,
     LLVM.IsFloating ar, SoV.RationalConstant ar,
     LLVM.CmpRet ar, LLVM.IsPrimitive ar) =>
       NativeFloating a ar where
@@ -1114,10 +1188,12 @@
 instance Select Bool8 where select = liftM3 LLVM.select
 instance Select Float where select = liftM3 LLVM.select
 instance Select Double where select = liftM3 LLVM.select
+instance Select Word where select = liftM3 LLVM.select
 instance Select Word8 where select = liftM3 LLVM.select
 instance Select Word16 where select = liftM3 LLVM.select
 instance Select Word32 where select = liftM3 LLVM.select
 instance Select Word64 where select = liftM3 LLVM.select
+instance Select Int where select = liftM3 LLVM.select
 instance Select Int8 where select = liftM3 LLVM.select
 instance Select Int16 where select = liftM3 LLVM.select
 instance Select Int32 where select = liftM3 LLVM.select
@@ -1161,11 +1237,13 @@
 instance Comparison Float where cmp = liftM2 . LLVM.cmp
 instance Comparison Double where cmp = liftM2 . LLVM.cmp
 
+instance Comparison Int where cmp = liftM2 . LLVM.cmp
 instance Comparison Int8 where cmp = liftM2 . LLVM.cmp
 instance Comparison Int16 where cmp = liftM2 . LLVM.cmp
 instance Comparison Int32 where cmp = liftM2 . LLVM.cmp
 instance Comparison Int64 where cmp = liftM2 . LLVM.cmp
 
+instance Comparison Word where cmp = liftM2 . LLVM.cmp
 instance Comparison Word8 where cmp = liftM2 . LLVM.cmp
 instance Comparison Word16 where cmp = liftM2 . LLVM.cmp
 instance Comparison Word32 where cmp = liftM2 . LLVM.cmp
@@ -1254,6 +1332,9 @@
    shl :: T a -> T a -> LLVM.CodeGenFunction r (T a)
    shr :: T a -> T a -> LLVM.CodeGenFunction r (T a)
 
+instance BitShift Word where
+   shl = liftM2 LLVM.shl; shr = liftM2 LLVM.lshr
+
 instance BitShift Word8 where
    shl = liftM2 LLVM.shl; shr = liftM2 LLVM.lshr
 
@@ -1266,6 +1347,9 @@
 instance BitShift Word64 where
    shl = liftM2 LLVM.shl; shr = liftM2 LLVM.lshr
 
+instance BitShift Int where
+   shl = liftM2 LLVM.shl; shr = liftM2 LLVM.ashr
+
 instance BitShift Int8 where
    shl = liftM2 LLVM.shl; shr = liftM2 LLVM.ashr
 
@@ -1284,11 +1368,19 @@
    idiv :: T a -> T a -> LLVM.CodeGenFunction r (T a)
    irem :: T a -> T a -> LLVM.CodeGenFunction r (T a)
 
+instance Integral Word where
+   idiv = liftM2 LLVM.idiv
+   irem = liftM2 LLVM.irem
+
 instance Integral Word32 where
    idiv = liftM2 LLVM.idiv
    irem = liftM2 LLVM.irem
 
 instance Integral Word64 where
+   idiv = liftM2 LLVM.idiv
+   irem = liftM2 LLVM.irem
+
+instance Integral Int where
    idiv = liftM2 LLVM.idiv
    irem = liftM2 LLVM.irem
 
diff --git a/src/LLVM/Extra/Multi/Value/Vector.hs b/src/LLVM/Extra/Multi/Value/Vector.hs
--- a/src/LLVM/Extra/Multi/Value/Vector.hs
+++ b/src/LLVM/Extra/Multi/Value/Vector.hs
@@ -20,6 +20,7 @@
 import qualified LLVM.Extra.Multi.Vector.Instance as Inst
 import qualified LLVM.Extra.Multi.Vector as MultiVector
 import qualified LLVM.Extra.Multi.Value.Private as MultiValue
+import LLVM.Extra.Multi.Vector.Instance (MVVector)
 
 import qualified LLVM.Core as LLVM
 
@@ -34,133 +35,113 @@
 
 cons ::
    (TypeNum.Positive n, MultiVector.C a) =>
-   LLVM.Vector n a -> MultiValue.T (LLVM.Vector n a)
+   LLVM.Vector n a -> MVVector n a
 cons = Inst.toMultiValue . MultiVector.cons
 
-fst :: MultiValue.T (LLVM.Vector n (a,b)) -> MultiValue.T (LLVM.Vector n a)
+fst :: MVVector n (a,b) -> MVVector n a
 fst = MultiValue.lift1 Tuple.fst
 
-snd :: MultiValue.T (LLVM.Vector n (a,b)) -> MultiValue.T (LLVM.Vector n b)
+snd :: MVVector n (a,b) -> MVVector n b
 snd = MultiValue.lift1 Tuple.snd
 
-swap :: MultiValue.T (LLVM.Vector n (a,b)) -> MultiValue.T (LLVM.Vector n (b,a))
+swap :: MVVector n (a,b) -> MVVector n (b,a)
 swap = MultiValue.lift1 TupleHT.swap
 
 mapFst ::
-   (MultiValue.T (LLVM.Vector n a0) -> MultiValue.T (LLVM.Vector n a1)) ->
-   MultiValue.T (LLVM.Vector n (a0,b)) -> MultiValue.T (LLVM.Vector n (a1,b))
+   (MVVector n a0 -> MVVector n a1) ->
+   MVVector n (a0,b) -> MVVector n (a1,b)
 mapFst f = Tuple.uncurry zip . TupleHT.mapFst f . unzip
 
 mapSnd ::
-   (MultiValue.T (LLVM.Vector n b0) -> MultiValue.T (LLVM.Vector n b1)) ->
-   MultiValue.T (LLVM.Vector n (a,b0)) -> MultiValue.T (LLVM.Vector n (a,b1))
+   (MVVector n b0 -> MVVector n b1) ->
+   MVVector n (a,b0) -> MVVector n (a,b1)
 mapSnd f = Tuple.uncurry zip . TupleHT.mapSnd f . unzip
 
 
-fst3 :: MultiValue.T (LLVM.Vector n (a,b,c)) -> MultiValue.T (LLVM.Vector n a)
+fst3 :: MVVector n (a,b,c) -> MVVector n a
 fst3 = MultiValue.lift1 TupleHT.fst3
 
-snd3 :: MultiValue.T (LLVM.Vector n (a,b,c)) -> MultiValue.T (LLVM.Vector n b)
+snd3 :: MVVector n (a,b,c) -> MVVector n b
 snd3 = MultiValue.lift1 TupleHT.snd3
 
-thd3 :: MultiValue.T (LLVM.Vector n (a,b,c)) -> MultiValue.T (LLVM.Vector n c)
+thd3 :: MVVector n (a,b,c) -> MVVector n c
 thd3 = MultiValue.lift1 TupleHT.thd3
 
 mapFst3 ::
-   (MultiValue.T (LLVM.Vector n a0) -> MultiValue.T (LLVM.Vector n a1)) ->
-   MultiValue.T (LLVM.Vector n (a0,b,c)) ->
-   MultiValue.T (LLVM.Vector n (a1,b,c))
+   (MVVector n a0 -> MVVector n a1) ->
+   MVVector n (a0,b,c) -> MVVector n (a1,b,c)
 mapFst3 f = TupleHT.uncurry3 zip3 . TupleHT.mapFst3 f . unzip3
 
 mapSnd3 ::
-   (MultiValue.T (LLVM.Vector n b0) -> MultiValue.T (LLVM.Vector n b1)) ->
-   MultiValue.T (LLVM.Vector n (a,b0,c)) ->
-   MultiValue.T (LLVM.Vector n (a,b1,c))
+   (MVVector n b0 -> MVVector n b1) ->
+   MVVector n (a,b0,c) -> MVVector n (a,b1,c)
 mapSnd3 f = TupleHT.uncurry3 zip3 . TupleHT.mapSnd3 f . unzip3
 
 mapThd3 ::
-   (MultiValue.T (LLVM.Vector n c0) -> MultiValue.T (LLVM.Vector n c1)) ->
-   MultiValue.T (LLVM.Vector n (a,b,c0)) ->
-   MultiValue.T (LLVM.Vector n (a,b,c1))
+   (MVVector n c0 -> MVVector n c1) ->
+   MVVector n (a,b,c0) -> MVVector n (a,b,c1)
 mapThd3 f = TupleHT.uncurry3 zip3 . TupleHT.mapThd3 f . unzip3
 
 
-zip ::
-   MultiValue.T (LLVM.Vector n a) ->
-   MultiValue.T (LLVM.Vector n b) ->
-   MultiValue.T (LLVM.Vector n (a,b))
+zip :: MVVector n a -> MVVector n b -> MVVector n (a,b)
 zip (MultiValue.Cons a) (MultiValue.Cons b) = MultiValue.Cons (a,b)
 
-zip3 ::
-   MultiValue.T (LLVM.Vector n a) ->
-   MultiValue.T (LLVM.Vector n b) ->
-   MultiValue.T (LLVM.Vector n c) ->
-   MultiValue.T (LLVM.Vector n (a,b,c))
+zip3 :: MVVector n a -> MVVector n b -> MVVector n c -> MVVector n (a,b,c)
 zip3 (MultiValue.Cons a) (MultiValue.Cons b) (MultiValue.Cons c) =
    MultiValue.Cons (a,b,c)
 
-unzip ::
-   MultiValue.T (LLVM.Vector n (a,b)) ->
-   (MultiValue.T (LLVM.Vector n a),
-    MultiValue.T (LLVM.Vector n b))
+unzip :: MVVector n (a,b) -> (MVVector n a, MVVector n b)
 unzip (MultiValue.Cons (a,b)) = (MultiValue.Cons a, MultiValue.Cons b)
 
-unzip3 ::
-   MultiValue.T (LLVM.Vector n (a,b,c)) ->
-   (MultiValue.T (LLVM.Vector n a),
-    MultiValue.T (LLVM.Vector n b),
-    MultiValue.T (LLVM.Vector n c))
+unzip3 :: MVVector n (a,b,c) -> (MVVector n a, MVVector n b, MVVector n c)
 unzip3 (MultiValue.Cons (a,b,c)) =
    (MultiValue.Cons a, MultiValue.Cons b, MultiValue.Cons c)
 
 
 extract ::
    (TypeNum.Positive n, MultiVector.C a) =>
-   LLVM.Value Word32 -> MultiValue.T (LLVM.Vector n a) ->
+   LLVM.Value Word32 -> MVVector n a ->
    LLVM.CodeGenFunction r (MultiValue.T a)
 extract k v = MultiVector.extract k (Inst.fromMultiValue v)
 
 insert ::
    (TypeNum.Positive n, MultiVector.C a) =>
    LLVM.Value Word32 -> MultiValue.T a ->
-   MultiValue.T (LLVM.Vector n a) ->
-   LLVM.CodeGenFunction r (MultiValue.T (LLVM.Vector n a))
+   MVVector n a -> LLVM.CodeGenFunction r (MVVector n a)
 insert k a = Inst.liftMultiValueM (MultiVector.insert k a)
 
 
 replicate ::
    (TypeNum.Positive n, MultiVector.C a) =>
-   MultiValue.T a -> LLVM.CodeGenFunction r (MultiValue.T (LLVM.Vector n a))
+   MultiValue.T a -> LLVM.CodeGenFunction r (MVVector n a)
 replicate = fmap Inst.toMultiValue . MultiVector.replicate
 
 take ::
    (TypeNum.Positive n, TypeNum.Positive m, MultiVector.C a) =>
-   MultiValue.T (LLVM.Vector n a) ->
-   LLVM.CodeGenFunction r (MultiValue.T (LLVM.Vector m a))
+   MVVector n a -> LLVM.CodeGenFunction r (MVVector m a)
 take = Inst.liftMultiValueM MultiVector.take
 
 takeRev ::
    (TypeNum.Positive n, TypeNum.Positive m, MultiVector.C a) =>
-   MultiValue.T (LLVM.Vector n a) ->
-   LLVM.CodeGenFunction r (MultiValue.T (LLVM.Vector m a))
+   MVVector n a -> LLVM.CodeGenFunction r (MVVector m a)
 takeRev = Inst.liftMultiValueM MultiVector.takeRev
 
 
 dissect ::
    (TypeNum.Positive n, MultiVector.C a) =>
-   MultiValue.T (LLVM.Vector n a) -> LLVM.CodeGenFunction r [MultiValue.T a]
+   MVVector n a -> LLVM.CodeGenFunction r [MultiValue.T a]
 dissect = MultiVector.dissect . Inst.fromMultiValue
 
 select ::
    (TypeNum.Positive n, MultiVector.Select a) =>
-   MultiValue.T (LLVM.Vector n Bool) ->
-   MultiValue.T (LLVM.Vector n a) -> MultiValue.T (LLVM.Vector n a) ->
-   LLVM.CodeGenFunction r (MultiValue.T (LLVM.Vector n a))
+   MVVector n Bool ->
+   MVVector n a -> MVVector n a ->
+   LLVM.CodeGenFunction r (MVVector n a)
 select = Inst.liftMultiValueM3 MultiVector.select
 
 cmp ::
    (TypeNum.Positive n, MultiVector.Comparison a) =>
    LLVM.CmpPredicate ->
-   MultiValue.T (LLVM.Vector n a) -> MultiValue.T (LLVM.Vector n a) ->
-   LLVM.CodeGenFunction r (MultiValue.T (LLVM.Vector n Bool))
+   MVVector n a -> MVVector n a ->
+   LLVM.CodeGenFunction r (MVVector n Bool)
 cmp = Inst.liftMultiValueM2 . MultiVector.cmp
diff --git a/src/LLVM/Extra/Multi/Vector.hs b/src/LLVM/Extra/Multi/Vector.hs
--- a/src/LLVM/Extra/Multi/Vector.hs
+++ b/src/LLVM/Extra/Multi/Vector.hs
@@ -57,12 +57,9 @@
 import qualified LLVM.Extra.Multi.Value.Private as MultiValue
 import qualified LLVM.Extra.ScalarOrVector as SoV
 import qualified LLVM.Extra.Arithmetic as A
-import qualified LLVM.Extra.Class as Class
-import LLVM.Extra.Multi.Value.Private (Repr, )
+import qualified LLVM.Extra.Tuple as Tuple
 
-import qualified LLVM.Util.Loop as Loop
 import qualified LLVM.Core as LLVM
-import LLVM.Util.Loop (Phi, )
 import LLVM.Core (CodeGenFunction, IsPrimitive, valueOf, value, )
 
 import qualified Type.Data.Num.Decimal as TypeNum
@@ -72,22 +69,20 @@
 import qualified Data.NonEmpty as NonEmpty
 import qualified Data.List as List
 import qualified Data.Bool8 as Bool8
-import Data.Functor.Compose (Compose(Compose), )
 import Data.Traversable (mapM, sequence, )
-import Data.Functor ((<$>), )
 import Data.NonEmpty ((!:), )
 import Data.Function (flip, (.), ($), )
-import Data.Tuple.HT (fst3, snd3, thd3, )
-import Data.Tuple (fst, snd, )
+import Data.Tuple (snd, )
 import Data.Maybe (maybe, )
 import Data.Ord ((<), )
-import Data.Word (Word8, Word16, Word32, Word64, )
+import Data.Word (Word8, Word16, Word32, Word64, Word)
 import Data.Int (Int8, Int16, Int32, Int64, )
 import Data.Bool8 (Bool8)
 import Data.Bool (Bool, )
 
 import qualified Control.Monad.HT as Monad
 import qualified Control.Applicative as App
+import qualified Control.Functor.HT as FuncHT
 import Control.Monad.HT ((<=<), )
 import Control.Monad (Monad, foldM, fmap, return, (>>), (=<<), )
 import Control.Applicative (liftA2, )
@@ -97,31 +92,31 @@
           fromIntegral, asTypeOf, (-), (+), error, )
 
 
-newtype T n a = Cons (Repr (Value n) a)
+newtype T n a = Cons (Tuple.VectorValueOf n a)
 
-type Value n = Compose LLVM.Value (LLVM.Vector n)
+type Value n a = LLVM.Value (LLVM.Vector n a)
 
 
 consPrim ::
-   (Repr (Value n) a ~ Value n a) =>
+   (Tuple.VectorValueOf n a ~ Value n a) =>
    LLVM.Value (LLVM.Vector n a) -> T n a
-consPrim = Cons . Compose
+consPrim = Cons
 
 deconsPrim ::
-   (Repr (Value n) a ~ Value n a) =>
+   (Tuple.VectorValueOf n a ~ Value n a) =>
    T n a -> LLVM.Value (LLVM.Vector n a)
-deconsPrim (Cons (Compose a)) = a
+deconsPrim (Cons a) = a
 
 
-instance (TypeNum.Positive n, C a) => Class.Undefined (T n a) where
-   undefTuple = undef
+instance (TypeNum.Positive n, C a) => Tuple.Undefined (T n a) where
+   undef = undef
 
-instance (TypeNum.Positive n, C a) => Class.Zero (T n a) where
-   zeroTuple = zero
+instance (TypeNum.Positive n, C a) => Tuple.Zero (T n a) where
+   zero = zero
 
-instance (TypeNum.Positive n, C a) => Phi (T n a) where
-   phis = phis
-   addPhis = addPhis
+instance (TypeNum.Positive n, C a) => Tuple.Phi (T n a) where
+   phi = phi
+   addPhi = addPhi
 
 
 size :: TypeNum.Positive n => T n a -> Int
@@ -148,10 +143,10 @@
    cons :: (TypeNum.Positive n) => LLVM.Vector n a -> T n a
    undef :: (TypeNum.Positive n) => T n a
    zero :: (TypeNum.Positive n) => T n a
-   phis ::
+   phi ::
       (TypeNum.Positive n) =>
       LLVM.BasicBlock -> T n a -> LLVM.CodeGenFunction r (T n a)
-   addPhis ::
+   addPhi ::
       (TypeNum.Positive n) =>
       LLVM.BasicBlock -> T n a -> T n a -> LLVM.CodeGenFunction r ()
 
@@ -171,8 +166,8 @@
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
    shuffle = shufflePrimitive
    extract = extractPrimitive
    insert = insertPrimitive
@@ -181,8 +176,8 @@
    cons = consPrimitive . fmap Bool8.toBool
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
    shuffle = shufflePrimitive
    extract = extractPrimitive
    insert = insertPrimitive
@@ -191,8 +186,8 @@
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
    shuffle = shufflePrimitive
    extract = extractPrimitive
    insert = insertPrimitive
@@ -201,18 +196,28 @@
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
    shuffle = shufflePrimitive
    extract = extractPrimitive
    insert = insertPrimitive
 
+instance C Int where
+   cons = consPrimitive
+   undef = undefPrimitive
+   zero = zeroPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
+   shuffle = shufflePrimitive
+   extract = extractPrimitive
+   insert = insertPrimitive
+
 instance C Int8 where
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
    shuffle = shufflePrimitive
    extract = extractPrimitive
    insert = insertPrimitive
@@ -221,8 +226,8 @@
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
    shuffle = shufflePrimitive
    extract = extractPrimitive
    insert = insertPrimitive
@@ -231,8 +236,8 @@
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
    shuffle = shufflePrimitive
    extract = extractPrimitive
    insert = insertPrimitive
@@ -241,18 +246,28 @@
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
    shuffle = shufflePrimitive
    extract = extractPrimitive
    insert = insertPrimitive
 
+instance C Word where
+   cons = consPrimitive
+   undef = undefPrimitive
+   zero = zeroPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
+   shuffle = shufflePrimitive
+   extract = extractPrimitive
+   insert = insertPrimitive
+
 instance C Word8 where
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
    shuffle = shufflePrimitive
    extract = extractPrimitive
    insert = insertPrimitive
@@ -261,8 +276,8 @@
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
    shuffle = shufflePrimitive
    extract = extractPrimitive
    insert = insertPrimitive
@@ -271,8 +286,8 @@
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
    shuffle = shufflePrimitive
    extract = extractPrimitive
    insert = insertPrimitive
@@ -281,85 +296,81 @@
    cons = consPrimitive
    undef = undefPrimitive
    zero = zeroPrimitive
-   phis = phisPrimitive
-   addPhis = addPhisPrimitive
+   phi = phiPrimitive
+   addPhi = addPhiPrimitive
    shuffle = shufflePrimitive
    extract = extractPrimitive
    insert = insertPrimitive
 
 consPrimitive ::
-   (TypeNum.Positive n, LLVM.IsConst al, IsPrimitive al,
-    Repr (Value n) a ~ Value n al) =>
+   (TypeNum.Positive n,
+    LLVM.IsConst al, IsPrimitive al, Tuple.VectorValueOf n a ~ Value n al) =>
    LLVM.Vector n al -> T n a
-consPrimitive = Cons . Compose . LLVM.valueOf
+consPrimitive = Cons . LLVM.valueOf
 
 undefPrimitive ::
-   (TypeNum.Positive n, IsPrimitive al,
-    Repr (Value n) a ~ Value n al) =>
+   (TypeNum.Positive n, IsPrimitive al, Tuple.VectorValueOf n a ~ Value n al) =>
    T n a
-undefPrimitive = Cons $ Compose $ LLVM.value LLVM.undef
+undefPrimitive = Cons $ LLVM.value LLVM.undef
 
 zeroPrimitive ::
-   (TypeNum.Positive n, IsPrimitive al,
-    Repr (Value n) a ~ Value n al) =>
+   (TypeNum.Positive n, IsPrimitive al, Tuple.VectorValueOf n a ~ Value n al) =>
    T n a
-zeroPrimitive = Cons $ Compose $ LLVM.value LLVM.zero
+zeroPrimitive = Cons $ LLVM.value LLVM.zero
 
-phisPrimitive ::
-   (TypeNum.Positive n, IsPrimitive al, Repr (Value n) a ~ Value n al) =>
+phiPrimitive ::
+   (TypeNum.Positive n, IsPrimitive al, Tuple.VectorValueOf n a ~ Value n al) =>
    LLVM.BasicBlock -> T n a -> LLVM.CodeGenFunction r (T n a)
-phisPrimitive bb (Cons (Compose a)) = fmap (Cons . Compose) $ Loop.phis bb a
+phiPrimitive bb (Cons a) = fmap Cons $ Tuple.phi bb a
 
-addPhisPrimitive ::
-   (TypeNum.Positive n, IsPrimitive al, Repr (Value n) a ~ Value n al) =>
+addPhiPrimitive ::
+   (TypeNum.Positive n, IsPrimitive al, Tuple.VectorValueOf n a ~ Value n al) =>
    LLVM.BasicBlock -> T n a -> T n a -> LLVM.CodeGenFunction r ()
-addPhisPrimitive bb (Cons (Compose a)) (Cons (Compose b)) = Loop.addPhis bb a b
+addPhiPrimitive bb (Cons a) (Cons b) = Tuple.addPhi bb a b
 
 
 shufflePrimitive ::
    (TypeNum.Positive n, TypeNum.Positive m, IsPrimitive al,
-    Repr LLVM.Value a ~ LLVM.Value al,
-    Repr (Value n) a ~ Value n al,
-    Repr (Value m) a ~ Value m al) =>
+    Tuple.ValueOf a ~ LLVM.Value al,
+    Tuple.VectorValueOf n a ~ Value n al,
+    Tuple.VectorValueOf m a ~ Value m al) =>
    LLVM.ConstValue (LLVM.Vector m Word32) ->
    T n a -> T n a -> CodeGenFunction r (T m a)
-shufflePrimitive k (Cons (Compose u)) (Cons (Compose v)) =
-   fmap (Cons . Compose) $ LLVM.shufflevector u v k
+shufflePrimitive k (Cons u) (Cons v) =
+   fmap Cons $ LLVM.shufflevector u v k
 
 extractPrimitive ::
    (TypeNum.Positive n, IsPrimitive al,
-    Repr LLVM.Value a ~ LLVM.Value al,
-    Repr (Value n) a ~ Value n al) =>
+    Tuple.ValueOf a ~ LLVM.Value al,
+    Tuple.VectorValueOf n a ~ Value n al) =>
    LLVM.Value Word32 -> T n a -> CodeGenFunction r (MultiValue.T a)
-extractPrimitive k (Cons (Compose v)) =
+extractPrimitive k (Cons v) =
    fmap MultiValue.Cons $ LLVM.extractelement v k
 
 insertPrimitive ::
    (TypeNum.Positive n, IsPrimitive al,
--- this constraint is accepted, but does not help
---    Repr f a ~ f a,
-    Repr LLVM.Value a ~ LLVM.Value al,
-    Repr (Value n) a ~ Value n al) =>
+    Tuple.ValueOf a ~ LLVM.Value al,
+    Tuple.VectorValueOf n a ~ Value n al) =>
    LLVM.Value Word32 ->
    MultiValue.T a -> T n a -> CodeGenFunction r (T n a)
-insertPrimitive k (MultiValue.Cons a) (Cons (Compose v)) =
-   fmap (Cons . Compose) $ LLVM.insertelement v a k
+insertPrimitive k (MultiValue.Cons a) (Cons v) =
+   fmap Cons $ LLVM.insertelement v a k
 
 
 instance (C a, C b) => C (a,b) where
-   cons v = zip (cons (fst <$> v)) (cons (snd <$> v))
+   cons v = case FuncHT.unzip v of (a,b) -> zip (cons a) (cons b)
    undef = zip undef undef
    zero = zip zero zero
 
-   phis bb a =
+   phi bb a =
       case unzip a of
          (a0,a1) ->
-            Monad.lift2 zip (phis bb a0) (phis bb a1)
-   addPhis bb a b =
+            Monad.lift2 zip (phi bb a0) (phi bb a1)
+   addPhi bb a b =
       case (unzip a, unzip b) of
          ((a0,a1), (b0,b1)) ->
-            addPhis bb a0 b0 >>
-            addPhis bb a1 b1
+            addPhi bb a0 b0 >>
+            addPhi bb a1 b1
 
    shuffle is u v =
       case (unzip u, unzip v) of
@@ -384,20 +395,20 @@
 
 
 instance (C a, C b, C c) => C (a,b,c) where
-   cons v = zip3 (cons (fst3 <$> v)) (cons (snd3 <$> v)) (cons (thd3 <$> v))
+   cons v = case FuncHT.unzip3 v of (a,b,c) -> zip3 (cons a) (cons b) (cons c)
    undef = zip3 undef undef undef
    zero = zip3 zero zero zero
 
-   phis bb a =
+   phi bb a =
       case unzip3 a of
          (a0,a1,a2) ->
-            Monad.lift3 zip3 (phis bb a0) (phis bb a1) (phis bb a2)
-   addPhis bb a b =
+            Monad.lift3 zip3 (phi bb a0) (phi bb a1) (phi bb a2)
+   addPhi bb a b =
       case (unzip3 a, unzip3 b) of
          ((a0,a1,a2), (b0,b1,b2)) ->
-            addPhis bb a0 b0 >>
-            addPhis bb a1 b1 >>
-            addPhis bb a2 b2
+            addPhi bb a0 b0 >>
+            addPhi bb a1 b1 >>
+            addPhi bb a2 b2
 
    shuffle is u v =
       case (unzip3 u, unzip3 v) of
@@ -434,10 +445,12 @@
 
 instance IntegerConstant Float  where fromInteger' = fromIntegerPrimitive
 instance IntegerConstant Double where fromInteger' = fromIntegerPrimitive
+instance IntegerConstant Word   where fromInteger' = fromIntegerPrimitive
 instance IntegerConstant Word8  where fromInteger' = fromIntegerPrimitive
 instance IntegerConstant Word16 where fromInteger' = fromIntegerPrimitive
 instance IntegerConstant Word32 where fromInteger' = fromIntegerPrimitive
 instance IntegerConstant Word64 where fromInteger' = fromIntegerPrimitive
+instance IntegerConstant Int   where fromInteger' = fromIntegerPrimitive
 instance IntegerConstant Int8  where fromInteger' = fromIntegerPrimitive
 instance IntegerConstant Int16 where fromInteger' = fromIntegerPrimitive
 instance IntegerConstant Int32 where fromInteger' = fromIntegerPrimitive
@@ -445,18 +458,18 @@
 
 fromIntegerPrimitive ::
    (TypeNum.Positive n, IsPrimitive a, SoV.IntegerConstant a,
-    Repr (Value n) a ~ Value n a) =>
+    Tuple.VectorValueOf n a ~ Value n a) =>
    Integer -> T n a
-fromIntegerPrimitive = Cons . Compose . LLVM.value . SoV.constFromInteger
+fromIntegerPrimitive = Cons . LLVM.value . SoV.constFromInteger
 
 instance RationalConstant Float  where fromRational' = fromRationalPrimitive
 instance RationalConstant Double where fromRational' = fromRationalPrimitive
 
 fromRationalPrimitive ::
    (TypeNum.Positive n, IsPrimitive a, SoV.RationalConstant a,
-    Repr (Value n) a ~ Value n a) =>
+    Tuple.VectorValueOf n a ~ Value n a) =>
    Rational -> T n a
-fromRationalPrimitive = Cons . Compose . LLVM.value . SoV.constFromRational
+fromRationalPrimitive = Cons . LLVM.value . SoV.constFromRational
 
 instance
    (TypeNum.Positive n, IntegerConstant a) =>
@@ -520,7 +533,7 @@
    (TypeNum.Positive n, C a) =>
    (MultiValue.T a -> CodeGenFunction r (MultiValue.T a)) ->
    MultiValue.T a -> CodeGenFunction r (T n a)
-iterate f x = fmap snd $ iterateCore f x Class.undefTuple
+iterate f x = fmap snd $ iterateCore f x Tuple.undef
 
 iterateCore ::
    (TypeNum.Positive n, C a) =>
@@ -694,45 +707,45 @@
 type PrimValue n a = LLVM.Value (LLVM.Vector n a)
 
 
-lift1 :: (Repr (Value n) a -> Repr (Value n) b) -> T n a -> T n b
+lift1 :: (Tuple.VectorValueOf n a -> Tuple.VectorValueOf n b) -> T n a -> T n b
 lift1 f (Cons a) = Cons $ f a
 
 _liftM0 ::
    (Monad m) =>
-   m (Repr (Value n) a) ->
+   m (Tuple.VectorValueOf n a) ->
    m (T n a)
 _liftM0 f = Monad.lift Cons f
 
 liftM0 ::
    (Monad m,
-    Repr (Value n) a ~ Value n a) =>
+    Tuple.VectorValueOf n a ~ Value n a) =>
    m (PrimValue n a) ->
    m (T n a)
 liftM0 f = Monad.lift consPrim f
 
 liftM ::
    (Monad m,
-    Repr (Value n) a ~ Value n a,
-    Repr (Value n) b ~ Value n b) =>
+    Tuple.VectorValueOf n a ~ Value n a,
+    Tuple.VectorValueOf n b ~ Value n b) =>
    (PrimValue n a -> m (PrimValue n b)) ->
    T n a -> m (T n b)
 liftM f a = Monad.lift consPrim $ f (deconsPrim a)
 
 liftM2 ::
    (Monad m,
-    Repr (Value n) a ~ Value n a,
-    Repr (Value n) b ~ Value n b,
-    Repr (Value n) c ~ Value n c) =>
+    Tuple.VectorValueOf n a ~ Value n a,
+    Tuple.VectorValueOf n b ~ Value n b,
+    Tuple.VectorValueOf n c ~ Value n c) =>
    (PrimValue n a -> PrimValue n b -> m (PrimValue n c)) ->
    T n a -> T n b -> m (T n c)
 liftM2 f a b = Monad.lift consPrim $ f (deconsPrim a) (deconsPrim b)
 
 liftM3 ::
    (Monad m,
-    Repr (Value n) a ~ Value n a,
-    Repr (Value n) b ~ Value n b,
-    Repr (Value n) c ~ Value n c,
-    Repr (Value n) d ~ Value n d) =>
+    Tuple.VectorValueOf n a ~ Value n a,
+    Tuple.VectorValueOf n b ~ Value n b,
+    Tuple.VectorValueOf n c ~ Value n c,
+    Tuple.VectorValueOf n d ~ Value n d) =>
    (PrimValue n a -> PrimValue n b -> PrimValue n c -> m (PrimValue n d)) ->
    T n a -> T n b -> T n c -> m (T n d)
 liftM3 f a b c =
@@ -757,6 +770,9 @@
 instance Additive Double where
    add = liftM2 LLVM.add; sub = liftM2 LLVM.sub; neg = liftM LLVM.neg
 
+instance Additive Int where
+   add = liftM2 LLVM.add; sub = liftM2 LLVM.sub; neg = liftM LLVM.neg
+
 instance Additive Int8 where
    add = liftM2 LLVM.add; sub = liftM2 LLVM.sub; neg = liftM LLVM.neg
 
@@ -769,6 +785,9 @@
 instance Additive Int64 where
    add = liftM2 LLVM.add; sub = liftM2 LLVM.sub; neg = liftM LLVM.neg
 
+instance Additive Word where
+   add = liftM2 LLVM.add; sub = liftM2 LLVM.sub; neg = liftM LLVM.neg
+
 instance Additive Word8 where
    add = liftM2 LLVM.add; sub = liftM2 LLVM.sub; neg = liftM LLVM.neg
 
@@ -933,10 +952,12 @@
 instance Select Float where select = liftM3 LLVM.select
 instance Select Double where select = liftM3 LLVM.select
 instance Select Bool where select = liftM3 LLVM.select
+instance Select Word where select = liftM3 LLVM.select
 instance Select Word8 where select = liftM3 LLVM.select
 instance Select Word16 where select = liftM3 LLVM.select
 instance Select Word32 where select = liftM3 LLVM.select
 instance Select Word64 where select = liftM3 LLVM.select
+instance Select Int where select = liftM3 LLVM.select
 instance Select Int8 where select = liftM3 LLVM.select
 instance Select Int16 where select = liftM3 LLVM.select
 instance Select Int32 where select = liftM3 LLVM.select
@@ -969,10 +990,12 @@
 
 instance Comparison Float where cmp = liftM2 . LLVM.cmp
 instance Comparison Double where cmp = liftM2 . LLVM.cmp
+instance Comparison Word where cmp = liftM2 . LLVM.cmp
 instance Comparison Word8 where cmp = liftM2 . LLVM.cmp
 instance Comparison Word16 where cmp = liftM2 . LLVM.cmp
 instance Comparison Word32 where cmp = liftM2 . LLVM.cmp
 instance Comparison Word64 where cmp = liftM2 . LLVM.cmp
+instance Comparison Int where cmp = liftM2 . LLVM.cmp
 instance Comparison Int8 where cmp = liftM2 . LLVM.cmp
 instance Comparison Int16 where cmp = liftM2 . LLVM.cmp
 instance Comparison Int32 where cmp = liftM2 . LLVM.cmp
@@ -1041,6 +1064,9 @@
    shl :: (TypeNum.Positive n) => T n a -> T n a -> LLVM.CodeGenFunction r (T n a)
    shr :: (TypeNum.Positive n) => T n a -> T n a -> LLVM.CodeGenFunction r (T n a)
 
+instance BitShift Word where
+   shl = liftM2 LLVM.shl; shr = liftM2 LLVM.lshr
+
 instance BitShift Word8 where
    shl = liftM2 LLVM.shl; shr = liftM2 LLVM.lshr
 
@@ -1052,6 +1078,9 @@
 
 instance BitShift Word64 where
    shl = liftM2 LLVM.shl; shr = liftM2 LLVM.lshr
+
+instance BitShift Int where
+   shl = liftM2 LLVM.shl; shr = liftM2 LLVM.ashr
 
 instance BitShift Int8 where
    shl = liftM2 LLVM.shl; shr = liftM2 LLVM.ashr
diff --git a/src/LLVM/Extra/Multi/Vector/Instance.hs b/src/LLVM/Extra/Multi/Vector/Instance.hs
--- a/src/LLVM/Extra/Multi/Vector/Instance.hs
+++ b/src/LLVM/Extra/Multi/Vector/Instance.hs
@@ -5,13 +5,11 @@
 
 import qualified LLVM.Extra.Multi.Vector as Vector
 import qualified LLVM.Extra.Multi.Value.Private as MultiValue
-import LLVM.Extra.Multi.Value.Private (Repr, )
 
 import qualified LLVM.Core as LLVM
 
 import qualified Type.Data.Num.Decimal as TypeNum
 
-import Data.Functor.Compose (Compose, )
 import Data.Functor ((<$>), )
 
 import Prelude2010
@@ -50,12 +48,11 @@
 instance
    (TypeNum.Positive n, Vector.C a) =>
       MultiValue.C (LLVM.Vector n a) where
-   type Repr f (LLVM.Vector n a) = Repr (Compose f (LLVM.Vector n)) a
    cons = toMultiValue . Vector.cons
    undef = toMultiValue Vector.undef
    zero = toMultiValue Vector.zero
-   phis = liftMultiValueM . Vector.phis
-   addPhis bb x y = Vector.addPhis bb (fromMultiValue x) (fromMultiValue y)
+   phi = liftMultiValueM . Vector.phi
+   addPhi bb x y = Vector.addPhi bb (fromMultiValue x) (fromMultiValue y)
 
 instance
    (TypeNum.Positive n, Vector.IntegerConstant a) =>
diff --git a/src/LLVM/Extra/Multi/Vector/Memory.hs b/src/LLVM/Extra/Multi/Vector/Memory.hs
deleted file mode 100644
--- a/src/LLVM/Extra/Multi/Vector/Memory.hs
+++ /dev/null
@@ -1,172 +0,0 @@
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE UndecidableInstances #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE TypeOperators #-}
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-module LLVM.Extra.Multi.Vector.Memory where
-
-import qualified LLVM.Extra.Multi.Vector as MultiVector
-import qualified LLVM.Extra.Multi.Vector.Instance as Inst
-import qualified LLVM.Extra.Multi.Value.Memory as MultiMem
-import LLVM.Extra.MemoryPrivate (decomposeFromLoad, composeFromStore, )
-
-import qualified LLVM.Core as LLVM
-import LLVM.Core (CodeGenFunction, Value, )
-
-import qualified Type.Data.Num.Decimal as TypeNum
-import Type.Data.Num.Decimal ((:*:), )
-
-import Foreign.Ptr (Ptr, )
-
-import Control.Applicative (liftA2, liftA3, )
-
-import Data.Word (Word8, Word16, Word32, Word64)
-import Data.Int (Int8, Int16, Int32, Int64)
-
-
-class
-   (TypeNum.Positive n, MultiVector.C a, LLVM.IsSized (Struct n a)) =>
-      C n a where
-   {-# MINIMAL (load|decompose), (store|compose) #-}
-   type Struct n a :: *
-   load :: Value (Ptr (Struct n a)) -> CodeGenFunction r (MultiVector.T n a)
-   load ptr  =  decompose =<< LLVM.load ptr
-   store :: MultiVector.T n a -> Value (Ptr (Struct n a)) -> CodeGenFunction r ()
-   store r ptr  =  flip LLVM.store ptr =<< compose r
-   decompose :: Value (Struct n a) -> CodeGenFunction r (MultiVector.T n a)
-   decompose = decomposeFromLoad load
-   compose :: MultiVector.T n a -> CodeGenFunction r (Value (Struct n a))
-   compose = composeFromStore store
-
-instance
-   (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D8)) =>
-      C n Word8 where
-   type Struct n Word8 = LLVM.Vector n Word8
-   load = fmap MultiVector.consPrim . LLVM.load
-   store = LLVM.store . MultiVector.deconsPrim
-   decompose = return . MultiVector.consPrim
-   compose = return . MultiVector.deconsPrim
-
-instance
-   (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D16)) =>
-      C n Word16 where
-   type Struct n Word16 = LLVM.Vector n Word16
-   load = fmap MultiVector.consPrim . LLVM.load
-   store = LLVM.store . MultiVector.deconsPrim
-   decompose = return . MultiVector.consPrim
-   compose = return . MultiVector.deconsPrim
-
-instance
-   (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D32)) =>
-      C n Word32 where
-   type Struct n Word32 = LLVM.Vector n Word32
-   load = fmap MultiVector.consPrim . LLVM.load
-   store = LLVM.store . MultiVector.deconsPrim
-   decompose = return . MultiVector.consPrim
-   compose = return . MultiVector.deconsPrim
-
-instance
-   (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D64)) =>
-      C n Word64 where
-   type Struct n Word64 = LLVM.Vector n Word64
-   load = fmap MultiVector.consPrim . LLVM.load
-   store = LLVM.store . MultiVector.deconsPrim
-   decompose = return . MultiVector.consPrim
-   compose = return . MultiVector.deconsPrim
-
-instance
-   (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D8)) =>
-      C n Int8 where
-   type Struct n Int8 = LLVM.Vector n Int8
-   load = fmap MultiVector.consPrim . LLVM.load
-   store = LLVM.store . MultiVector.deconsPrim
-   decompose = return . MultiVector.consPrim
-   compose = return . MultiVector.deconsPrim
-
-instance
-   (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D16)) =>
-      C n Int16 where
-   type Struct n Int16 = LLVM.Vector n Int16
-   load = fmap MultiVector.consPrim . LLVM.load
-   store = LLVM.store . MultiVector.deconsPrim
-   decompose = return . MultiVector.consPrim
-   compose = return . MultiVector.deconsPrim
-
-instance
-   (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D32)) =>
-      C n Int32 where
-   type Struct n Int32 = LLVM.Vector n Int32
-   load = fmap MultiVector.consPrim . LLVM.load
-   store = LLVM.store . MultiVector.deconsPrim
-   decompose = return . MultiVector.consPrim
-   compose = return . MultiVector.deconsPrim
-
-instance
-   (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D64)) =>
-      C n Int64 where
-   type Struct n Int64 = LLVM.Vector n Int64
-   load = fmap MultiVector.consPrim . LLVM.load
-   store = LLVM.store . MultiVector.deconsPrim
-   decompose = return . MultiVector.consPrim
-   compose = return . MultiVector.deconsPrim
-
-instance
-   (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D32)) =>
-      C n Float where
-   type Struct n Float = LLVM.Vector n Float
-   load = fmap MultiVector.consPrim . LLVM.load
-   store = LLVM.store . MultiVector.deconsPrim
-   decompose = return . MultiVector.consPrim
-   compose = return . MultiVector.deconsPrim
-
-instance
-   (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D64)) =>
-      C n Double where
-   type Struct n Double = LLVM.Vector n Double
-   load = fmap MultiVector.consPrim . LLVM.load
-   store = LLVM.store . MultiVector.deconsPrim
-   decompose = return . MultiVector.consPrim
-   compose = return . MultiVector.deconsPrim
-
-instance (C n a, C n b) => C n (a,b) where
-   type Struct n (a,b) = (LLVM.Struct (Struct n a, (Struct n b, ())))
-   decompose ab =
-      liftA2 MultiVector.zip
-         (decompose =<< LLVM.extractvalue ab TypeNum.d0)
-         (decompose =<< LLVM.extractvalue ab TypeNum.d1)
-   compose ab =
-      case MultiVector.unzip ab of
-         (a,b) -> do
-            sa <- compose a
-            sb <- compose b
-            ra <- LLVM.insertvalue (LLVM.value LLVM.undef) sa TypeNum.d0
-            LLVM.insertvalue ra sb TypeNum.d1
-
-instance (C n a, C n b, C n c) => C n (a,b,c) where
-   type Struct n (a,b,c) =
-         (LLVM.Struct (Struct n a, (Struct n b, (Struct n c, ()))))
-   decompose abc =
-      liftA3 MultiVector.zip3
-         (decompose =<< LLVM.extractvalue abc TypeNum.d0)
-         (decompose =<< LLVM.extractvalue abc TypeNum.d1)
-         (decompose =<< LLVM.extractvalue abc TypeNum.d2)
-   compose abc =
-      case MultiVector.unzip3 abc of
-         (a,b,c) -> do
-            sa <- compose a
-            sb <- compose b
-            sc <- compose c
-            ra <- LLVM.insertvalue (LLVM.value LLVM.undef) sa TypeNum.d0
-            rb <- LLVM.insertvalue ra sb TypeNum.d1
-            LLVM.insertvalue rb sc TypeNum.d2
-
-
--- orphan
-instance (C n a) => MultiMem.C (LLVM.Vector n a) where
-   type Struct (LLVM.Vector n a) = Struct n a
-   load = fmap Inst.toMultiValue . load
-   store = store . Inst.fromMultiValue
-   decompose = fmap Inst.toMultiValue . decompose
-   compose = compose . Inst.fromMultiValue
diff --git a/src/LLVM/Extra/Scalar.hs b/src/LLVM/Extra/Scalar.hs
--- a/src/LLVM/Extra/Scalar.hs
+++ b/src/LLVM/Extra/Scalar.hs
@@ -1,12 +1,9 @@
 {-# LANGUAGE TypeFamilies #-}
 module LLVM.Extra.Scalar where
 
-import qualified LLVM.Extra.Class as Class
+import qualified LLVM.Extra.Tuple as Tuple
 import qualified LLVM.Extra.Arithmetic as A
 
-import qualified LLVM.Util.Loop as Loop
-import LLVM.Util.Loop (Phi, )
-
 import qualified Control.Monad as Monad
 
 
@@ -66,15 +63,15 @@
    Monad.liftM decons $ f (Cons a) (Cons b) (Cons c) (Cons d) (Cons e)
 
 
-instance (Class.Zero a) => Class.Zero (T a) where
-   zeroTuple = Cons Class.zeroTuple
+instance (Tuple.Zero a) => Tuple.Zero (T a) where
+   zero = Cons Tuple.zero
 
-instance (Class.Undefined a) => Class.Undefined (T a) where
-   undefTuple = Cons Class.undefTuple
+instance (Tuple.Undefined a) => Tuple.Undefined (T a) where
+   undef = Cons Tuple.undef
 
-instance (Phi a) => Phi (T a) where
-   phis bb = fmap Cons . Loop.phis bb . decons
-   addPhis bb (Cons a) (Cons b) = Loop.addPhis bb a b
+instance (Tuple.Phi a) => Tuple.Phi (T a) where
+   phi bb = fmap Cons . Tuple.phi bb . decons
+   addPhi bb (Cons a) (Cons b) = Tuple.addPhi bb a b
 
 instance (A.IntegerConstant a) => A.IntegerConstant (T a) where
    fromInteger' = Cons . A.fromInteger'
diff --git a/src/LLVM/Extra/ScalarOrVector.hs b/src/LLVM/Extra/ScalarOrVector.hs
--- a/src/LLVM/Extra/ScalarOrVector.hs
+++ b/src/LLVM/Extra/ScalarOrVector.hs
@@ -49,7 +49,7 @@
 
 import qualified Type.Data.Num.Decimal as TypeNum
 
-import Data.Word (Word8, Word16, Word32, Word64, )
+import Data.Word (Word8, Word16, Word32, Word64, Word)
 import Data.Int  (Int8,  Int16,  Int32,  Int64, )
 import Data.Maybe (fromMaybe)
 
@@ -228,10 +228,12 @@
       A.signumGen minusOne one x
 
 
+instance Real Int    where min = A.min; max = A.max; signum = A.signum; abs = A.abs;
 instance Real Int8   where min = A.min; max = A.max; signum = A.signum; abs = A.abs;
 instance Real Int16  where min = A.min; max = A.max; signum = A.signum; abs = A.abs;
 instance Real Int32  where min = A.min; max = A.max; signum = A.signum; abs = A.abs;
 instance Real Int64  where min = A.min; max = A.max; signum = A.signum; abs = A.abs;
+instance Real Word   where min = A.min; max = A.max; signum = A.signum; abs = return;
 instance Real Word8  where min = A.min; max = A.max; signum = A.signum; abs = return;
 instance Real Word16 where min = A.min; max = A.max; signum = A.signum; abs = return;
 instance Real Word32 where min = A.min; max = A.max; signum = A.signum; abs = return;
@@ -254,6 +256,8 @@
 class (IsInteger a) => Saturated a where
    addSat, subSat :: Value a -> Value a -> CodeGenFunction r (Value a)
 
+instance Saturated Int    where
+   addSat = addSatProxy LP.Proxy; subSat = subSatProxy LP.Proxy;
 instance Saturated Int8   where
    addSat = addSatProxy LP.Proxy; subSat = subSatProxy LP.Proxy;
 instance Saturated Int16  where
@@ -262,6 +266,8 @@
    addSat = addSatProxy LP.Proxy; subSat = subSatProxy LP.Proxy;
 instance Saturated Int64  where
    addSat = addSatProxy LP.Proxy; subSat = subSatProxy LP.Proxy;
+instance Saturated Word   where
+   addSat = addSatProxy LP.Proxy; subSat = subSatProxy LP.Proxy;
 instance Saturated Word8  where
    addSat = addSatProxy LP.Proxy; subSat = subSatProxy LP.Proxy;
 instance Saturated Word16 where
@@ -302,10 +308,12 @@
    scale :: (a ~ Scalar v) => Value a -> Value v -> CodeGenFunction r (Value v)
    scaleConst :: (a ~ Scalar v) => ConstValue a -> ConstValue v -> CodeGenFunction r (ConstValue v)
 
+instance PseudoModule Word   where scale = LLVM.mul; scaleConst = LLVM.mul
 instance PseudoModule Word8  where scale = LLVM.mul; scaleConst = LLVM.mul
 instance PseudoModule Word16 where scale = LLVM.mul; scaleConst = LLVM.mul
 instance PseudoModule Word32 where scale = LLVM.mul; scaleConst = LLVM.mul
 instance PseudoModule Word64 where scale = LLVM.mul; scaleConst = LLVM.mul
+instance PseudoModule Int    where scale = LLVM.mul; scaleConst = LLVM.mul
 instance PseudoModule Int8   where scale = LLVM.mul; scaleConst = LLVM.mul
 instance PseudoModule Int16  where scale = LLVM.mul; scaleConst = LLVM.mul
 instance PseudoModule Int32  where scale = LLVM.mul; scaleConst = LLVM.mul
@@ -322,10 +330,12 @@
 class (LLVM.IsConst a) => IntegerConstant a where
    constFromInteger :: Integer -> ConstValue a
 
+instance IntegerConstant Word   where constFromInteger = constOf . fromInteger
 instance IntegerConstant Word8  where constFromInteger = constOf . fromInteger
 instance IntegerConstant Word16 where constFromInteger = constOf . fromInteger
 instance IntegerConstant Word32 where constFromInteger = constOf . fromInteger
 instance IntegerConstant Word64 where constFromInteger = constOf . fromInteger
+instance IntegerConstant Int    where constFromInteger = constOf . fromInteger
 instance IntegerConstant Int8   where constFromInteger = constOf . fromInteger
 instance IntegerConstant Int16  where constFromInteger = constOf . fromInteger
 instance IntegerConstant Int32  where constFromInteger = constOf . fromInteger
diff --git a/src/LLVM/Extra/Storable.hs b/src/LLVM/Extra/Storable.hs
new file mode 100644
--- /dev/null
+++ b/src/LLVM/Extra/Storable.hs
@@ -0,0 +1,47 @@
+{- |
+Transfer values between Haskell and JIT generated code
+in a Haskell-compatible format as dictated by the 'Foreign.Storable' class.
+E.g. instance 'Bool' may use more than a byte (e.g. Word32).
+For tuples, you may use the @Tuple@ wrapper from the @storable-record@ package.
+The 'Storable' instance for 'Vector's is compatible with arrays,
+i.e. indices always count upwards irrespective of machine endianess
+and tuple elements are interleaved.
+-}
+module LLVM.Extra.Storable (
+   -- * Basic class
+   Store.C(..),
+   Store.storeNext,
+   Store.modify,
+
+   -- * Classes for tuples and vectors
+   Store.Tuple(..),
+   Store.Vector(..),
+   Store.TupleVector(..),
+
+   -- * MultiValue support
+   Store.loadMultiValue,
+   Store.storeMultiValue,
+   Store.storeNextMultiValue,
+   Store.modifyMultiValue,
+
+   -- * Standard method implementations
+   Store.loadNewtype,
+   Store.storeNewtype,
+   Store.loadTraversable,
+   Store.loadApplicative,
+   Store.storeFoldable,
+
+   -- * Pointer handling
+   Store.advancePtr,
+   Store.incrementPtr,
+   Store.decrementPtr,
+
+   -- * Loops over Storable arrays
+   Array.arrayLoop,
+   Array.arrayLoop2,
+   Array.arrayLoopMaybeCont,
+   Array.arrayLoopMaybeCont2,
+   ) where
+
+import qualified LLVM.Extra.Storable.Private as Store
+import qualified LLVM.Extra.Storable.Array as Array
diff --git a/src/LLVM/Extra/Storable/Array.hs b/src/LLVM/Extra/Storable/Array.hs
new file mode 100644
--- /dev/null
+++ b/src/LLVM/Extra/Storable/Array.hs
@@ -0,0 +1,75 @@
+{-# LANGUAGE TypeFamilies #-}
+{- |
+Loops over Storable arrays.
+-}
+module LLVM.Extra.Storable.Array where
+
+import qualified LLVM.Extra.Storable.Private as Storable
+import qualified LLVM.Extra.MaybeContinuation as MaybeCont
+import qualified LLVM.Extra.Maybe as Maybe
+import qualified LLVM.Extra.Tuple as Tuple
+import qualified LLVM.Extra.Control as C
+import LLVM.Core
+   (CodeGenFunction, Value, CmpRet, IsInteger, IsConst, IsPrimitive)
+
+import Foreign.Ptr (Ptr)
+
+import Control.Monad (liftM2)
+
+import Data.Tuple.HT (mapSnd)
+
+
+arrayLoop ::
+   (Tuple.Phi s, Num i, IsConst i, IsInteger i, CmpRet i, IsPrimitive i,
+    Storable.C a, Value (Ptr a) ~ ptrA) =>
+   Value i -> ptrA -> s ->
+   (ptrA -> s -> CodeGenFunction r s) ->
+   CodeGenFunction r s
+arrayLoop len ptr start body =
+   fmap snd $
+   C.fixedLengthLoop len (ptr, start) $ \(p,s) ->
+      liftM2 (,) (Storable.incrementPtr p) (body p s)
+
+arrayLoop2 ::
+   (Tuple.Phi s, Num i, IsConst i, IsInteger i, CmpRet i, IsPrimitive i,
+    Storable.C a, Value (Ptr a) ~ ptrA,
+    Storable.C b, Value (Ptr b) ~ ptrB) =>
+   Value i -> ptrA -> ptrB -> s ->
+   (ptrA -> ptrB -> s -> CodeGenFunction r s) ->
+   CodeGenFunction r s
+arrayLoop2 len ptrA ptrB start body =
+   fmap snd $
+   arrayLoop len ptrA (ptrB,start) $ \pa (pb,s) ->
+      liftM2 (,) (Storable.incrementPtr pb) (body pa pb s)
+
+
+arrayLoopMaybeCont ::
+   (Tuple.Phi s, Tuple.Undefined s, Num i, IsConst i, IsInteger i, CmpRet i, IsPrimitive i,
+    Storable.C a, Value (Ptr a) ~ ptrA,
+    Maybe.T (ptrA, s) ~ z) =>
+   Value i ->
+   ptrA -> s ->
+   (ptrA -> s -> MaybeCont.T r z s) ->
+   CodeGenFunction r (Value i, Maybe.T s)
+arrayLoopMaybeCont len ptr start body =
+   fmap (mapSnd (fmap snd)) $
+   MaybeCont.fixedLengthLoop len (ptr,start) $ \(ptr0,s0) ->
+      liftM2 (,)
+         (MaybeCont.lift $ Storable.incrementPtr ptr0)
+         (body ptr0 s0)
+
+arrayLoopMaybeCont2 ::
+   (Tuple.Phi s, Tuple.Undefined s, Num i, IsConst i, IsInteger i, CmpRet i, IsPrimitive i,
+    Storable.C a, Value (Ptr a) ~ ptrA,
+    Storable.C b, Value (Ptr b) ~ ptrB,
+    Maybe.T (ptrA, (ptrB, s)) ~ z) =>
+   Value i ->
+   ptrA -> ptrB -> s ->
+   (ptrA -> ptrB -> s -> MaybeCont.T r z s) ->
+   CodeGenFunction r (Value i, Maybe.T s)
+arrayLoopMaybeCont2 len ptrA ptrB start body =
+   fmap (mapSnd (fmap snd)) $
+   arrayLoopMaybeCont len ptrA (ptrB,start) $ \ptrAi (ptrB0,s0) ->
+      liftM2 (,)
+         (MaybeCont.lift $ Storable.incrementPtr ptrB0)
+         (body ptrAi ptrB0 s0)
diff --git a/src/LLVM/Extra/Storable/Private.hs b/src/LLVM/Extra/Storable/Private.hs
new file mode 100644
--- /dev/null
+++ b/src/LLVM/Extra/Storable/Private.hs
@@ -0,0 +1,499 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE UndecidableInstances #-}
+module LLVM.Extra.Storable.Private where
+
+import qualified LLVM.Extra.Multi.Value as MultiValue
+import qualified LLVM.Extra.Tuple as Tuple
+import qualified LLVM.Extra.ArithmeticPrivate as A
+import qualified LLVM.Util.Proxy as LP
+import qualified LLVM.Core as LLVM
+import LLVM.Core (CodeGenFunction, Value)
+
+import qualified Type.Data.Num.Decimal as TypeNum
+
+import qualified Control.Monad.Trans.Class as MT
+import qualified Control.Monad.Trans.Reader as MR
+import qualified Control.Monad.Trans.State as MS
+import qualified Control.Applicative.HT as App
+import qualified Control.Functor.HT as FuncHT
+import Control.Monad (foldM, replicateM, replicateM_, (<=<))
+import Control.Applicative (Applicative, pure)
+
+import qualified Foreign.Storable.Record.Tuple as StoreTuple
+import qualified Foreign.Storable as Store
+import Foreign.Storable.FixedArray (roundUp)
+import Foreign.Ptr (Ptr)
+
+import qualified Data.NonEmpty.Class as NonEmptyC
+import qualified Data.Traversable as Trav
+import qualified Data.Foldable as Fold
+import Data.Orphans ()
+import Data.Complex (Complex)
+import Data.Word (Word8, Word16, Word32, Word64, Word)
+import Data.Int  (Int8,  Int16,  Int32,  Int64)
+import Data.Bool8 (Bool8)
+
+
+
+class
+   (Store.Storable a, Tuple.Value a,
+    Tuple.Phi (Tuple.ValueOf a), Tuple.Undefined (Tuple.ValueOf a)) =>
+      C a where
+
+   {-
+   Not all Storable types have a compatible LLVM type,
+   or even more, one LLVM type that is compatible on all platforms.
+   -}
+   load :: Value (Ptr a) -> CodeGenFunction r (Tuple.ValueOf a)
+   store :: Tuple.ValueOf a -> Value (Ptr a) -> CodeGenFunction r ()
+
+storeNext ::
+   (C a, Tuple.ValueOf a ~ al, Value (Ptr a) ~ ptr) =>
+   al -> ptr -> CodeGenFunction r ptr
+storeNext a ptr  =  store a ptr >> incrementPtr ptr
+
+modify ::
+   (C a, Tuple.ValueOf a ~ al) =>
+   (al -> CodeGenFunction r al) ->
+   Value (Ptr a) -> CodeGenFunction r ()
+modify f ptr  =  flip store ptr =<< f =<< load ptr
+
+
+loadMultiValue ::
+   (C a) => Value (Ptr a) -> CodeGenFunction r (MultiValue.T a)
+loadMultiValue ptr = fmap MultiValue.Cons $ load ptr
+
+storeMultiValue ::
+   (C a) => MultiValue.T a -> Value (Ptr a) -> CodeGenFunction r ()
+storeMultiValue (MultiValue.Cons a) ptr = store a ptr
+
+storeNextMultiValue ::
+   (C a) => MultiValue.T a -> Value (Ptr a) -> CodeGenFunction r (Value (Ptr a))
+storeNextMultiValue (MultiValue.Cons a) ptr =
+   store a ptr >> incrementPtr ptr
+
+modifyMultiValue ::
+   (C a) =>
+   (MultiValue.T a -> CodeGenFunction r (MultiValue.T a)) ->
+   Value (Ptr a) -> CodeGenFunction r ()
+modifyMultiValue f ptr =
+   flip storeMultiValue ptr =<< f =<< loadMultiValue ptr
+
+
+loadPrimitive ::
+   (LLVM.Storable a) => Value (Ptr a) -> CodeGenFunction r (Value a)
+loadPrimitive ptr = LLVM.load =<< LLVM.bitcast ptr
+
+storePrimitive ::
+   (LLVM.Storable a) => Value a -> Value (Ptr a) -> CodeGenFunction r ()
+storePrimitive a ptr = LLVM.store a =<< LLVM.bitcast ptr
+
+instance C Float where
+   load = loadPrimitive; store = storePrimitive
+
+instance C Double where
+   load = loadPrimitive; store = storePrimitive
+
+instance C Word where
+   load = loadPrimitive; store = storePrimitive
+
+instance C Word8 where
+   load = loadPrimitive; store = storePrimitive
+
+instance C Word16 where
+   load = loadPrimitive; store = storePrimitive
+
+instance C Word32 where
+   load = loadPrimitive; store = storePrimitive
+
+instance C Word64 where
+   load = loadPrimitive; store = storePrimitive
+
+instance C Int where
+   load = loadPrimitive; store = storePrimitive
+
+instance C Int8 where
+   load = loadPrimitive; store = storePrimitive
+
+instance C Int16 where
+   load = loadPrimitive; store = storePrimitive
+
+instance C Int32 where
+   load = loadPrimitive; store = storePrimitive
+
+instance C Int64 where
+   load = loadPrimitive; store = storePrimitive
+
+{- |
+Not very efficient implementation
+because we want to adapt to @sizeOf Bool@ dynamically.
+Unfortunately, LLVM-9's optimizer does not recognize the instruction pattern.
+Better use 'Bool8' for booleans.
+-}
+instance C Bool where
+   load ptr = do
+      bytePtr <- castToBytePtr ptr
+      bytes <-
+         flip MS.evalStateT bytePtr $
+            replicateM (Store.sizeOf (False :: Bool))
+               (MT.lift . LLVM.load =<< incPtrState)
+      let zero = LLVM.valueOf 0
+      mask <- foldM A.or zero bytes
+      A.cmp LLVM.CmpNE mask zero
+   store b ptr = do
+      bytePtr <- castToBytePtr ptr
+      byte <- LLVM.sext b
+      flip MS.evalStateT bytePtr $
+         replicateM_ (Store.sizeOf (False :: Bool))
+            (MT.lift . LLVM.store byte =<< incPtrState)
+
+incPtrState :: MS.StateT BytePtr (CodeGenFunction r) BytePtr
+incPtrState = update A.advanceArrayElementPtr
+
+instance C Bool8 where
+   load ptr =
+      A.cmp LLVM.CmpNE (LLVM.valueOf 0) =<< LLVM.load =<< castToBytePtr ptr
+   store b ptr = do
+      byte <- LLVM.zext b
+      LLVM.store byte =<< castToBytePtr ptr
+
+instance (C a) => C (Complex a) where
+   load = loadApplicative; store = storeFoldable
+
+
+
+instance (Tuple tuple) => C (StoreTuple.Tuple tuple) where
+   load = loadTuple
+   store = storeTuple
+
+class
+   (StoreTuple.Storable tuple, Tuple.Value tuple,
+    Tuple.Phi (Tuple.ValueOf tuple), Tuple.Undefined (Tuple.ValueOf tuple)) =>
+      Tuple tuple where
+   loadTuple ::
+      Value (Ptr (StoreTuple.Tuple tuple)) ->
+      CodeGenFunction r (Tuple.ValueOf tuple)
+   storeTuple ::
+      Tuple.ValueOf tuple ->
+      Value (Ptr (StoreTuple.Tuple tuple)) ->
+      CodeGenFunction r ()
+
+instance (C a, C b) => Tuple (a,b) where
+   loadTuple ptr =
+      runElements ptr $
+         App.mapPair (loadElement, loadElement) $
+         FuncHT.unzip $ proxyFromElement3 ptr
+   storeTuple (a,b) ptr =
+      case FuncHT.unzip $ proxyFromElement3 ptr of
+         (pa,pb) -> runElements ptr $ storeElement pa a >> storeElement pb b
+
+instance (C a, C b, C c) => Tuple (a,b,c) where
+   loadTuple ptr =
+      runElements ptr $
+         App.mapTriple (loadElement, loadElement, loadElement) $
+         FuncHT.unzip3 $ proxyFromElement3 ptr
+   storeTuple (a,b,c) ptr =
+      case FuncHT.unzip3 $ proxyFromElement3 ptr of
+         (pa,pb,pc) ->
+            runElements ptr $
+               storeElement pa a >> storeElement pb b >> storeElement pc c
+
+runElements ::
+   Value (Ptr a) ->
+   MR.ReaderT BytePtr (MS.StateT Int (CodeGenFunction r)) c ->
+   CodeGenFunction r c
+runElements ptr act = do
+   bytePtr <- castToBytePtr ptr
+   flip MS.evalStateT 0 $ flip MR.runReaderT bytePtr act
+
+loadElement ::
+   (C a) =>
+   LP.Proxy a ->
+   MR.ReaderT BytePtr (MS.StateT Int (CodeGenFunction r)) (Tuple.ValueOf a)
+loadElement proxy =
+   MT.lift . MT.lift . load =<< elementPtr proxy
+
+storeElement ::
+   (C a) =>
+   LP.Proxy a -> Tuple.ValueOf a ->
+   MR.ReaderT BytePtr (MS.StateT Int (CodeGenFunction r)) ()
+storeElement proxy a =
+   MT.lift . MT.lift . store a =<< elementPtr proxy
+
+elementPtr ::
+   (C a) =>
+   LP.Proxy a ->
+   MR.ReaderT BytePtr
+      (MS.StateT Int (CodeGenFunction r)) (LLVM.Value (Ptr a))
+elementPtr proxy = do
+   ptr <- MR.ask
+   MT.lift $ do
+      offset <- elementOffset proxy
+      MT.lift $ castFromBytePtr =<< LLVM.getElementPtr ptr (offset, ())
+
+elementOffset ::
+   (Monad m, Store.Storable a) => LP.Proxy a -> MS.StateT Int m Int
+elementOffset proxy = do
+   let dummy = elementFromProxy proxy
+   MS.modify (roundUp $ Store.alignment dummy)
+   offset <- MS.get
+   MS.modify (+ Store.sizeOf dummy)
+   return offset
+
+
+instance
+   (TypeNum.Positive n, Vector a, Tuple.VectorValue n a,
+    Tuple.Phi (Tuple.VectorValueOf n a)) =>
+      C (LLVM.Vector n a) where
+   load ptr =
+      assembleVector (proxyFromElement3 ptr) =<< loadApplicative ptr
+   store a ptr =
+      flip storeFoldable ptr
+         =<< disassembleVector (proxyFromElement3 ptr) a
+
+class (C a) => Vector a where
+   assembleVector ::
+      (TypeNum.Positive n) =>
+      LP.Proxy a -> LLVM.Vector n (Tuple.ValueOf a) ->
+      CodeGenFunction r (Tuple.VectorValueOf n a)
+   disassembleVector ::
+      (TypeNum.Positive n) =>
+      LP.Proxy a -> Tuple.VectorValueOf n a ->
+      CodeGenFunction r (LLVM.Vector n (Tuple.ValueOf a))
+
+assemblePrimitive ::
+   (TypeNum.Positive n, LLVM.IsPrimitive a) =>
+   LLVM.Vector n (Value a) -> CodeGenFunction r (Value (LLVM.Vector n a))
+assemblePrimitive =
+   foldM
+      (\v (i,x) -> LLVM.insertelement v x (LLVM.valueOf i))
+      (LLVM.value LLVM.undef)
+    . zip [0..] . Fold.toList
+
+disassemblePrimitive ::
+   (TypeNum.Positive n, LLVM.IsPrimitive a) =>
+   Value (LLVM.Vector n a) -> CodeGenFunction r (LLVM.Vector n (Value a))
+disassemblePrimitive v =
+   Trav.mapM (LLVM.extractelement v . LLVM.valueOf) indices
+
+indices :: (Applicative f, Trav.Traversable f) => f Word32
+indices =
+   flip MS.evalState 0 $ Trav.sequenceA $ pure $ MS.state (\k -> (k,k+1))
+
+instance Vector Float where
+   assembleVector LP.Proxy = assemblePrimitive
+   disassembleVector LP.Proxy = disassemblePrimitive
+
+instance Vector Double where
+   assembleVector LP.Proxy = assemblePrimitive
+   disassembleVector LP.Proxy = disassemblePrimitive
+
+instance Vector Word where
+   assembleVector LP.Proxy = assemblePrimitive
+   disassembleVector LP.Proxy = disassemblePrimitive
+
+instance Vector Word8 where
+   assembleVector LP.Proxy = assemblePrimitive
+   disassembleVector LP.Proxy = disassemblePrimitive
+
+instance Vector Word16 where
+   assembleVector LP.Proxy = assemblePrimitive
+   disassembleVector LP.Proxy = disassemblePrimitive
+
+instance Vector Word32 where
+   assembleVector LP.Proxy = assemblePrimitive
+   disassembleVector LP.Proxy = disassemblePrimitive
+
+instance Vector Word64 where
+   assembleVector LP.Proxy = assemblePrimitive
+   disassembleVector LP.Proxy = disassemblePrimitive
+
+instance Vector Int where
+   assembleVector LP.Proxy = assemblePrimitive
+   disassembleVector LP.Proxy = disassemblePrimitive
+
+instance Vector Int8 where
+   assembleVector LP.Proxy = assemblePrimitive
+   disassembleVector LP.Proxy = disassemblePrimitive
+
+instance Vector Int16 where
+   assembleVector LP.Proxy = assemblePrimitive
+   disassembleVector LP.Proxy = disassemblePrimitive
+
+instance Vector Int32 where
+   assembleVector LP.Proxy = assemblePrimitive
+   disassembleVector LP.Proxy = disassemblePrimitive
+
+instance Vector Int64 where
+   assembleVector LP.Proxy = assemblePrimitive
+   disassembleVector LP.Proxy = disassemblePrimitive
+
+instance Vector Bool where
+   assembleVector LP.Proxy = assemblePrimitive
+   disassembleVector LP.Proxy = disassemblePrimitive
+
+instance Vector Bool8 where
+   assembleVector LP.Proxy = assemblePrimitive
+   disassembleVector LP.Proxy = disassemblePrimitive
+
+
+instance
+   (Tuple tuple, TupleVector tuple) =>
+      Vector (StoreTuple.Tuple tuple) where
+   assembleVector = deinterleave . fmap StoreTuple.getTuple
+   disassembleVector = interleave . fmap StoreTuple.getTuple
+
+
+class TupleVector a where
+   deinterleave ::
+      (TypeNum.Positive n) =>
+      LP.Proxy a -> LLVM.Vector n (Tuple.ValueOf a) ->
+      CodeGenFunction r (Tuple.VectorValueOf n a)
+   interleave ::
+      (TypeNum.Positive n) =>
+      LP.Proxy a -> Tuple.VectorValueOf n a ->
+      CodeGenFunction r (LLVM.Vector n (Tuple.ValueOf a))
+
+instance (Vector a, Vector b) => TupleVector (a,b) where
+   deinterleave = FuncHT.uncurry $ \pa pb -> FuncHT.uncurry $ \a b ->
+      App.lift2 (,) (assembleVector pa a) (assembleVector pb b)
+   interleave = FuncHT.uncurry $ \pa pb (a,b) ->
+      App.lift2 (App.lift2 (,))
+         (disassembleVector pa a) (disassembleVector pb b)
+
+instance (Vector a, Vector b, Vector c) => TupleVector (a,b,c) where
+   deinterleave = FuncHT.uncurry3 $ \pa pb pc -> FuncHT.uncurry3 $ \a b c ->
+      App.lift3 (,,)
+         (assembleVector pa a)
+         (assembleVector pb b)
+         (assembleVector pc c)
+   interleave = FuncHT.uncurry3 $ \pa pb pc (a,b,c) ->
+      App.lift3 (App.lift3 (,,))
+         (disassembleVector pa a)
+         (disassembleVector pb b)
+         (disassembleVector pc c)
+
+
+{-
+instance Storable () available since base-4.9/GHC-8.0.
+Before we need Data.Orphans.
+-}
+instance C () where
+   load _ptr = return ()
+   store () _ptr = return ()
+
+
+loadNewtype ::
+   (C a, Tuple.ValueOf a ~ al) =>
+   (a -> wrapped) ->
+   (al -> wrappedl) ->
+   Value (Ptr wrapped) -> CodeGenFunction r wrappedl
+loadNewtype wrap wrapl =
+   fmap wrapl . load <=< rmapPtr wrap
+
+storeNewtype ::
+   (C a, Tuple.ValueOf a ~ al) =>
+   (a -> wrapped) ->
+   (wrappedl -> al) ->
+   wrappedl -> Value (Ptr wrapped) -> CodeGenFunction r ()
+storeNewtype wrap unwrapl y =
+   store (unwrapl y) <=< rmapPtr wrap
+
+rmapPtr :: (a -> b) -> Value (Ptr b) -> CodeGenFunction r (Value (Ptr a))
+rmapPtr _f = LLVM.bitcast
+
+
+loadTraversable ::
+   (NonEmptyC.Repeat f, Trav.Traversable f, C a, Tuple.ValueOf a ~ al) =>
+   Value (Ptr (f a)) -> CodeGenFunction r (f al)
+loadTraversable =
+   (MS.evalStateT $ Trav.sequence $ NonEmptyC.repeat $ loadState)
+      <=< castElementPtr
+
+loadApplicative ::
+   (Applicative f, Trav.Traversable f, C a, Tuple.ValueOf a ~ al) =>
+   Value (Ptr (f a)) -> CodeGenFunction r (f al)
+loadApplicative =
+   (MS.evalStateT $ Trav.sequence $ pure loadState) <=< castElementPtr
+
+loadState ::
+   (C a, Tuple.ValueOf a ~ al) =>
+   MS.StateT (Value (Ptr a)) (CodeGenFunction r) al
+loadState = MT.lift . load =<< advancePtrState
+
+
+storeFoldable ::
+   (Fold.Foldable f, C a, Tuple.ValueOf a ~ al) =>
+   f al -> Value (Ptr (f a)) -> CodeGenFunction r ()
+storeFoldable xs = MS.evalStateT (Fold.mapM_ storeState xs) <=< castElementPtr
+
+storeState ::
+   (C a, Tuple.ValueOf a ~ al) =>
+   al -> MS.StateT (Value (Ptr a)) (CodeGenFunction r) ()
+storeState a = MT.lift . store a =<< advancePtrState
+
+
+update :: (Monad m) => (a -> m a) -> MS.StateT a m a
+update f = MS.StateT $ \a0 -> do a1 <- f a0; return (a0,a1)
+
+advancePtrState ::
+   (C a, Tuple.ValueOf a ~ al, Value (Ptr a) ~ ptr) =>
+   MS.StateT ptr (CodeGenFunction r) ptr
+advancePtrState = update $ advancePtrStatic 1
+
+advancePtr ::
+   (Store.Storable a, Value (Ptr a) ~ ptr) =>
+   Value Int -> ptr -> CodeGenFunction r ptr
+advancePtr n ptr = do
+   size <- A.mul n $ LLVM.valueOf $ Store.sizeOf (elementFromPtr ptr)
+   addPointer size ptr
+
+advancePtrStatic ::
+   (Store.Storable a, Value (Ptr a) ~ ptr) =>
+   Int -> ptr -> CodeGenFunction r ptr
+advancePtrStatic n ptr =
+   addPointer (LLVM.valueOf (Store.sizeOf (elementFromPtr ptr) * n)) ptr
+
+incrementPtr ::
+   (Store.Storable a, Value (Ptr a) ~ ptr) =>
+   ptr -> CodeGenFunction r ptr
+incrementPtr = advancePtrStatic 1
+
+decrementPtr ::
+   (Store.Storable a, Value (Ptr a) ~ ptr) =>
+   ptr -> CodeGenFunction r ptr
+decrementPtr = advancePtrStatic (-1)
+
+addPointer :: Value Int -> Value (Ptr a) -> CodeGenFunction r (Value (Ptr a))
+addPointer k ptr = do
+   bytePtr <- castToBytePtr ptr
+   castFromBytePtr =<< LLVM.getElementPtr bytePtr (k, ())
+
+type BytePtr = Value (LLVM.Ptr Word8)
+
+castToBytePtr :: Value (Ptr a) -> CodeGenFunction r BytePtr
+castToBytePtr = LLVM.bitcast
+
+castFromBytePtr :: BytePtr -> CodeGenFunction r (Value (Ptr a))
+castFromBytePtr = LLVM.bitcast
+
+castElementPtr :: Value (Ptr (f a)) -> CodeGenFunction r (Value (Ptr a))
+castElementPtr = LLVM.bitcast
+
+
+sizeOf :: (Store.Storable a) => LP.Proxy a -> Int
+sizeOf = Store.sizeOf . elementFromProxy
+
+elementFromPtr :: LLVM.Value (Ptr a) -> a
+elementFromPtr _ = error "elementFromProxy"
+
+elementFromProxy :: LP.Proxy a -> a
+elementFromProxy LP.Proxy = error "elementFromProxy"
+
+proxyFromElement2 :: f (g a) -> LP.Proxy a
+proxyFromElement2 _ = LP.Proxy
+
+proxyFromElement3 :: f (g (h a)) -> LP.Proxy a
+proxyFromElement3 _ = LP.Proxy
diff --git a/src/LLVM/Extra/Tuple.hs b/src/LLVM/Extra/Tuple.hs
new file mode 100644
--- /dev/null
+++ b/src/LLVM/Extra/Tuple.hs
@@ -0,0 +1,246 @@
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE UndecidableInstances #-}
+module LLVM.Extra.Tuple (
+   Phi(..), phiTraversable, addPhiFoldable,
+   Undefined(..), undefPointed,
+   Zero(..), zeroPointed,
+   Value(..), valueOfFunctor,
+   VectorValue(..),
+   ) where
+
+import LLVM.Extra.TuplePrivate (
+   Phi(..), phiTraversable, addPhiFoldable,
+   Undefined(..), undefPointed,
+   Zero(..), zeroPointed,
+   )
+import qualified LLVM.Extra.EitherPrivate as Either
+import qualified LLVM.Extra.MaybePrivate as Maybe
+import qualified LLVM.Core as LLVM
+import LLVM.Core (IsType, Vector)
+
+import qualified Type.Data.Num.Decimal as TypeNum
+import Type.Data.Num.Decimal ((:*:))
+
+import qualified Control.Monad.Trans.State as MS
+import qualified Control.Applicative as App
+import qualified Control.Functor.HT as FuncHT
+
+import qualified Data.Foldable as Fold
+import qualified Data.Traversable as Trav
+
+import qualified Foreign.Storable.Record.Tuple as StoreTuple
+import Foreign.StablePtr (StablePtr, )
+import Foreign.Ptr (FunPtr, Ptr, )
+
+import qualified Data.EnumBitSet as EnumBitSet
+import qualified Data.Enum.Storable as Enum
+import qualified Data.Bool8 as Bool8
+import Data.Complex (Complex((:+)))
+import Data.Tagged (Tagged(unTagged))
+import Data.Word (Word8, Word16, Word32, Word64, Word)
+import Data.Int  (Int8,  Int16,  Int32,  Int64, )
+import Data.Bool8 (Bool8)
+
+import Prelude2010
+import Prelude ()
+
+
+-- * class for creating tuples of constant values
+
+class (Undefined (ValueOf a)) => Value a where
+   type ValueOf a
+   valueOf :: a -> ValueOf a
+
+instance (Value a, Value b) => Value (a,b) where
+   type ValueOf (a,b) = (ValueOf a, ValueOf b)
+   valueOf ~(a,b) = (valueOf a, valueOf b)
+
+instance (Value a, Value b, Value c) => Value (a,b,c) where
+   type ValueOf (a,b,c) = (ValueOf a, ValueOf b, ValueOf c)
+   valueOf ~(a,b,c) = (valueOf a, valueOf b, valueOf c)
+
+instance (Value a, Value b, Value c, Value d) => Value (a,b,c,d) where
+   type ValueOf (a,b,c,d) = (ValueOf a, ValueOf b, ValueOf c, ValueOf d)
+   valueOf ~(a,b,c,d) = (valueOf a, valueOf b, valueOf c, valueOf d)
+
+instance (Value tuple) => Value (StoreTuple.Tuple tuple) where
+   type ValueOf (StoreTuple.Tuple tuple) = ValueOf tuple
+   valueOf (StoreTuple.Tuple a) = valueOf a
+
+instance (Value a) => Value (Maybe a) where
+   type ValueOf (Maybe a) = Maybe.T (ValueOf a)
+   valueOf = maybe (Maybe.nothing undef) (Maybe.just . valueOf)
+
+instance (Value a, Value b) => Value (Either a b) where
+   type ValueOf (Either a b) = Either.T (ValueOf a) (ValueOf b)
+   valueOf =
+      either
+         (Either.left undef . valueOf)
+         (Either.right undef . valueOf)
+
+instance Value Float  where type ValueOf Float  = LLVM.Value Float  ; valueOf = LLVM.valueOf
+instance Value Double where type ValueOf Double = LLVM.Value Double ; valueOf = LLVM.valueOf
+-- instance Value FP128  where type ValueOf FP128  = LLVM.Value FP128  ; valueOf = LLVM.valueOf
+instance Value Bool   where type ValueOf Bool   = LLVM.Value Bool   ; valueOf = LLVM.valueOf
+instance Value Bool8  where type ValueOf Bool8  = LLVM.Value Bool   ; valueOf = LLVM.valueOf . Bool8.toBool
+instance Value Int    where type ValueOf Int    = LLVM.Value Int    ; valueOf = LLVM.valueOf
+instance Value Int8   where type ValueOf Int8   = LLVM.Value Int8   ; valueOf = LLVM.valueOf
+instance Value Int16  where type ValueOf Int16  = LLVM.Value Int16  ; valueOf = LLVM.valueOf
+instance Value Int32  where type ValueOf Int32  = LLVM.Value Int32  ; valueOf = LLVM.valueOf
+instance Value Int64  where type ValueOf Int64  = LLVM.Value Int64  ; valueOf = LLVM.valueOf
+instance Value Word   where type ValueOf Word   = LLVM.Value Word   ; valueOf = LLVM.valueOf
+instance Value Word8  where type ValueOf Word8  = LLVM.Value Word8  ; valueOf = LLVM.valueOf
+instance Value Word16 where type ValueOf Word16 = LLVM.Value Word16 ; valueOf = LLVM.valueOf
+instance Value Word32 where type ValueOf Word32 = LLVM.Value Word32 ; valueOf = LLVM.valueOf
+instance Value Word64 where type ValueOf Word64 = LLVM.Value Word64 ; valueOf = LLVM.valueOf
+instance Value ()     where type ValueOf ()     = ()           ; valueOf = id
+
+
+instance (TypeNum.Positive n) => Value (LLVM.IntN n) where
+   type ValueOf (LLVM.IntN n) = LLVM.Value (LLVM.IntN n)
+   valueOf = LLVM.valueOf
+
+instance (TypeNum.Positive n) => Value (LLVM.WordN n) where
+   type ValueOf (LLVM.WordN n) = LLVM.Value (LLVM.WordN n)
+   valueOf = LLVM.valueOf
+
+
+instance Value (Ptr a) where
+   type ValueOf (Ptr a) = LLVM.Value (Ptr a)
+   valueOf = LLVM.valueOf
+
+instance IsType a => Value (LLVM.Ptr a) where
+   type ValueOf (LLVM.Ptr a) = LLVM.Value (LLVM.Ptr a)
+   valueOf = LLVM.valueOf
+
+instance LLVM.IsFunction a => Value (FunPtr a) where
+   type ValueOf (FunPtr a) = LLVM.Value (FunPtr a)
+   valueOf = LLVM.valueOf
+
+instance Value (StablePtr a) where
+   type ValueOf (StablePtr a) = LLVM.Value (StablePtr a)
+   valueOf = LLVM.valueOf
+
+instance
+   (TypeNum.Positive n, VectorValue n a, Undefined (VectorValueOf n a)) =>
+      Value (Vector n a) where
+   type ValueOf (Vector n a) = VectorValueOf n a
+   valueOf = vectorValueOf
+
+
+instance Value a => Value (Tagged tag a) where
+   type ValueOf (Tagged tag a) = ValueOf a
+   valueOf = valueOf . unTagged
+
+instance
+   (LLVM.IsInteger w, LLVM.IsConst w, Num w, Enum e) =>
+      Value (Enum.T w e) where
+   type ValueOf (Enum.T w e) = LLVM.Value w
+   valueOf = LLVM.valueOf . fromIntegral . fromEnum . Enum.toPlain
+
+instance (LLVM.IsInteger w, LLVM.IsConst w) => Value (EnumBitSet.T w i) where
+   type ValueOf (EnumBitSet.T w i) = LLVM.Value w
+   valueOf = LLVM.valueOf . EnumBitSet.decons
+
+instance (Value a) => Value (Complex a) where
+   type ValueOf (Complex a) = Complex (ValueOf a)
+   valueOf (a:+b) = valueOf a :+ valueOf b
+
+
+-- * class for vectors of tuples and other complex types
+
+class
+   (TypeNum.Positive n, Undefined (VectorValueOf n a)) =>
+      VectorValue n a where
+   type VectorValueOf n a
+   vectorValueOf :: Vector n a -> VectorValueOf n a
+
+-- may be simplified using a fake proof of TypeNum.Positive (n :*: m)
+instance
+   (TypeNum.Positive n, TypeNum.Positive m, TypeNum.Positive (n :*: m),
+    Undefined (Vector (n :*: m) a)) =>
+      VectorValue n (Vector m a) where
+   type VectorValueOf n (Vector m a) = Vector (n :*: m) a
+   vectorValueOf = vectorFromList . Fold.foldMap Fold.toList
+
+vectorFromList :: (TypeNum.Positive n) => [a] -> Vector n a
+vectorFromList =
+   MS.evalState $ Trav.sequence $ App.pure $ MS.state $ \(y:ys) -> (y,ys)
+
+instance (VectorValue n a, VectorValue n b) => VectorValue n (a,b) where
+   type VectorValueOf n (a,b) = (VectorValueOf n a, VectorValueOf n b)
+   vectorValueOf v =
+      case FuncHT.unzip v of
+         (a,b) -> (vectorValueOf a, vectorValueOf b)
+
+instance
+   (VectorValue n a, VectorValue n b, VectorValue n c) =>
+      VectorValue n (a,b,c) where
+   type VectorValueOf n (a,b,c) =
+         (VectorValueOf n a, VectorValueOf n b, VectorValueOf n c)
+   vectorValueOf v =
+      case FuncHT.unzip3 v of
+         (a,b,c) -> (vectorValueOf a, vectorValueOf b, vectorValueOf c)
+
+instance (VectorValue n tuple) => VectorValue n (StoreTuple.Tuple tuple) where
+   type VectorValueOf n (StoreTuple.Tuple tuple) = VectorValueOf n tuple
+   vectorValueOf = vectorValueOf . fmap StoreTuple.getTuple
+
+instance (TypeNum.Positive n) => VectorValue n Float where
+   type VectorValueOf n Float  = LLVM.Value (Vector n Float)
+   vectorValueOf = LLVM.valueOf
+
+instance (TypeNum.Positive n) => VectorValue n Double where
+   type VectorValueOf n Double = LLVM.Value (Vector n Double)
+   vectorValueOf = LLVM.valueOf
+{-
+instance (TypeNum.Positive n) => VectorValue n FP128  where
+   type VectorValueOf n FP128  = LLVM.Value (Vector n FP128)
+   vectorValueOf = LLVM.valueOf
+-}
+instance (TypeNum.Positive n) => VectorValue n Bool   where
+   type VectorValueOf n Bool   = LLVM.Value (Vector n Bool)
+   vectorValueOf = LLVM.valueOf
+instance (TypeNum.Positive n) => VectorValue n Bool8  where
+   type VectorValueOf n Bool8  = LLVM.Value (Vector n Bool)
+   vectorValueOf = LLVM.valueOf . fmap Bool8.toBool
+instance (TypeNum.Positive n) => VectorValue n Int  where
+   type VectorValueOf n Int    = LLVM.Value (Vector n Int)
+   vectorValueOf = LLVM.valueOf
+instance (TypeNum.Positive n) => VectorValue n Int8   where
+   type VectorValueOf n Int8   = LLVM.Value (Vector n Int8)
+   vectorValueOf = LLVM.valueOf
+instance (TypeNum.Positive n) => VectorValue n Int16  where
+   type VectorValueOf n Int16  = LLVM.Value (Vector n Int16)
+   vectorValueOf = LLVM.valueOf
+instance (TypeNum.Positive n) => VectorValue n Int32  where
+   type VectorValueOf n Int32  = LLVM.Value (Vector n Int32)
+   vectorValueOf = LLVM.valueOf
+instance (TypeNum.Positive n) => VectorValue n Int64  where
+   type VectorValueOf n Int64  = LLVM.Value (Vector n Int64)
+   vectorValueOf = LLVM.valueOf
+instance (TypeNum.Positive n) => VectorValue n Word   where
+   type VectorValueOf n Word   = LLVM.Value (Vector n Word)
+   vectorValueOf = LLVM.valueOf
+instance (TypeNum.Positive n) => VectorValue n Word8  where
+   type VectorValueOf n Word8  = LLVM.Value (Vector n Word8)
+   vectorValueOf = LLVM.valueOf
+instance (TypeNum.Positive n) => VectorValue n Word16 where
+   type VectorValueOf n Word16 = LLVM.Value (Vector n Word16)
+   vectorValueOf = LLVM.valueOf
+instance (TypeNum.Positive n) => VectorValue n Word32 where
+   type VectorValueOf n Word32 = LLVM.Value (Vector n Word32)
+   vectorValueOf = LLVM.valueOf
+instance (TypeNum.Positive n) => VectorValue n Word64 where
+   type VectorValueOf n Word64 = LLVM.Value (Vector n Word64)
+   vectorValueOf = LLVM.valueOf
+
+
+-- * default methods for LLVM classes
+
+valueOfFunctor :: (Value h, Functor f) => f h -> f (ValueOf h)
+valueOfFunctor = fmap valueOf
diff --git a/src/LLVM/Extra/TuplePrivate.hs b/src/LLVM/Extra/TuplePrivate.hs
new file mode 100644
--- /dev/null
+++ b/src/LLVM/Extra/TuplePrivate.hs
@@ -0,0 +1,140 @@
+module LLVM.Extra.TuplePrivate where
+
+import qualified LLVM.Core as LLVM
+
+import qualified Data.FixedLength as FixedLength
+import Data.Complex (Complex)
+
+import qualified Type.Data.Num.Unary as Unary
+
+import qualified Control.Applicative.HT as App
+import Control.Applicative (Applicative, liftA2, pure)
+
+import qualified Data.Traversable as Trav
+import qualified Data.Foldable as Fold
+
+import Data.Orphans ()
+
+
+
+-- * class for phi operating on value tuples
+
+class Phi a where
+   phi :: LLVM.BasicBlock -> a -> LLVM.CodeGenFunction r a
+   addPhi :: LLVM.BasicBlock -> a -> a -> LLVM.CodeGenFunction r ()
+
+instance Phi () where
+   phi _ _ = return ()
+   addPhi _ _ _ = return ()
+
+instance (LLVM.IsFirstClass a) => Phi (LLVM.Value a) where
+   phi bb a = LLVM.phi [(a, bb)]
+   addPhi bb a a' = LLVM.addPhiInputs a [(a', bb)]
+
+instance (Phi a, Phi b) => Phi (a, b) where
+   phi bb = App.mapPair (phi bb, phi bb)
+   addPhi bb (a0,b0) (a1,b1) = do
+      addPhi bb a0 a1
+      addPhi bb b0 b1
+
+instance (Phi a, Phi b, Phi c) => Phi (a, b, c) where
+   phi bb = App.mapTriple (phi bb, phi bb, phi bb)
+   addPhi bb (a0,b0,c0) (a1,b1,c1) = do
+      addPhi bb a0 a1
+      addPhi bb b0 b1
+      addPhi bb c0 c1
+
+instance (Phi a, Phi b, Phi c, Phi d) => Phi (a, b, c, d) where
+   phi bb (a,b,c,d) =
+      App.lift4 (,,,) (phi bb a) (phi bb b) (phi bb c) (phi bb d)
+   addPhi bb (a0,b0,c0,d0) (a1,b1,c1,d1) = do
+      addPhi bb a0 a1
+      addPhi bb b0 b1
+      addPhi bb c0 c1
+      addPhi bb d0 d1
+
+instance (Phi a) => Phi (Complex a) where
+   phi = phiTraversable
+   addPhi = addPhiFoldable
+
+instance (Unary.Natural n, Phi a) => Phi (FixedLength.T n a) where
+   phi = phiTraversable
+   addPhi = addPhiFoldable
+
+phiTraversable ::
+   (Phi a, Trav.Traversable f) =>
+   LLVM.BasicBlock -> f a -> LLVM.CodeGenFunction r (f a)
+phiTraversable bb x = Trav.mapM (phi bb) x
+
+addPhiFoldable ::
+   (Phi a, Fold.Foldable f, Applicative f) =>
+   LLVM.BasicBlock -> f a -> f a -> LLVM.CodeGenFunction r ()
+addPhiFoldable bb x y = Fold.sequence_ (liftA2 (addPhi bb) x y)
+
+
+-- * class for tuples of undefined values
+
+class Undefined a where
+   undef :: a
+
+instance Undefined () where
+   undef = ()
+
+instance (LLVM.IsFirstClass a) => Undefined (LLVM.Value a) where
+   undef = LLVM.value LLVM.undef
+
+instance (LLVM.IsFirstClass a) => Undefined (LLVM.ConstValue a) where
+   undef = LLVM.undef
+
+instance (Undefined a, Undefined b) => Undefined (a, b) where
+   undef = (undef, undef)
+
+instance (Undefined a, Undefined b, Undefined c) => Undefined (a, b, c) where
+   undef = (undef, undef, undef)
+
+instance
+   (Undefined a, Undefined b, Undefined c, Undefined d) =>
+      Undefined (a, b, c, d) where
+   undef = (undef, undef, undef, undef)
+
+instance (Undefined a) => Undefined (Complex a) where
+   undef = undefPointed
+
+instance (Unary.Natural n, Undefined a) => Undefined (FixedLength.T n a) where
+   undef = undefPointed
+
+undefPointed :: (Undefined a, Applicative f) => f a
+undefPointed = pure undef
+
+
+-- * class for tuples of zero values
+
+class Zero a where
+   zero :: a
+
+instance Zero () where
+   zero = ()
+
+instance (LLVM.IsFirstClass a) => Zero (LLVM.Value a) where
+   zero = LLVM.value LLVM.zero
+
+instance (LLVM.IsFirstClass a) => Zero (LLVM.ConstValue a) where
+   zero = LLVM.zero
+
+instance (Zero a, Zero b) => Zero (a, b) where
+   zero = (zero, zero)
+
+instance (Zero a, Zero b, Zero c) => Zero (a, b, c) where
+   zero = (zero, zero, zero)
+
+instance (Zero a, Zero b, Zero c, Zero d) => Zero (a, b, c, d) where
+   zero = (zero, zero, zero, zero)
+
+instance (Zero a) => Zero (Complex a) where
+   zero = zeroPointed
+
+instance (Unary.Natural n, Zero a) => Zero (FixedLength.T n a) where
+   zero = zeroPointed
+
+zeroPointed :: (Zero a, Applicative f) => f a
+zeroPointed = pure zero
diff --git a/src/LLVM/Extra/Vector.hs b/src/LLVM/Extra/Vector.hs
--- a/src/LLVM/Extra/Vector.hs
+++ b/src/LLVM/Extra/Vector.hs
@@ -40,12 +40,11 @@
        truncate, floor, fraction),
    ) where
 
-import qualified LLVM.Extra.Class as Class
+import qualified LLVM.Extra.Tuple as Tuple
 import qualified LLVM.Extra.ArithmeticPrivate as A
 import qualified LLVM.Util.Intrinsic as Intrinsic
 
 import qualified LLVM.Core as LLVM
-import LLVM.Util.Loop (Phi(phis, addPhis), )
 import LLVM.Core
    (Value, ConstValue, valueOf, value, constOf, undef,
     Vector, insertelement, extractelement,
@@ -70,9 +69,8 @@
 import qualified Data.List as List
 import Data.NonEmpty ((!:), )
 
--- import qualified Data.Bits as Bit
 import Data.Int  (Int8, Int16, Int32, Int64, )
-import Data.Word (Word8, Word16, Word32, Word64, )
+import Data.Word (Word8, Word16, Word32, Word64, Word)
 
 import Prelude hiding
           (Real, truncate, floor, round,
@@ -101,7 +99,7 @@
    insert :: Value Word32 -> Element v -> v -> CodeGenFunction r v
 
 class
-   (TypeNum.Positive (Size v), Phi v, Class.Undefined v) =>
+   (TypeNum.Positive (Size v), Tuple.Phi v, Tuple.Undefined v) =>
       Simple v where
 
    type Element v :: *
@@ -210,14 +208,14 @@
    {-# INLINE sequenceA #-}
    sequenceA (Constant a) = fmap Constant a
 
-instance (Phi a) => Phi (Constant n a) where
-   phis = Class.phisTraversable
-   addPhis = Class.addPhisFoldable
+instance (Tuple.Phi a) => Tuple.Phi (Constant n a) where
+   phi = Tuple.phiTraversable
+   addPhi = Tuple.addPhiFoldable
 
-instance (Class.Undefined a) => Class.Undefined (Constant n a) where
-   undefTuple = Class.undefTuplePointed
+instance (Tuple.Undefined a) => Tuple.Undefined (Constant n a) where
+   undef = Tuple.undefPointed
 
-instance (TypeNum.Positive n, Phi a, Class.Undefined a) => Simple (Constant n a) where
+instance (TypeNum.Positive n, Tuple.Phi a, Tuple.Undefined a) => Simple (Constant n a) where
 
    type Element (Constant n a) = a
    type Size (Constant n a) = n
@@ -277,10 +275,10 @@
    (C v) =>
    [Element v] -> CodeGenFunction r v
 assemble =
-   foldM (\v (k,x) -> insert (valueOf k) x v) Class.undefTuple .
+   foldM (\v (k,x) -> insert (valueOf k) x v) Tuple.undef .
    List.zip [0..]
 {- sends GHC into an infinite loop
-   foldM (\(k,x) -> insert (valueOf k) x) Class.undefTuple .
+   foldM (\(k,x) -> insert (valueOf k) x) Tuple.undef .
    List.zip [0..]
 -}
 
@@ -303,7 +301,7 @@
    Element v -> CodeGenFunction r v
 iterate f x =
    fmap snd $
-   iterateCore f x Class.undefTuple
+   iterateCore f x Tuple.undef
 
 iterateCore ::
    (C v) =>
@@ -413,18 +411,18 @@
       (insert (LLVM.valueOf (fromIntegral (sizeInTuple x) - 1)) x0 y)
 
 shiftUpMultiZero ::
-   (C v, Class.Zero (Element v)) =>
+   (C v, Tuple.Zero (Element v)) =>
    Int -> v -> LLVM.CodeGenFunction r v
 shiftUpMultiZero n v =
    assemble . take (sizeInTuple v) .
-   (List.replicate n Class.zeroTuple ++) =<< extractAll v
+   (List.replicate n Tuple.zero ++) =<< extractAll v
 
 shiftDownMultiZero ::
-   (C v, Class.Zero (Element v)) =>
+   (C v, Tuple.Zero (Element v)) =>
    Int -> v -> LLVM.CodeGenFunction r v
 shiftDownMultiZero n v =
    assemble . take (sizeInTuple v) .
-   (++ List.repeat Class.zeroTuple) . List.drop n
+   (++ List.repeat Tuple.zero) . List.drop n
       =<< extractAll v
 
 
@@ -522,7 +520,7 @@
          extract (valueOf n) a >>=
          f >>=
          flip (insert (valueOf n)) b)
-      Class.undefTuple
+      Tuple.undef
       (take (sizeInTuple a) [0..])
 
 mapChunks ::
@@ -537,7 +535,7 @@
          am >>= \ac ->
          f ac >>= \bc ->
          insertChunk (k * sizeInTuple ac) bc b)
-      Class.undefTuple $
+      Tuple.undef $
    List.zip (chop a) [0..]
 
 zipChunksWith ::
@@ -653,7 +651,7 @@
                insert (valueOf j) x v)
             v0 $
          List.zip [0..] js)
-      Class.undefTuple $
+      Tuple.undef $
    List.zip
       (ListHT.sliceVertical (sizeInTuple (head xs)) [0..])
       xs
@@ -754,7 +752,7 @@
          a1 <- A.add a0 =<< extract (valueOf k) x
          y1 <- insert (valueOf k) a0 y0
          return (a1,y1))
-      (a, Class.undefTuple)
+      (a, Tuple.undef)
       (take (sizeInTuple x) $ [0..])
 
 cumulateGeneric =
@@ -929,10 +927,12 @@
 instance Arithmetic Float where
 instance Arithmetic Double where
 
+instance Arithmetic Int    where
 instance Arithmetic Int8   where
 instance Arithmetic Int16  where
 instance Arithmetic Int32  where
 instance Arithmetic Int64  where
+instance Arithmetic Word   where
 instance Arithmetic Word8  where
 instance Arithmetic Word16 where
 instance Arithmetic Word32 where
@@ -981,6 +981,15 @@
    floor = Intrinsic.floor
    fraction = A.fraction
 
+instance Real Int where
+   min = A.min
+   max = A.max
+   abs = A.abs
+   signum = signumIntGeneric
+   truncate = return
+   floor = return
+   fraction = const $ return (value LLVM.zero)
+
 instance Real Int8 where
    min = A.min
    max = A.max
@@ -1013,6 +1022,15 @@
    max = A.max
    abs = A.abs
    signum = signumIntGeneric
+   truncate = return
+   floor = return
+   fraction = const $ return (value LLVM.zero)
+
+instance Real Word where
+   min = A.min
+   max = A.max
+   abs = return
+   signum = signumWordGeneric
    truncate = return
    floor = return
    fraction = const $ return (value LLVM.zero)
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -1,5 +1,6 @@
 module Main where
 
+import qualified Test.Storable as Storable
 import qualified Test.Vector as Vector
 
 import qualified LLVM.Core as LLVM
@@ -14,4 +15,6 @@
    LLVM.initializeNativeTarget
 
    mapM_ (\(msg,prop) -> putStr (msg++": ") >> prop >>= QC.quickCheck) $
-      map (mapFst ("Vector."++)) Vector.tests
+      map (mapFst ("Storable."++)) Storable.tests ++
+      map (mapFst ("Vector."++)) Vector.tests ++
+      []
diff --git a/test/Test/Storable.hs b/test/Test/Storable.hs
new file mode 100644
--- /dev/null
+++ b/test/Test/Storable.hs
@@ -0,0 +1,99 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+{-# LANGUAGE TypeFamilies #-}
+module Test.Storable (tests) where
+
+import qualified LLVM.Extra.Storable as Storable
+import qualified LLVM.Extra.Tuple as Tuple
+
+import qualified LLVM.ExecutionEngine as EE
+import qualified LLVM.Core as LLVM
+
+import qualified Type.Data.Num.Decimal as TypeNum
+
+import qualified Foreign
+import Foreign.Storable.Record.Tuple (Tuple(Tuple))
+import Foreign.Ptr (FunPtr, Ptr)
+
+import Data.Complex (Complex)
+import Data.Word (Word16, Word32)
+import Data.Int (Int8, Int16, Int32)
+import Data.Tuple.HT (mapFst)
+
+import qualified Test.QuickCheck.Monadic as QCMon
+import qualified Test.QuickCheck as QC
+
+
+
+type Importer func = FunPtr func -> func
+
+generateFunction ::
+   EE.ExecutionFunction f =>
+   Importer f -> LLVM.CodeGenModule (LLVM.Function f) -> IO f
+generateFunction imprt code = do
+   m <- LLVM.newModule
+   fn <- do
+      func <- LLVM.defineModule m $ LLVM.setTarget LLVM.hostTriple >> code
+      EE.runEngineAccessWithModule m $ EE.getExecutionFunction imprt func
+   LLVM.writeBitcodeToFile "test-storable.bc" m
+   return fn
+
+
+foreign import ccall safe "dynamic" derefTestCasePtr ::
+   Importer (Ptr inp -> Ptr out -> IO ())
+
+modul ::
+   (Storable.C a, Tuple.ValueOf a ~ al) =>
+   (Storable.C b, Tuple.ValueOf b ~ bl) =>
+   (al -> LLVM.CodeGenFunction () bl) ->
+   LLVM.CodeGenModule (LLVM.Function (Ptr a -> Ptr b -> IO ()))
+modul codegen =
+   LLVM.createFunction LLVM.ExternalLinkage $ \aPtr bPtr -> do
+      flip Storable.store bPtr =<< codegen =<< Storable.load aPtr
+      LLVM.ret ()
+
+run ::
+   (Show a) =>
+   (Storable.C a, Tuple.ValueOf a ~ al) =>
+   (Storable.C b, Tuple.ValueOf b ~ bl) =>
+   QC.Gen a ->
+   (al -> LLVM.CodeGenFunction () bl) ->
+   (a -> b -> Bool) ->
+   IO QC.Property
+run qcgen codegen predicate = do
+   funIO <- generateFunction derefTestCasePtr $ modul codegen
+   return $ QC.forAll qcgen $ \a ->
+      QCMon.monadicIO $ do
+         b <-
+            QCMon.run $
+               Foreign.with a $ \aPtr ->
+               Foreign.alloca $ \bPtr -> do
+                  funIO aPtr bPtr
+                  Foreign.peek bPtr
+         QCMon.assert $ predicate a b
+
+
+roundTrip ::
+   (Show a, Eq a, Storable.C a) =>
+   QC.Gen a -> IO QC.Property
+roundTrip qcgen = run qcgen return (==)
+
+
+tests :: [(String, IO QC.Property)]
+tests =
+   map (mapFst ("RoundTrip." ++)) $
+   ("()",
+      roundTrip (QC.arbitrary :: QC.Gen ())) :
+   ("Float",
+      roundTrip (QC.arbitrary :: QC.Gen Float)) :
+   ("(Word16,Float)",
+      roundTrip (fmap Tuple (QC.arbitrary :: QC.Gen (Word16,Float)))) :
+   ("(Int8,Bool,Double)",
+      roundTrip (fmap Tuple (QC.arbitrary :: QC.Gen (Int8,Bool,Double)))) :
+   ("Complex Float",
+      roundTrip (QC.arbitrary :: QC.Gen (Complex Float))) :
+   ("Vector D3 Int32",
+      roundTrip (QC.arbitrary :: QC.Gen (LLVM.Vector TypeNum.D3 Int32))) :
+   ("Vector D7 (Int16,Word32)",
+      roundTrip (fmap (fmap Tuple)
+         (QC.arbitrary :: QC.Gen (LLVM.Vector TypeNum.D7 (Int16,Word32))))) :
+   []
diff --git a/test/Test/Vector.hs b/test/Test/Vector.hs
--- a/test/Test/Vector.hs
+++ b/test/Test/Vector.hs
@@ -1,23 +1,23 @@
 {-# LANGUAGE ForeignFunctionInterface #-}
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE FlexibleContexts #-}
 module Test.Vector where
 
 import qualified LLVM.Extra.ScalarOrVectorPrivate as SoVPriv
 import qualified LLVM.Extra.ScalarOrVector as SoV
 import qualified LLVM.Extra.VectorAlt as VectorAlt
 import qualified LLVM.Extra.Vector as Vector
+import qualified LLVM.Extra.Memory as Memory
 import qualified LLVM.Extra.Marshal as Marshal
-import qualified LLVM.Extra.Class as Class
+import qualified LLVM.Extra.Tuple as Tuple
 import qualified LLVM.ExecutionEngine as EE
-import qualified LLVM.Util.Proxy as LP
 import qualified LLVM.Core as LLVM
 
 import qualified Type.Data.Num.Decimal as TypeNum
 import Type.Base.Proxy (Proxy(Proxy))
 
-import qualified Foreign.Marshal as Marsh
-import Foreign.Ptr (FunPtr, Ptr)
+import Foreign.Ptr (FunPtr)
 
 import qualified Data.Traversable as Trav
 import qualified Data.Foldable as Fold
@@ -50,49 +50,39 @@
    fn <- do
       func <- LLVM.defineModule m $ LLVM.setTarget LLVM.hostTriple >> code
       EE.runEngineAccessWithModule m $ EE.getExecutionFunction imprt func
-   LLVM.writeBitcodeToFile "test.bc" m
+   LLVM.writeBitcodeToFile "test-vector.bc" m
    return fn
 
 
 foreign import ccall safe "dynamic" derefTestCasePtr ::
-   Importer (Ptr inp -> Ptr out -> IO ())
+   Importer (LLVM.Ptr inp -> LLVM.Ptr out -> IO ())
 
 modul ::
-   (Marshal.C inp, Marshal.Struct inp ~ minp, LLVM.IsType minp,
-    Marshal.C out, Marshal.Struct out ~ mout, LLVM.IsType mout,
-    Class.ValueTuple inp ~ linp, Class.ValueTuple out ~ lout) =>
-   (LP.Proxy inp, LP.Proxy out) ->
+   (Memory.C linp, Memory.Struct linp ~ minp, LLVM.IsType minp,
+    Memory.C lout, Memory.Struct lout ~ mout, LLVM.IsType mout) =>
    (linp -> LLVM.CodeGenFunction () lout) ->
-   LLVM.CodeGenModule (LLVM.Function (Ptr minp -> Ptr mout -> IO ()))
-modul (xProxy,yProxy) codegen =
+   LLVM.CodeGenModule (LLVM.Function (LLVM.Ptr minp -> LLVM.Ptr mout -> IO ()))
+modul codegen =
    LLVM.createFunction LLVM.ExternalLinkage $ \xPtr yPtr -> do
-      flip (Marshal.store yProxy) yPtr =<< codegen =<< Marshal.load xProxy xPtr
+      flip Memory.store yPtr =<< codegen =<< Memory.load xPtr
       LLVM.ret ()
 
-proxies :: (inp -> out -> Bool) -> (LP.Proxy inp, LP.Proxy out)
-proxies _ = (LP.Proxy, LP.Proxy)
-
-alloca :: (LLVM.IsType a) => LP.Proxy a -> (Ptr a -> IO b) -> IO b
-alloca proxy = Marsh.allocaBytes (EE.sizeOf proxy)
-
 run ::
    (Marshal.C inp, Marshal.Struct inp ~ minp, LLVM.IsType minp,
     Marshal.C out, Marshal.Struct out ~ mout, LLVM.IsType mout,
-    Class.ValueTuple inp ~ linp, Class.ValueTuple out ~ lout) =>
+    Tuple.ValueOf inp ~ linp, Tuple.ValueOf out ~ lout) =>
    (Show inp, QC.Arbitrary inp) =>
    (linp -> LLVM.CodeGenFunction () lout) ->
    (inp -> out -> Bool) ->
    IO QC.Property
 run codegen predicate = do
-   funIO <-
-      generateFunction derefTestCasePtr $ modul (proxies predicate) codegen
+   funIO <- generateFunction derefTestCasePtr $ modul codegen
    return $ QC.property $ \x ->
       QCMon.monadicIO $ do
          y <-
             QCMon.run $
-               alloca LP.Proxy $ \xPtr ->
-               alloca LP.Proxy $ \yPtr -> do
-                  Marshal.poke xPtr x
+               Marshal.with x $ \xPtr ->
+               Marshal.alloca $ \yPtr -> do
                   funIO xPtr yPtr
                   Marshal.peek yPtr
          QCMon.assert $ predicate x y
@@ -119,10 +109,9 @@
 
 binop ::
    ((TypeNum.D4 TypeNum.:*: LLVM.SizeOf a) ~ size, TypeNum.Natural size,
-    QC.Arbitrary a, Show a, Eq a, EE.Marshal a,
-    LLVM.IsConst a, LLVM.IsSized a, LLVM.IsPrimitive a) =>
-   (LLVM.Value (V4 a) -> LLVM.Value (V4 a) ->
-    LLVM.CodeGenFunction () (LLVM.Value (V4 a))) ->
+    QC.Arbitrary a, Show a, Eq a,
+    Marshal.Vector TypeNum.D4 a, Tuple.VectorValueOf TypeNum.D4 a ~ v) =>
+   (v -> v -> LLVM.CodeGenFunction () v) ->
    (a -> a -> a) ->
    IO QC.Property
 binop codegen fun =
@@ -130,8 +119,8 @@
       (\(x,y) z -> liftA2 fun (vec4 x) (vec4 y)  ==  vec4 z)
 
 binopInt ::
-   (LLVM.Value V4Int32 -> LLVM.Value V4Int32 ->
-    LLVM.CodeGenFunction () (LLVM.Value V4Int32)) ->
+   (LLVM.Value V4Int32 ~ v) =>
+   (v -> v -> LLVM.CodeGenFunction () v) ->
    (Int32 -> Int32 -> Int32) ->
    IO QC.Property
 binopInt = binop
@@ -179,10 +168,10 @@
 unpackWord3 = unpackWords 8
 
 binopV4I2 ::
-   (Eq a, LLVM.IsPrimitive a, LLVM.IsSized a, LLVM.SizeOf a ~ TypeNum.D2) =>
+   (Eq a, LLVM.IsPrimitive a, LLVM.IsSized a, LLVM.SizeOf a ~ TypeNum.D2,
+    LLVM.Value (V4 a) ~ v) =>
    (Word8 -> V4 a) ->
-   (LLVM.Value (V4 a) -> LLVM.Value (V4 a) ->
-    LLVM.CodeGenFunction () (LLVM.Value (V4 a))) ->
+   (v -> v -> LLVM.CodeGenFunction () v) ->
    (a -> a -> a) ->
    IO QC.Property
 binopV4I2 unpackBits codegen fun =
@@ -198,10 +187,10 @@
 type Code15 r = LLVM.CodeGenFunction r (LLVM.Value (LLVM.WordN TypeNum.D15))
 
 binopV5I3 ::
-   (Eq a, LLVM.IsPrimitive a, LLVM.IsSized a, LLVM.SizeOf a ~ TypeNum.D3) =>
+   (Eq a, LLVM.IsPrimitive a, LLVM.IsSized a, LLVM.SizeOf a ~ TypeNum.D3,
+    LLVM.Value (V5 a) ~ v) =>
    (Word16 -> V5 a) ->
-   (LLVM.Value (V5 a) -> LLVM.Value (V5 a) ->
-    LLVM.CodeGenFunction () (LLVM.Value (V5 a))) ->
+   (v -> v -> LLVM.CodeGenFunction () v) ->
    (a -> a -> a) ->
    IO QC.Property
 binopV5I3 unpackBits codegen fun =
@@ -215,15 +204,15 @@
          liftA2 fun (unpackBits x) (unpackBits y)  ==  unpackBits z)
 
 binopInt8 ::
-   (LLVM.Value (V4 Int8) -> LLVM.Value (V4 Int8) ->
-    LLVM.CodeGenFunction () (LLVM.Value (V4 Int8))) ->
+   (LLVM.Value (V4 Int8) ~ v) =>
+   (v -> v -> LLVM.CodeGenFunction () v) ->
    (Int8 -> Int8 -> Int8) ->
    IO QC.Property
 binopInt8 = binop
 
 binopWord8 ::
-   (LLVM.Value (V4 Word8) -> LLVM.Value (V4 Word8) ->
-    LLVM.CodeGenFunction () (LLVM.Value (V4 Word8))) ->
+   (LLVM.Value (V4 Word8) ~ v) =>
+   (v -> v -> LLVM.CodeGenFunction () v) ->
    (Word8 -> Word8 -> Word8) ->
    IO QC.Property
 binopWord8 = binop
