diff --git a/Problems.txt b/Problems.txt
--- a/Problems.txt
+++ b/Problems.txt
@@ -12,6 +12,10 @@
 This is a known issue:
    http://hackage.haskell.org/trac/ghc/ticket/2615#comment:16
 
+In GHC-6.12.3 you must also run
+   ghc-pkg recache --user
+  after removing pthread from ~/.ghc/i386-linux-6.12.3/package.conf.d/llvm-*.conf
+
 Now when running 'main' I get the error,
 that something about CurrentEngine cannot be found.
 It means, we must also include /usr/lib/llvm/LLVM*.o files.
@@ -64,3 +68,24 @@
 ghci: Pass.cpp:152: void<unnamed>::PassRegistrar::RegisterPass(const llvm::PassInfo&): Assertion `Inserted && "Pass registered multiple times!"' failed.
 Also running LLVM.Target.X86.initializeTarget or Array.renderRamp
 leads to this error.
+
+
+LLVM-2.8
+
+If I remove 'pthread' from Extra-Libraries and add 'LLVM-2.8rc' to Extra-GHCi-Libraries in
+  $HOME/.ghc/i386-linux-6.12.3/package.conf.d/llvm-0.9.*-*.conf
+ and run
+  ghc-pkg recache --user
+ I am even able to run 'llvm' example programs from within GHCi!
+
+Sometimes it happends that llvm.buildinfo contains
+ld-options: /usr/local/lib/libLLVM-2.8rc.so
+and then llvm-0.9.*-*.conf contains this as well.
+This leads to a failure of a LLVM runtime assertion:
+
+llvm/examples$ DotProd.exe
+Two passes with the same argument (-preverify) attempted to be registered!
+UNREACHABLE executed!
+Aborted
+
+ld-options field must be empty!
diff --git a/llvm-extra.cabal b/llvm-extra.cabal
--- a/llvm-extra.cabal
+++ b/llvm-extra.cabal
@@ -1,5 +1,5 @@
 Name:           llvm-extra
-Version:        0.1
+Version:        0.2
 License:        BSD3
 License-File:   LICENSE
 Author:         Henning Thielemann <haskell@henning-thielemann.de>
@@ -18,7 +18,7 @@
     in "LLVM.Extra.Arithmetic",
   .
   * a type class for loading and storing sets of values with one command (macro)
-    in "LLVM.Extra.Representation",
+    in "LLVM.Extra.Memory",
   .
   * support instance declarations of LLVM classes
     in "LLVM.Extra.Class",
@@ -48,8 +48,8 @@
   * a Makefile and a description
     of how to run LLVM code from within GHCi.
 Stability:      Experimental
-Tested-With:    GHC==6.10.4
-Cabal-Version:  >=1.2
+Tested-With:    GHC==6.10.4, GHC==6.12.3
+Cabal-Version:  >=1.6
 Build-Type:     Simple
 Extra-Source-Files:
   Makefile
@@ -61,11 +61,15 @@
   description: Build example executables
   default:     False
 
+Source-Repository head
+  Type:        darcs
+  Location:    http://code.haskell.org/~thielema/llvm-extra/
+
 Library
   Build-Depends:
     -- llvm must be imported with restrictive version bounds,
     -- because we import implicitly and unqualified
-    llvm-ht >=0.7.0 && <0.7.1,
+    llvm >=0.9.1.0 && <0.9.1.2,
     type-level >=0.2.3 && <0.3,
     containers >=0.1 && <0.4,
     transformers >=0.1.1 && <0.3,
@@ -75,7 +79,7 @@
     base >= 3 && <5
 
   If arch(i386)
-    Build-Depends: cpuid >=0.2 && <0.3
+    Build-Depends: cpuid >=0.2.2 && <0.3
     Hs-Source-Dirs: x86/cpuid
   Else
     -- Instead of calling the cpuid instruction directly
@@ -89,7 +93,8 @@
   Exposed-Modules:
     LLVM.Extra.Arithmetic
     LLVM.Extra.Monad
-    LLVM.Extra.Representation
+    LLVM.Extra.Memory
+    LLVM.Extra.ForeignPtr
     LLVM.Extra.MaybeContinuation
     LLVM.Extra.Class
     LLVM.Extra.Control
diff --git a/src/Array.hs b/src/Array.hs
--- a/src/Array.hs
+++ b/src/Array.hs
@@ -4,7 +4,6 @@
 import LLVM.Extra.Control (arrayLoop, )
 import qualified LLVM.Extra.ScalarOrVector as SV
 import qualified LLVM.Extra.Vector as Vector
-import qualified LLVM.Extra.Control as U
 
 import qualified LLVM.Extra.Extension.X86 as X86
 import qualified LLVM.Extra.Extension as Ext
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
@@ -2,12 +2,10 @@
 module LLVM.Extra.Arithmetic (
    add, sub, inc, dec,
    mul, square, fdiv,
-   udiv, urem,
-   fcmp, icmp,
+   idiv, irem,
+   fcmp, cmp,
    and, or,
-   umin, umax,
-   smin, smax, sabs,
-   fmin, fmax, fabs,
+   min, max, abs,
    advanceArrayElementPtr,
    sqrt, sin, cos, exp, log, pow,
    ) where
@@ -15,17 +13,15 @@
 import qualified LLVM.Core as LLVM
 import LLVM.Core
    (Ptr, getElementPtr, value, valueOf, Value,
-    IntPredicate(IntULE, IntSLE, IntUGE, IntSGE),
-    FPPredicate(FPOLE, FPOGE),
-    IsIntegerOrPointer,
+    CmpPredicate(CmpLE, CmpGE), CmpRet,
+    FPPredicate,
     IsType, IsConst, IsInteger, IsFloating, IsArithmetic, IsFirstClass,
-    CmpRet,
     CodeGenFunction, )
 
 import Data.Word (Word32, )
 
 
-import Prelude hiding (and, or, sqrt, sin, cos, exp, log, )
+import Prelude hiding (and, or, sqrt, sin, cos, exp, log, abs, min, max, )
 
 
 
@@ -69,25 +65,25 @@
 fdiv = LLVM.fdiv
 
 fcmp ::
-  (IsFloating a, CmpRet a b) =>
-  FPPredicate -> Value a -> Value a -> CodeGenFunction r (Value b)
+   (IsFloating a, CmpRet a b) =>
+   FPPredicate -> Value a -> Value a -> CodeGenFunction r (Value b)
 fcmp = LLVM.fcmp
 
 
-icmp ::
-  (IsIntegerOrPointer a, CmpRet a b) =>
-  IntPredicate -> Value a -> Value a -> CodeGenFunction r (Value b)
-icmp = LLVM.icmp
+cmp ::
+   (CmpRet a b) =>
+   CmpPredicate -> Value a -> Value a -> CodeGenFunction r (Value b)
+cmp = LLVM.cmp
 
-udiv ::
+idiv ::
    (IsInteger a) =>
    Value a -> Value a -> CodeGenFunction r (Value a)
-udiv = LLVM.udiv
+idiv = LLVM.idiv
 
-urem ::
+irem ::
    (IsInteger a) =>
    Value a -> Value a -> CodeGenFunction r (Value a)
-urem = LLVM.urem
+irem = LLVM.irem
 
 
 and ::
@@ -106,42 +102,18 @@
 This would also work for vectors,
 if LLVM would support 'select' with bool vectors as condition.
 -}
-umin :: (IsInteger a, CmpRet a Bool) =>
-   Value a -> Value a -> CodeGenFunction r (Value a)
-umin = cmpSelect (icmp IntULE)
-
-umax :: (IsInteger a, CmpRet a Bool) =>
-   Value a -> Value a -> CodeGenFunction r (Value a)
-umax = cmpSelect (icmp IntUGE)
-
-
-smin :: (IsInteger a, CmpRet a Bool) =>
-   Value a -> Value a -> CodeGenFunction r (Value a)
-smin = cmpSelect (icmp IntSLE)
-
-smax :: (IsInteger a, CmpRet a Bool) =>
-   Value a -> Value a -> CodeGenFunction r (Value a)
-smax = cmpSelect (icmp IntSGE)
-
-sabs :: (IsInteger a, CmpRet a Bool) =>
-   Value a -> CodeGenFunction r (Value a)
-sabs x = do
-   b <- icmp IntSGE x (value LLVM.zero)
-   LLVM.select b x =<< LLVM.neg x
-
-
-fmin :: (IsFloating a, CmpRet a Bool) =>
+min :: (IsFirstClass a, CmpRet a Bool) =>
    Value a -> Value a -> CodeGenFunction r (Value a)
-fmin = cmpSelect (fcmp FPOLE)
+min = cmpSelect (cmp CmpLE)
 
-fmax :: (IsFloating a, CmpRet a Bool) =>
+max :: (IsFirstClass a, CmpRet a Bool) =>
    Value a -> Value a -> CodeGenFunction r (Value a)
-fmax = cmpSelect (fcmp FPOGE)
+max = cmpSelect (cmp CmpGE)
 
-fabs :: (IsFloating a, CmpRet a Bool) =>
+abs :: (IsArithmetic a, CmpRet a Bool) =>
    Value a -> CodeGenFunction r (Value a)
-fabs x = do
-   b <- fcmp FPOGE x (value LLVM.zero)
+abs x = do
+   b <- cmp CmpGE x (value LLVM.zero)
    LLVM.select b x =<< LLVM.neg x
 
 
@@ -179,18 +151,37 @@
    String -> Value a -> CodeGenFunction r (Value a)
 callIntrinsic1 fn x = do
    op <- LLVM.externFunction ("llvm." ++ fn ++ "." ++ valueTypeName x)
-   r <- LLVM.call op x
-   LLVM.addAttributes r 0 [LLVM.ReadNoneAttribute]
-   return r
+   LLVM.call op x >>= addReadNone
 
 callIntrinsic2 ::
    (IsFirstClass a) =>
    String -> Value a -> Value a -> CodeGenFunction r (Value a)
 callIntrinsic2 fn x y = do
    op <- LLVM.externFunction ("llvm." ++ fn ++ "." ++ valueTypeName x)
-   r <- LLVM.call op x y
-   LLVM.addAttributes r 0 [LLVM.ReadNoneAttribute]
-   return r
+   LLVM.call op x y >>= addReadNone
+
+
+{-
+If we add the attribute, then LLVM-2.8 complains:
+
+$ ./dist/build/synthi-llvm-test/synthi-llvm-test
+Attribute readnone only applies to the function!
+  %97 = call readnone float @llvm.sin.f32(float %96)
+Attribute readnone only applies to the function!
+  %99 = call readnone float @llvm.exp.f32(float %98)
+Attribute readnone only applies to the function!
+  %102 = call readnone float @llvm.cos.f32(float %101)
+Broken module found, compilation aborted!
+Stack dump:
+0.      Running pass 'Function Pass Manager' on module '_module'.
+1.      Running pass 'Module Verifier' on function '@fillsignal'
+make: *** [test] Abgebrochen
+-}
+addReadNone :: Value a -> CodeGenFunction r (Value a)
+addReadNone x = do
+--   LLVM.addAttributes x 0 [LLVM.ReadNoneAttribute]
+   return x
+
 
 
 sqrt, sin, cos, exp, log ::
diff --git a/src/LLVM/Extra/Class.hs b/src/LLVM/Extra/Class.hs
--- a/src/LLVM/Extra/Class.hs
+++ b/src/LLVM/Extra/Class.hs
@@ -7,21 +7,45 @@
 
 import qualified LLVM.Core as LLVM
 import LLVM.Core
-   (Undefined, undefTuple,
-    IsTuple, tupleDesc, TypeDesc,
-    MakeValueTuple, valueTupleOf,
-    Value,
+   (Value, value, valueOf, undef,
+    Vector,
+    IsConst, IsType, IsFirstClass, IsPrimitive,
     CodeGenFunction, BasicBlock, )
 import LLVM.Util.Loop (Phi, phis, addPhis, )
+import qualified Data.TypeLevel.Num as TypeNum
 
 import Control.Applicative (pure, liftA2, )
 import qualified Control.Applicative as App
 import qualified Data.Foldable as Fold
 import qualified Data.Traversable as Trav
 
+import Foreign.StablePtr (StablePtr, )
+import Foreign.Ptr (Ptr, )
+
+import Data.Word (Word8, Word16, Word32, Word64, )
+import Data.Int  (Int8,  Int16,  Int32,  Int64, )
+
 import Prelude hiding (and, iterate, map, zipWith, writeFile, )
 
 
+-- * 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 (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)
+
+
 -- * class for tuples of zero values
 
 class Zero a where
@@ -46,6 +70,61 @@
    pure zeroTuple
 
 
+-- * class for creating tuples of constant values
+
+{-
+ToDo: flip type parameter order in order to match good style
+-}
+-- class (IsTuple haskellValue, ValueTuple llvmValue) =>
+--      MakeValueTuple haskellValue llvmValue | haskellValue -> llvmValue where
+class (Undefined llvmValue) =>
+      MakeValueTuple haskellValue llvmValue | haskellValue -> llvmValue where
+   valueTupleOf :: haskellValue -> llvmValue
+
+instance (MakeValueTuple ah al, MakeValueTuple bh bl) =>
+      MakeValueTuple (ah,bh) (al,bl) where
+   valueTupleOf ~(a,b) = (valueTupleOf a, valueTupleOf b)
+
+instance (MakeValueTuple ah al, MakeValueTuple bh bl, MakeValueTuple ch cl) =>
+      MakeValueTuple (ah,bh,ch) (al,bl,cl) where
+   valueTupleOf ~(a,b,c) = (valueTupleOf a, valueTupleOf b, valueTupleOf c)
+
+instance MakeValueTuple Float        (Value Float)  where valueTupleOf = valueOf
+instance MakeValueTuple Double       (Value Double) where valueTupleOf = valueOf
+-- instance MakeValueTuple FP128        (Value FP128)  where valueTupleOf = valueOf
+instance MakeValueTuple Bool         (Value Bool)   where valueTupleOf = valueOf
+instance MakeValueTuple Int8         (Value Int8)   where valueTupleOf = valueOf
+instance MakeValueTuple Int16        (Value Int16)  where valueTupleOf = valueOf
+instance MakeValueTuple Int32        (Value Int32)  where valueTupleOf = valueOf
+instance MakeValueTuple Int64        (Value Int64)  where valueTupleOf = valueOf
+instance MakeValueTuple Word8        (Value Word8)  where valueTupleOf = valueOf
+instance MakeValueTuple Word16       (Value Word16) where valueTupleOf = valueOf
+instance MakeValueTuple Word32       (Value Word32) where valueTupleOf = valueOf
+instance MakeValueTuple Word64       (Value Word64) where valueTupleOf = valueOf
+instance MakeValueTuple ()           ()             where 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) (Value (Ptr a)) where valueTupleOf = valueOf
+instance MakeValueTuple (StablePtr a) (Value (StablePtr a)) where valueTupleOf = valueOf
+
+{-
+instance (MakeValueTuple haskellValue llvmValue, Memory llvmValue llvmStruct) =>
+         MakeValueTuple (Ptr haskellValue) (Value (Ptr llvmStruct)) where
+   valueTupleOf = valueOf . castStorablePtr
+instance (Pos n) =>
+         MakeValueTuple (IntN n)     (Value (IntN n)) where
+instance (Pos n) =>
+         MakeValueTuple (WordN n)    (Value (WordN n)) where
+-}
+instance (TypeNum.Pos n, IsPrimitive a, IsConst a) =>
+         MakeValueTuple (Vector n a) (Value (Vector n a)) where valueTupleOf = valueOf
+
+
 -- * default methods for LLVM classes
 
 {-
@@ -63,12 +142,14 @@
 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) =>
@@ -82,11 +163,13 @@
 valueTupleOfFunctor =
    fmap valueTupleOf
 
+{-
 tupleDescFoldable ::
    (IsTuple a, Fold.Foldable f) =>
    f a -> [TypeDesc]
 tupleDescFoldable =
    Fold.foldMap tupleDesc
+-}
 
 phisTraversable ::
    (Phi a, Trav.Traversable f) =>
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
@@ -10,7 +10,9 @@
    arrayLoop,
    arrayLoopWithExit,
    arrayLoop2WithExit,
+   fixedLengthLoop,
    whileLoop,
+   whileLoopShared,
    ifThenElse,
    ifThen,
    Select(select),
@@ -19,14 +21,15 @@
    ) where
 
 import LLVM.Extra.Arithmetic
-   (icmp, sub, dec, advanceArrayElementPtr, )
+   (cmp, sub, dec, advanceArrayElementPtr, )
+import qualified LLVM.Extra.Arithmetic as A
 import qualified LLVM.Core as LLVM
 import LLVM.Core
    (getCurrentBasicBlock, newBasicBlock, defineBasicBlock,
     br, condBr,
-    Ptr, Value, value,
+    Ptr, Value, value, valueOf,
     phi, addPhiInputs,
-    IntPredicate(IntNE), CmpRet,
+    CmpPredicate(CmpGT), CmpRet,
     IsInteger, IsType, IsConst, IsFirstClass,
     CodeGenFunction,
     CodeGenModule, newModule, defineModule, writeBitcodeToFile, )
@@ -52,35 +55,12 @@
    Value i -> Value (Ptr b) -> a ->
    (Value (Ptr b) -> a -> CodeGenFunction r a) ->
    CodeGenFunction r a
-arrayLoop len ptr start loopBody = do
-   top <- getCurrentBasicBlock
-   loop <- newBasicBlock
-   body <- newBasicBlock
-   exit <- newBasicBlock
-
-   br loop
-
-   defineBasicBlock loop
-   i <- phi [(len, top)]
-   p <- phi [(ptr, top)]
-   vars <- phis top start
-   t <- icmp IntNE i (value LLVM.zero)
-   condBr t body exit
-
-   defineBasicBlock body
-
-   vars' <- loopBody p vars
-   i' <- dec i
-   p' <- advanceArrayElementPtr p
-
-   body' <- getCurrentBasicBlock
-   addPhis body' vars vars'
-   addPhiInputs i [(i', body')]
-   addPhiInputs p [(p', body')]
-   br loop
-
-   defineBasicBlock exit
-   return vars
+arrayLoop len ptr start loopBody =
+   fmap snd $
+   fixedLengthLoop len (ptr, start) $ \(p,s) ->
+      liftM2 (,)
+         (advanceArrayElementPtr p)
+         (loopBody p s)
 
 
 arrayLoopWithExit ::
@@ -90,35 +70,16 @@
    (Value (Ptr a) -> s -> CodeGenFunction r (Value Bool, s)) ->
    CodeGenFunction r (Value i, s)
 arrayLoopWithExit len ptr start loopBody = do
-   top <- getCurrentBasicBlock
-   loop <- newBasicBlock
-   body <- newBasicBlock
-   next <- newBasicBlock
-   exit <- newBasicBlock
-
-   br loop
-
-   defineBasicBlock loop
-   i <- phi [(len, top)]
-   p <- phi [(ptr, top)]
-   vars <- phis top start
-   t <- icmp IntNE i (value LLVM.zero)
-   condBr t body exit
-
-   defineBasicBlock body
-   (cont, vars') <- loopBody p vars
-   addPhis next vars vars'
-   condBr cont next exit
-
-   defineBasicBlock next
-   i' <- dec i
-   p' <- advanceArrayElementPtr p
-
-   addPhiInputs i [(i', next)]
-   addPhiInputs p [(p', next)]
-   br loop
-
-   defineBasicBlock exit
+   ((_, vars), (i,_)) <-
+      whileLoopShared ((valueOf True, start), (len, ptr)) $ \((b,v0), (i,p)) ->
+         (A.and b =<< cmp CmpGT i (value LLVM.zero),
+          do bv1 <- loopBody p v0
+             ip1 <-
+                ifThen (fst bv1) (i,p) $
+                   liftM2 (,)
+                      (dec i)
+                      (advanceArrayElementPtr p)
+             return (bv1,ip1))
    pos <- sub len i
    return (pos, vars)
 
@@ -145,7 +106,7 @@
 
    {- unfortunately, t0 is not just stored as processor flag
       but is written to a register and then tested again in checkEnd -}
-   t0 <- icmp IntNE len (value LLVM.zero)
+   t0 <- cmp CmpGT len (value LLVM.zero)
    br checkEnd
 
    defineBasicBlock checkEnd
@@ -164,7 +125,7 @@
    defineBasicBlock next
    p' <- advanceArrayElementPtr p
    i' <- dec i
-   t' <- icmp IntNE i' (value LLVM.zero)
+   t' <- cmp CmpGT i' (value LLVM.zero)
 
    addPhiInputs i [(i', next)]
    addPhiInputs p [(p', next)]
@@ -185,12 +146,25 @@
 arrayLoop2WithExit len ptrA ptrB start loopBody =
    fmap (mapSnd snd) $
    arrayLoopWithExit len ptrA (ptrB,start)
-      (\ptrAi (ptrBi,s0) -> do
-         (cont, s1) <- loopBody ptrAi ptrBi s0
-         ptrBi' <- advanceArrayElementPtr ptrBi
-         return (cont, (ptrBi',s1)))
+      (\ptrAi (ptrB0,s0) -> do
+         (cont, s1) <- loopBody ptrAi ptrB0 s0
+         ptrB1 <- advanceArrayElementPtr ptrB0
+         return (cont, (ptrB1,s1)))
 
 
+fixedLengthLoop ::
+   (Phi s,
+    Num i, IsConst i, IsInteger i, IsFirstClass i, CmpRet i Bool) =>
+   Value i -> s ->
+   (s -> CodeGenFunction r s) ->
+   CodeGenFunction r s
+fixedLengthLoop len start loopBody =
+   fmap snd $
+   whileLoopShared (len,start) $ \(i,s) ->
+      (cmp LLVM.CmpGT i (value LLVM.zero),
+       liftM2 (,) (dec i) (loopBody s))
+
+
 whileLoop ::
    Phi a =>
    a ->
@@ -217,6 +191,23 @@
    defineBasicBlock exit
    return state
 
+
+{- |
+This is a variant of 'whileLoop' that may be more convient,
+because you only need one lambda expression
+for both loop condition and loop body.
+-}
+whileLoopShared ::
+   Phi a =>
+   a ->
+   (a ->
+      (CodeGenFunction r (Value Bool),
+       CodeGenFunction r a)) ->
+   CodeGenFunction r a
+whileLoopShared start checkBody =
+   whileLoop start
+      (fst . checkBody)
+      (snd . checkBody)
 
 {- |
 This construct starts new blocks,
diff --git a/src/LLVM/Extra/Extension.hs b/src/LLVM/Extra/Extension.hs
--- a/src/LLVM/Extra/Extension.hs
+++ b/src/LLVM/Extra/Extension.hs
@@ -16,13 +16,12 @@
 import qualified LLVM.Core as LLVM
 import LLVM.Core
    (Value, CodeGenFunction, externFunction, call,
-    addAttributes, Attribute(ReadNoneAttribute), )
+    addAttributes, Attribute {- (ReadNoneAttribute) -}, )
 
 import Data.Map (Map, )
 import qualified Data.Map as Map
 
 import Control.Monad.Trans.Writer (Writer, writer, runWriter, )
-import qualified Control.Monad.Trans.Writer as Writer
 import Control.Monad (join, )
 import Control.Applicative (Applicative, pure, (<*>), )
 
@@ -106,7 +105,7 @@
    (LLVM.IsFunction f, LLVM.CallArgs f g, CallArgs g r) =>
    Subtarget -> String -> T g
 intrinsic =
-   intrinsicAttr [ReadNoneAttribute]
+   intrinsicAttr [{- ReadNoneAttribute -}]
 
 intrinsicAttr ::
    (LLVM.IsFunction f, LLVM.CallArgs f g, CallArgs g r) =>
diff --git a/src/LLVM/Extra/Extension/X86.hs b/src/LLVM/Extra/Extension/X86.hs
--- a/src/LLVM/Extra/Extension/X86.hs
+++ b/src/LLVM/Extra/Extension/X86.hs
@@ -84,7 +84,7 @@
 switchFPPred ::
    (Num i, LLVM.IsConst i, LLVM.IsInteger i, LLVM.IsPrimitive i,
     LLVM.IsFirstClass v,
-    LLVM.IsPowerOf2 n,
+    TypeNum.Pos n,
     LLVM.IsSized v s, LLVM.IsSized (Vector n i) s) =>
    (Value v -> Value v -> Value Word8 -> CodeGenFunction r (Value v)) ->
    FPPredicate -> Value v -> Value v -> CodeGenFunction r (Value (Vector n i))
@@ -135,7 +135,7 @@
 
 
 pcmpuFromPcmp ::
-   (LLVM.IsPowerOf2 n,
+   (TypeNum.Pos n,
     LLVM.IsPrimitive s,
     LLVM.IsPrimitive u, LLVM.IsArithmetic u, LLVM.IsConst u,
     Bounded u, Integral u,
@@ -227,16 +227,22 @@
 cvtpd2dq :: Ext.T (VDouble -> CodeGenFunction r (Value (Vector D4 Int32)))
 cvtpd2dq = Ext.intrinsic sse2 "cvtpd2dq"
 
+
+valueUnit :: Value () -> ()
+valueUnit _ = ()
+
 {- |
 MXCSR is not really supported by LLVM-2.6.
 LLVM does not know about the dependency of all floating point operations
 on this status register.
 -}
-ldmxcsr :: Ext.T (Value (Ptr Word32) -> CodeGenFunction r (Value ()))
-ldmxcsr = Ext.intrinsicAttr [] sse1 "ldmxcsr"
+ldmxcsr :: Ext.T (Value (Ptr Word32) -> CodeGenFunction r ())
+ldmxcsr =
+   fmap (fmap valueUnit .) $ Ext.intrinsicAttr [] sse1 "ldmxcsr"
 
-stmxcsr :: Ext.T (Value (Ptr Word32) -> CodeGenFunction r (Value ()))
-stmxcsr = Ext.intrinsicAttr [] sse1 "stmxcsr"
+stmxcsr :: Ext.T (Value (Ptr Word32) -> CodeGenFunction r ())
+stmxcsr =
+   fmap (fmap valueUnit .) $ Ext.intrinsicAttr [] sse1 "stmxcsr"
 
 withMXCSR :: Word32 -> Ext.T (CodeGenFunction r a -> CodeGenFunction r a)
 withMXCSR mxcsr =
diff --git a/src/LLVM/Extra/ForeignPtr.hs b/src/LLVM/Extra/ForeignPtr.hs
new file mode 100644
--- /dev/null
+++ b/src/LLVM/Extra/ForeignPtr.hs
@@ -0,0 +1,84 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+module LLVM.Extra.ForeignPtr (
+   newInit, newParam,
+   new, with,
+   ) where
+
+import qualified LLVM.Extra.Memory as Memory
+import LLVM.Extra.Class (MakeValueTuple, )
+
+import qualified Foreign.Marshal.Utils as Marshal
+import qualified Foreign.ForeignPtr as FPtr
+import qualified Foreign.Concurrent as FC
+import Foreign.Storable (Storable, poke, )
+import Foreign.Ptr (Ptr, FunPtr, )
+
+
+type Importer f = FunPtr f -> f
+
+foreign import ccall safe "dynamic" derefStartPtr ::
+   Importer (IO (Ptr a))
+
+newInit ::
+   FunPtr (Ptr a -> IO ()) ->
+   FunPtr (IO (Ptr a)) ->
+   IO (FPtr.ForeignPtr a)
+newInit stop start =
+   FPtr.newForeignPtr stop =<< derefStartPtr start
+
+
+foreign import ccall safe "dynamic" derefStartParamPtr ::
+   Importer (Ptr b -> IO (Ptr a))
+
+{-
+We cannot use 'bracket' when constructing lazy StorableVector,
+since this would mean that the temporary memory is freed immediately.
+Instead we must add a Finalizer to the ForeignPtr.
+-}
+newParam ::
+   (Storable b, MakeValueTuple b bl, Memory.C bl bp) =>
+   FunPtr (Ptr a -> IO ()) ->
+   FunPtr (Ptr bp -> IO (Ptr a)) ->
+   b -> IO (FPtr.ForeignPtr a)
+newParam stop start b =
+   FPtr.newForeignPtr stop =<<
+   Marshal.with b (derefStartParamPtr start . Memory.castStorablePtr)
+
+{-
+requires (Storable ap) constraint
+and we have no Storable instance for Struct
+
+new ::
+   (Storable a, MakeValueTuple a al, Memory.C al ap) =>
+   a -> IO (FPtr.ForeignPtr ap)
+new a = do
+   ptr <- FPtr.mallocForeignPtr
+   FPtr.withForeignPtr ptr (flip poke a . castPtr)
+   return ptr
+-}
+
+{- |
+Adding the finalizer to a ForeignPtr seems to be the only way
+that warrants execution of the finalizer (not too early and not never).
+However, the normal ForeignPtr finalizers must be independent from Haskell runtime.
+In contrast to ForeignPtr finalizers,
+addFinalizer adds finalizers to boxes, that are optimized away.
+Thus finalizers are run too early or not at all.
+Concurrent.ForeignPtr and using threaded execution
+is the only way to get finalizers in Haskell IO.
+-}
+new ::
+   Storable a =>
+   IO () ->
+   a -> IO (FPtr.ForeignPtr a)
+new finalizer a = do
+   ptr <- FPtr.mallocForeignPtr
+   FC.addForeignPtrFinalizer ptr finalizer
+   FPtr.withForeignPtr ptr (flip poke a)
+   return ptr
+
+with ::
+   (Storable a, MakeValueTuple a al, Memory.C al ap) =>
+   FPtr.ForeignPtr a -> (Ptr ap -> IO b) -> IO b
+with fp func =
+   FPtr.withForeignPtr fp (func . Memory.castStorablePtr)
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
@@ -7,9 +7,10 @@
 -}
 module LLVM.Extra.MaybeContinuation where
 
-import qualified LLVM.Extra.Control as U
+import qualified LLVM.Extra.Control as C
 import LLVM.Extra.Control (ifThenElse, )
 
+import LLVM.Extra.Class (Undefined, undefTuple, )
 import qualified LLVM.Extra.Arithmetic as A
 import LLVM.Core as LLVM
 import LLVM.Util.Loop (Phi, ) -- (phis, addPhis, )
@@ -20,7 +21,7 @@
 import Control.Monad.HT ((<=<), )
 import Data.Tuple.HT (mapSnd, )
 
-import Prelude hiding (fmap, and, iterate, map, zip, zipWith, writeFile, )
+import Prelude hiding (and, iterate, map, zip, zipWith, writeFile, )
 import qualified Prelude as P
 
 
@@ -67,7 +68,7 @@
 
 fromBool ::
    (Phi z) =>
-   CodeGenFunction r (Value Bool, a) -> 
+   CodeGenFunction r (Value Bool, a) ->
    T r z a
 fromBool m = do
    (b,a) <- lift m
@@ -80,6 +81,11 @@
 toBool (Cons m) =
    m (return (valueOf False, undefTuple)) (return . (,) (valueOf True))
 
+isJust ::
+   T r (Value Bool) a -> CodeGenFunction r (Value Bool)
+isJust (Cons m) =
+   m (return (valueOf False)) (const $ return (valueOf True))
+
 lift :: CodeGenFunction r a -> T r z a
 lift a = Cons $ \ _n j -> j =<< a
 
@@ -109,53 +115,18 @@
 then returned final state is undefined.
 -}
 arrayLoop ::
-   (Phi s, IsType a,
+   (Phi s, Undefined s, IsType a,
     Num i, IsConst i, IsInteger i, IsFirstClass i, CmpRet i Bool) =>
    Value i ->
    Value (Ptr a) -> s ->
    (Value (Ptr a) -> s -> T r (Value Bool, s) s) ->
    CodeGenFunction r (Value i, s)
 arrayLoop len ptr start loopBody =
-   U.arrayLoopWithExit len ptr start $ \ptri s0 ->
+   C.arrayLoopWithExit len ptr start $ \ptri s0 ->
       toBool (loopBody ptri s0)
 
-{-
-arrayLoop len ptr start loopBody = do
-   top <- getCurrentBasicBlock
-   loop <- newBasicBlock
-   body <- newBasicBlock
-   exit <- newBasicBlock
-
-   br loop
-
-   defineBasicBlock loop
-   i <- phi [(len, top)]
-   p <- phi [(ptr, top)]
-   vars <- phis top start
-   t <- A.icmp IntNE i (value LLVM.zero)
-   condBr t body exit
-
-   defineBasicBlock body
-   loopBody p vars
-      (br exit)
-      (\vars' -> do
-         next <- getCurrentBasicBlock
-         addPhis next vars vars'
-
-         i' <- A.dec i
-         p' <- A.advanceArrayElementPtr p
-
-         addPhiInputs i [(i', next)]
-         addPhiInputs p [(p', next)]
-         br loop)
-
-   defineBasicBlock exit
-   pos <- sub len i
-   return (pos, vars)
--}
-
 arrayLoop2 ::
-   (Phi s, IsType a, IsType b,
+   (Phi s, Undefined s, IsType a, IsType b,
     Num i, IsConst i, IsInteger i, IsFirstClass i, CmpRet i Bool) =>
    Value i ->
    Value (Ptr a) -> Value (Ptr b) -> s ->
@@ -163,12 +134,58 @@
       T r (Value Bool, (Value (Ptr b), s)) s) ->
    CodeGenFunction r (Value i, s)
 arrayLoop2 len ptrA ptrB start loopBody =
-   P.fmap (mapSnd snd) $
-   arrayLoop len ptrA (ptrB,start) $ \ptrAi (ptrBi,s0) -> do
-      s1 <- loopBody ptrAi ptrBi s0
-      ptrBi' <- lift $ A.advanceArrayElementPtr ptrBi
-      return (ptrBi',s1)
+   fmap (mapSnd snd) $
+   arrayLoop len ptrA (ptrB,start) $ \ptrAi (ptrB0,s0) -> do
+      s1 <- loopBody ptrAi ptrB0 s0
+      ptrB1 <- lift $ A.advanceArrayElementPtr ptrB0
+      return (ptrB1,s1)
 
+
+fixedLengthLoop ::
+   (Phi s, Undefined s,
+    Num i, IsConst i, IsInteger i, IsFirstClass i, CmpRet i Bool) =>
+   Value i -> s ->
+   (s -> T r (Value Bool, (Value i, s)) s) ->
+   CodeGenFunction r (Value i, s)
+fixedLengthLoop len start loopBody = do
+   (_,(lastI,lastS)) <-
+      C.whileLoopShared (valueOf True, (len, start)) $ \(cont,(i,s)) ->
+         (A.and cont =<< A.cmp LLVM.CmpGT i (value LLVM.zero),
+          resolve (loopBody s)
+             (return (valueOf False, undefTuple))
+             (\newS -> do
+                newI <- A.dec i
+                return (valueOf True, (newI, newS))))
+   fmap (flip (,) lastS) $ A.sub len lastI
+
+
 {-
-a specialised variant of whileLoop might also be useful
+In case of early exit we would not have a final state.
+However, the loop could be in the T monad
+and we could just propagate a Nothing.
+
+whileLoop ::
+   Phi a =>
+   a ->
+   (a -> T r z a) ->
+   CodeGenFunction r a
+whileLoop start check body = do
+   top <- getCurrentBasicBlock
+   loop <- newBasicBlock
+   cont <- newBasicBlock
+   exit <- newBasicBlock
+   br loop
+
+   defineBasicBlock loop
+   state <- phis top start
+   b <- check state
+   condBr b cont exit
+   defineBasicBlock cont
+   res <- body state
+   cont' <- getCurrentBasicBlock
+   addPhis cont' state res
+   br loop
+
+   defineBasicBlock exit
+   return state
 -}
diff --git a/src/LLVM/Extra/Memory.hs b/src/LLVM/Extra/Memory.hs
new file mode 100644
--- /dev/null
+++ b/src/LLVM/Extra/Memory.hs
@@ -0,0 +1,229 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FunctionalDependencies #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleContexts #-}
+module LLVM.Extra.Memory (
+   C(load, store, decompose, compose), modify, castStorablePtr,
+   Record, Element, element,
+   loadRecord, storeRecord, decomposeRecord, composeRecord,
+   loadNewtype, storeNewtype, decomposeNewtype, composeNewtype,
+   ) where
+
+import LLVM.Extra.Class (MakeValueTuple, Undefined, )
+
+import qualified LLVM.Core as LLVM
+import LLVM.Core
+   (Struct, getElementPtr0,
+    extractvalue, insertvalue,
+    Value, -- valueOf, Vector,
+    IsType, IsSized,
+    CodeGenFunction, )
+import LLVM.Util.Loop (Phi, )
+
+-- import qualified Data.TypeLevel.Num as TypeNum
+import Data.TypeLevel.Num (d0, d1, d2, )
+
+import Foreign.Ptr (Ptr, castPtr, )
+
+import Control.Monad (ap, )
+import Control.Applicative (pure, liftA2, liftA3, )
+import qualified Control.Applicative as App
+
+import Data.Tuple.HT (fst3, snd3, thd3, )
+
+
+{- |
+An implementation of both 'MakeValueTuple' and 'Memory.C'
+must ensure that @haskellValue@ is compatible with @llvmStruct@.
+That is, writing and reading @llvmStruct@ by LLVM
+must be the same as accessing @haskellValue@ by 'Storable' methods.
+ToDo: In future we may also require Storable constraint for llvmStruct.
+
+We use a functional dependency in order to let type inference work nicely.
+-}
+class (Phi llvmValue, Undefined llvmValue, IsType llvmStruct) =>
+      C llvmValue llvmStruct | llvmValue -> llvmStruct where
+   load :: Value (Ptr llvmStruct) -> CodeGenFunction r llvmValue
+   load ptr  =  decompose =<< LLVM.load ptr
+   store :: llvmValue -> Value (Ptr llvmStruct) -> CodeGenFunction r ()
+   store r ptr  =  flip LLVM.store ptr =<< compose r
+   decompose :: Value llvmStruct -> CodeGenFunction r llvmValue
+   compose :: llvmValue -> CodeGenFunction r (Value llvmStruct)
+
+modify ::
+   (C llvmValue llvmStruct) =>
+   (llvmValue -> CodeGenFunction r llvmValue) ->
+   Value (Ptr llvmStruct) -> CodeGenFunction r ()
+modify f ptr =
+   flip store ptr =<< f =<< load ptr
+
+
+type Record r o v = Element r o v v
+
+data Element r o v x =
+   Element {
+      loadElement :: Value (Ptr o) -> CodeGenFunction r x,
+      storeElement :: Value (Ptr o) -> v -> CodeGenFunction r (),
+      extractElement :: Value o -> CodeGenFunction r x,
+      insertElement :: v -> Value o -> CodeGenFunction r (Value o)
+         -- State.Monoid
+   }
+
+element ::
+   (C x llvmStruct,
+    LLVM.GetValue o n llvmStruct,
+    LLVM.GetElementPtr o (n, ()) llvmStruct) =>
+   (v -> x) -> n -> Element r o v x
+element field n =
+   Element {
+      loadElement = \ptr -> load =<< getElementPtr0 ptr (n, ()),
+      storeElement = \ptr v -> store (field v) =<< getElementPtr0 ptr (n, ()),
+      extractElement = \o -> decompose =<< extractvalue o n,
+      insertElement = \v o -> flip (insertvalue o) n =<< compose (field v)
+   }
+
+instance Functor (Element r o v) where
+   fmap f m =
+      Element {
+         loadElement = fmap f . loadElement m,
+         storeElement = storeElement m,
+         extractElement = fmap f . extractElement m,
+         insertElement = insertElement m
+      }
+
+instance App.Applicative (Element r o v) where
+   pure x =
+      Element {
+         loadElement = \ _ptr -> return x,
+         storeElement = \ _ptr _v -> return (),
+         extractElement = \ _o -> return x,
+         insertElement = \ _v o -> return o
+      }
+   f <*> x =
+      Element {
+         loadElement = \ptr -> loadElement f ptr `ap` loadElement x ptr,
+         storeElement = \ptr y -> storeElement f ptr y >> storeElement x ptr y,
+         extractElement = \o -> extractElement f o `ap` extractElement x o,
+         insertElement = \y o -> insertElement f y o >>= insertElement x y
+      }
+
+
+loadRecord ::
+   Record r o llvmValue ->
+   Value (Ptr o) -> CodeGenFunction r llvmValue
+loadRecord = loadElement
+
+storeRecord ::
+   Record r o llvmValue ->
+   llvmValue -> Value (Ptr o) -> CodeGenFunction r ()
+storeRecord m y ptr = storeElement m ptr y
+
+decomposeRecord ::
+   Record r o llvmValue ->
+   Value o -> CodeGenFunction r llvmValue
+decomposeRecord m =
+   extractElement m
+
+composeRecord ::
+   (IsType o) =>
+   Record r o llvmValue ->
+   llvmValue -> CodeGenFunction r (Value o)
+composeRecord m v =
+   insertElement m v (LLVM.value LLVM.undef)
+
+
+
+pair ::
+   (C al as, C bl bs,
+    IsSized as sas, IsSized bs sbs) =>
+   Record r (Struct (as, (bs, ()))) (al, bl)
+pair =
+   liftA2 (,)
+      (element fst d0)
+      (element snd d1)
+
+instance
+      (C al as, C bl bs,
+       IsSized as sas, IsSized bs sbs) =>
+      C (al, bl) (Struct (as, (bs, ()))) where
+   load = loadRecord pair
+   store = storeRecord pair
+   decompose = decomposeRecord pair
+   compose = composeRecord pair
+
+
+triple ::
+   (C al as, C bl bs, C cl cs,
+    IsSized as sas, IsSized bs sbs, IsSized cs scs) =>
+   Record r (Struct (as, (bs, (cs, ())))) (al, bl, cl)
+triple =
+   liftA3 (,,)
+      (element fst3 d0)
+      (element snd3 d1)
+      (element thd3 d2)
+
+instance
+      (C al as, C bl bs, C cl cs,
+       IsSized as sas, IsSized bs sbs, IsSized cs scs) =>
+      C (al, bl, cl) (Struct (as, (bs, (cs, ())))) where
+   load = loadRecord triple
+   store = storeRecord triple
+   decompose = decomposeRecord triple
+   compose = composeRecord triple
+
+
+{- |
+ToDo:
+This is dangerous because LLVM uses one bit for Bool representation,
+and I think one byte in memory,
+whereas Storable uses 4 byte and 4 byte alignment.
+We should define a sub-class of IsFirstClass for all compatible types,
+and make this a super-class of this instance.
+-}
+instance (LLVM.IsFirstClass a) => C (Value a) a where
+   load = LLVM.load
+   store = LLVM.store
+   decompose = return
+   compose = return
+
+instance C () (Struct ()) where
+   load _ = return ()
+   store _ _ = return ()
+   decompose _ = return ()
+   compose _ = return (LLVM.value LLVM.undef)
+
+castStorablePtr ::
+   (MakeValueTuple haskellValue llvmValue, C llvmValue llvmStruct) =>
+   Ptr haskellValue -> Ptr llvmStruct
+castStorablePtr = castPtr
+
+
+
+loadNewtype ::
+   (C a o) =>
+   (a -> llvmValue) ->
+   Value (Ptr o) -> CodeGenFunction r llvmValue
+loadNewtype wrap ptr =
+   fmap wrap $ load ptr
+
+storeNewtype ::
+   (C a o) =>
+   (llvmValue -> a) ->
+   llvmValue -> Value (Ptr o) -> CodeGenFunction r ()
+storeNewtype unwrap y ptr =
+   store (unwrap y) ptr
+
+decomposeNewtype ::
+   (C a o) =>
+   (a -> llvmValue) ->
+   Value o -> CodeGenFunction r llvmValue
+decomposeNewtype wrap y =
+   fmap wrap $ decompose y
+
+composeNewtype ::
+   (C a o) =>
+   (llvmValue -> a) ->
+   llvmValue -> CodeGenFunction r (Value o)
+composeNewtype unwrap y =
+   compose (unwrap y)
diff --git a/src/LLVM/Extra/Representation.hs b/src/LLVM/Extra/Representation.hs
deleted file mode 100644
--- a/src/LLVM/Extra/Representation.hs
+++ /dev/null
@@ -1,376 +0,0 @@
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE FunctionalDependencies #-}
-{-# LANGUAGE UndecidableInstances #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE ForeignFunctionInterface #-}
-module LLVM.Extra.Representation (
-   Memory(load, store, decompose, compose), modify, castStorablePtr,
-   MemoryRecord, MemoryElement, memoryElement,
-   loadRecord, storeRecord, decomposeRecord, composeRecord,
-   loadNewtype, storeNewtype, decomposeNewtype, composeNewtype,
-
-   newForeignPtrInit, newForeignPtrParam,
-   newForeignPtr, withForeignPtr,
-   malloc, free,
-   ) where
-
-import qualified LLVM.Core as LLVM
-import LLVM.Core
-   (MakeValueTuple,
-    Struct, getElementPtr0,
-    extractvalue, insertvalue,
-    Value, valueOf, Vector,
-    IsType, IsSized,
-    CodeGenFunction, )
-import LLVM.Util.Loop (Phi, )
-
-import qualified Foreign.Marshal.Utils as Marshal
-import qualified Foreign.ForeignPtr as FPtr
-import qualified Foreign.Concurrent as FC
-import Foreign.Storable (Storable, poke, )
-import Foreign.Ptr (Ptr, castPtr, FunPtr, )
-import Data.TypeLevel.Num (d0, d1, d2, D4, )
-import Data.Word (Word32, Word64, )
--- import Data.Word (Word8, Word16, Word32, Word64, )
--- import Data.Int  (Int8,  Int16,  Int32,  Int64, )
-
-import Control.Monad (ap, )
-import Control.Applicative (pure, liftA2, liftA3, )
-import qualified Control.Applicative as App
-
-import Data.Tuple.HT (fst3, snd3, thd3, )
-
-
--- * Memory class and helper functions
-
-{- |
-An implementation of both 'MakeValueTuple' and 'Memory'
-must ensure that @haskellValue@ is compatible with @llvmStruct@.
-That is, writing and reading @llvmStruct@ by LLVM
-must be the same as accessing @haskellValue@ by 'Storable' methods.
-
-We use a functional dependency in order to let type inference work nicely.
--}
-class (Phi llvmValue, IsType llvmStruct) =>
-      Memory llvmValue llvmStruct | llvmValue -> llvmStruct where
-   load :: Value (Ptr llvmStruct) -> CodeGenFunction r llvmValue
-   load ptr  =  decompose =<< LLVM.load ptr
-   store :: llvmValue -> Value (Ptr llvmStruct) -> CodeGenFunction r (Value ())
-   store r ptr  =  flip LLVM.store ptr =<< compose r
-   decompose :: Value llvmStruct -> CodeGenFunction r llvmValue
-   compose :: llvmValue -> CodeGenFunction r (Value llvmStruct)
-
-modify ::
-   (Memory llvmValue llvmStruct) =>
-   (llvmValue -> CodeGenFunction r llvmValue) ->
-   Value (Ptr llvmStruct) -> CodeGenFunction r (Value ())
-modify f ptr =
-   flip store ptr =<< f =<< load ptr
-
-
-type MemoryRecord r o v = MemoryElement r o v v
-
-data MemoryElement r o v x =
-   MemoryElement {
-      loadElement :: Value (Ptr o) -> CodeGenFunction r x,
-      storeElement :: Value (Ptr o) -> v -> CodeGenFunction r (Value ()),
-      extractElement :: Value o -> CodeGenFunction r x,
-      insertElement :: v -> Value o -> CodeGenFunction r (Value o)
-         -- State.Monoid
-   }
-
-memoryElement ::
-   (Memory x llvmStruct,
-    LLVM.GetValue o n llvmStruct,
-    LLVM.GetElementPtr o (n, ()) llvmStruct) =>
-   (v -> x) -> n -> MemoryElement r o v x
-memoryElement field n =
-   MemoryElement {
-      loadElement = \ptr -> load =<< getElementPtr0 ptr (n, ()),
-      storeElement = \ptr v -> store (field v) =<< getElementPtr0 ptr (n, ()),
-      extractElement = \o -> decompose =<< extractvalue o n,
-      insertElement = \v o -> flip (insertvalue o) n =<< compose (field v)
-   }
-
-instance Functor (MemoryElement r o v) where
-   fmap f m =
-      MemoryElement {
-         loadElement = fmap f . loadElement m,
-         storeElement = storeElement m,
-         extractElement = fmap f . extractElement m,
-         insertElement = insertElement m
-      }
-
-instance App.Applicative (MemoryElement r o v) where
-   pure x =
-      MemoryElement {
-         loadElement = \ _ptr -> return x,
-         storeElement = \ _ptr _v ->
-            return (error "MemoryElement: undefined value" :: Value ()),
-         extractElement = \ _o -> return x,
-         insertElement = \ _v o -> return o
-      }
-   f <*> x =
-      MemoryElement {
-         loadElement = \ptr -> loadElement f ptr `ap` loadElement x ptr,
-         storeElement = \ptr y -> storeElement f ptr y >> storeElement x ptr y,
-         extractElement = \o -> extractElement f o `ap` extractElement x o,
-         insertElement = \y o -> insertElement f y o >>= insertElement x y
-      }
-
-
-loadRecord ::
-   MemoryRecord r o llvmValue ->
-   Value (Ptr o) -> CodeGenFunction r llvmValue
-loadRecord = loadElement
-
-storeRecord ::
-   MemoryRecord r o llvmValue ->
-   llvmValue -> Value (Ptr o) -> CodeGenFunction r (Value ())
-storeRecord m y ptr = storeElement m ptr y
-
-decomposeRecord ::
-   MemoryRecord r o llvmValue ->
-   Value o -> CodeGenFunction r llvmValue
-decomposeRecord m =
-   extractElement m
-
-composeRecord ::
-   (IsType o) =>
-   MemoryRecord r o llvmValue ->
-   llvmValue -> CodeGenFunction r (Value o)
-composeRecord m v =
-   insertElement m v (LLVM.value LLVM.undef)
-
-
-
-pairMemory ::
-   (Memory al as, Memory bl bs,
-    IsSized as sas, IsSized bs sbs) =>
-   MemoryRecord r (Struct (as, (bs, ()))) (al, bl)
-pairMemory =
-   liftA2 (,)
-      (memoryElement fst d0)
-      (memoryElement snd d1)
-
-instance
-      (Memory al as, Memory bl bs,
-       IsSized as sas, IsSized bs sbs) =>
-      Memory (al, bl) (Struct (as, (bs, ()))) where
-   load = loadRecord pairMemory
-   store = storeRecord pairMemory
-   decompose = decomposeRecord pairMemory
-   compose = composeRecord pairMemory
-
-
-tripleMemory ::
-   (Memory al as, Memory bl bs, Memory cl cs,
-    IsSized as sas, IsSized bs sbs, IsSized cs scs) =>
-   MemoryRecord r (Struct (as, (bs, (cs, ())))) (al, bl, cl)
-tripleMemory =
-   liftA3 (,,)
-      (memoryElement fst3 d0)
-      (memoryElement snd3 d1)
-      (memoryElement thd3 d2)
-
-instance
-      (Memory al as, Memory bl bs, Memory cl cs,
-       IsSized as sas, IsSized bs sbs, IsSized cs scs) =>
-      Memory (al, bl, cl) (Struct (as, (bs, (cs, ())))) where
-   load = loadRecord tripleMemory
-   store = storeRecord tripleMemory
-   decompose = decomposeRecord tripleMemory
-   compose = composeRecord tripleMemory
-
-
-instance (LLVM.IsFirstClass a) => Memory (Value a) a where
-   load = LLVM.load
-   store = LLVM.store
-   decompose = return
-   compose = return
-
-instance Memory () (Struct ()) where
-   load _ = return ()
-   store _ _ = return (error "().store: no result" :: Value ())
-   decompose _ = return ()
-   compose _ = return (LLVM.value LLVM.undef)
-
-castStorablePtr ::
-   (MakeValueTuple haskellValue llvmValue, Memory llvmValue llvmStruct) =>
-   Ptr haskellValue -> Ptr llvmStruct
-castStorablePtr = castPtr
-
-
-
-loadNewtype ::
-   (Memory a o) =>
-   (a -> llvmValue) ->
-   Value (Ptr o) -> CodeGenFunction r llvmValue
-loadNewtype wrap ptr =
-   fmap wrap $ load ptr
-
-storeNewtype ::
-   (Memory a o) =>
-   (llvmValue -> a) ->
-   llvmValue -> Value (Ptr o) -> CodeGenFunction r (Value ())
-storeNewtype unwrap y ptr =
-   store (unwrap y) ptr
-
-decomposeNewtype ::
-   (Memory a o) =>
-   (a -> llvmValue) ->
-   Value o -> CodeGenFunction r llvmValue
-decomposeNewtype wrap y =
-   fmap wrap $ decompose y
-
-composeNewtype ::
-   (Memory a o) =>
-   (llvmValue -> a) ->
-   llvmValue -> CodeGenFunction r (Value o)
-composeNewtype unwrap y =
-   compose (unwrap y)
-
-
-
-
--- * ForeignPtr support
-
-type Importer f = FunPtr f -> f
-
-foreign import ccall safe "dynamic" derefStartPtr ::
-   Importer (IO (Ptr a))
-
-newForeignPtrInit ::
-   FunPtr (Ptr a -> IO ()) ->
-   FunPtr (IO (Ptr a)) ->
-   IO (FPtr.ForeignPtr a)
-newForeignPtrInit stop start =
-   FPtr.newForeignPtr stop =<< derefStartPtr start
-
-
-foreign import ccall safe "dynamic" derefStartParamPtr ::
-   Importer (Ptr b -> IO (Ptr a))
-
-{-
-We cannot use 'bracket' when constructing lazy StorableVector,
-since this would mean that the temporary memory is freed immediately.
-Instead we must add a Finalizer to the ForeignPtr.
--}
-newForeignPtrParam ::
-   (Storable b, MakeValueTuple b bl, Memory bl bp) =>
-   FunPtr (Ptr a -> IO ()) ->
-   FunPtr (Ptr bp -> IO (Ptr a)) ->
-   b -> IO (FPtr.ForeignPtr a)
-newForeignPtrParam stop start b =
-   FPtr.newForeignPtr stop =<<
-   Marshal.with b (derefStartParamPtr start . castStorablePtr)
-
-{-
-requires (Storable ap) constraint
-and we have no Storable instance for Struct
-
-newForeignPtr ::
-   (Storable a, MakeValueTuple a al, Memory al ap) =>
-   a -> IO (FPtr.ForeignPtr ap)
-newForeignPtr a = do
-   ptr <- FPtr.mallocForeignPtr
-   FPtr.withForeignPtr ptr (flip poke a . castPtr)
-   return ptr
--}
-
-{- |
-Adding the finalizer to a ForeignPtr seems to be the only way
-that warrants execution of the finalizer (not too early and not never).
-However, the normal ForeignPtr finalizers must be independent from Haskell runtime.
-In contrast to ForeignPtr finalizers,
-addFinalizer adds finalizers to boxes, that are optimized away.
-Thus finalizers are run too early or not at all.
-Concurrent.ForeignPtr and using threaded execution
-is the only way to get finalizers in Haskell IO.
--}
-newForeignPtr ::
-   Storable a =>
-   IO () ->
-   a -> IO (FPtr.ForeignPtr a)
-newForeignPtr finalizer a = do
-   ptr <- FPtr.mallocForeignPtr
-   FC.addForeignPtrFinalizer ptr finalizer
-   FPtr.withForeignPtr ptr (flip poke a)
-   return ptr
-
-withForeignPtr ::
-   (Storable a, MakeValueTuple a al, Memory al ap) =>
-   FPtr.ForeignPtr a -> (Ptr ap -> IO b) -> IO b
-withForeignPtr fp func =
-   FPtr.withForeignPtr fp (func . castStorablePtr)
-
-
-{-
-malloc :: (IsSized a s) => CodeGenFunction r (Value (Ptr a))
-malloc = LLVM.malloc
-
-free :: (IsSized a s) => Value (Ptr a) -> CodeGenFunction r (Value ())
-free = LLVM.free
--}
-
-
-type Aligned a = Struct (a, (Ptr (Vector D4 Float), ()))
-type AlignedPtr a = Ptr (Aligned a)
-
-{- |
-Returns 16 Byte aligned piece of memory.
-Otherwise program crashes when vectors are part of the structure.
-I think that malloc in LLVM-2.5 and LLVM-2.6 is simply buggy.
-
-FIXME:
-Aligning to 16 Byte might not be appropriate for all vector types on all platforms.
-Maybe we should use alignment of Storable class
-in order to determine the right alignment.
--}
-malloc :: (IsSized a s) => CodeGenFunction r (Value (Ptr a))
-malloc =
-   let m :: (IsSized a s) =>
-            CodeGenFunction r (Value (Ptr (Struct (Vector D4 Float, (Aligned a, ())))))
-       m = LLVM.malloc
-   in  do p <- m
-          -- skip pad
-          p1 <- getElementPtr0 p (d1, ())
-          p1int <- LLVM.ptrtoint p1
-          -- go back to the last 16 byte aligned address
-          p16int <- LLVM.and (valueOf (-16) :: Value Word64) (p1int :: Value Word64)
-          p16 <- LLVM.inttoptr p16int
-          {-
-          v has same address as p but different type.
-          This way we avoid a recursive datatype but we avoid also a cast.
-          -}
-          v <- getElementPtr0 p (d0, ())
-          store v =<< getElementPtr0 (p16 `asTypeOf` p1) (d1, ())
-          getElementPtr0 p16 (d0, ())
-
-{-
-This is correct but will be optimized incorrectly.
-The "optimized" code will access a pointer
-that is 4 cells greater than the right pointer
-for certain sizes of the record @a@.
-
-free :: (IsSized a s) => Value (Ptr a) -> CodeGenFunction r (Value ())
-free p =
-   LLVM.free =<<
-   load =<<
-   flip getElementPtr0 (d1, ()) =<<
-   (LLVM.bitcastUnify ::
-      (IsSized a sa) =>
-      Value (Ptr a) ->
-      CodeGenFunction r (Value (AlignedPtr a))) p
--}
-
-free :: (IsSized a s) => Value (Ptr a) -> CodeGenFunction r (Value ())
-free p =
-   LLVM.free =<<
-   load =<<
-   (LLVM.bitcastUnify ::
-      (IsSized a sa) =>
-      Value (Ptr a) ->
-      CodeGenFunction r (Value (Ptr (AlignedPtr a)))) =<<
-   LLVM.getElementPtr p (1 :: Word32, ())
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
@@ -8,7 +8,7 @@
 Attention:
 The rounding and fraction functions only work
 for floating point values with maximum magnitude of @maxBound :: Int32@.
-This way we safe expensive handling of possibly seldom cases.
+This way we save expensive handling of possibly seldom cases.
 -}
 module LLVM.Extra.ScalarOrVector (
    Fraction (truncate, fraction),
@@ -24,16 +24,17 @@
 import qualified LLVM.Extra.Extension.X86 as X86
 import qualified LLVM.Extra.Extension as Ext
 
+import qualified LLVM.Extra.Class as Class
 import qualified LLVM.Extra.Arithmetic as A
 
+import qualified Data.TypeLevel.Num as TypeNum
 import Data.TypeLevel.Num (D1, )
 import qualified LLVM.Core as LLVM
 import LLVM.Core
    (Value, ConstValue, valueOf,
-    Vector, insertelement, constOf, constVector,
-    IsConst, IsFloating, IsPrimitive, IsPowerOf2,
-    CodeGenFunction,
-    FP128, )
+    Vector, FP128,
+    IsConst, IsFloating,
+    CodeGenFunction, )
 
 import Control.Monad.HT ((<=<), )
 
@@ -71,12 +72,12 @@
    fptosi = LLVM.fptosi
    sitofp = LLVM.sitofp
 
-instance (LLVM.IsPowerOf2 n) =>
+instance (TypeNum.Pos n) =>
       Fraction (Vector n Int32) (Vector n Float) where
    fptosi = LLVM.fptosi
    sitofp = LLVM.sitofp
 
-instance (LLVM.IsPowerOf2 n) =>
+instance (TypeNum.Pos n) =>
       Fraction (Vector n Int64) (Vector n Double) where
    fptosi = LLVM.fptosi
    sitofp = LLVM.sitofp
@@ -125,7 +126,7 @@
       (Ext.with X86.roundsd $ \round x ->
          A.sub x =<< round x (valueOf 1))
 
-instance (LLVM.IsPowerOf2 n, Vector.Real a, IsFloating a, IsConst a) =>
+instance (TypeNum.Pos n, Vector.Real a, IsFloating a, IsConst a) =>
       Fraction (Vector n a) where
    truncate = Vector.truncate
    fraction = Vector.fraction
@@ -197,10 +198,10 @@
 instance Replicate Word16 Word16 where replicate = return; replicateConst = id;
 instance Replicate Word32 Word32 where replicate = return; replicateConst = id;
 instance Replicate Word64 Word64 where replicate = return; replicateConst = id;
-instance (LLVM.IsPowerOf2 n, LLVM.IsPrimitive a) => Replicate a (Vector n a) where
+instance (TypeNum.Pos n, LLVM.IsPrimitive a) => Replicate a (Vector n a) where
 {- crashes LLVM-2.5, seems to be fixed in LLVM-2.6 -}
    replicate x = do
-      v <- LLVM.insertelement (LLVM.value LLVM.undef) x (valueOf 0)
+      v <- singleton x
       LLVM.shufflevector v (LLVM.value LLVM.undef) LLVM.zero
 {- crashes LLVM-2.5
    replicate x = do
@@ -216,6 +217,12 @@
 -}
    replicateConst x = LLVM.constVector [x];
 
+singleton ::
+   (LLVM.IsPrimitive a) =>
+   Value a -> CodeGenFunction r (Value (Vector D1 a))
+singleton x =
+   LLVM.insertelement (LLVM.value LLVM.undef) x (valueOf 0)
+
 replicateOf ::
    (IsConst a, Replicate a v) =>
    a -> Value v
@@ -230,16 +237,16 @@
 
 
 instance Real Float  where
-   min = zipAutoWith A.fmin X86.minss
-   max = zipAutoWith A.fmax X86.maxss
-   abs = mapAuto     A.fabs X86.absss
+   min = zipAutoWith A.min X86.minss
+   max = zipAutoWith A.max X86.maxss
+   abs = mapAuto     A.abs X86.absss
    -- abs x = max x =<< LLVM.neg x
-   -- abs x = A.fabs
+   -- abs x = A.abs
 
 instance Real Double where
-   min = zipAutoWith A.fmin X86.minsd
-   max = zipAutoWith A.fmax X86.maxsd
-   abs = mapAuto     A.fabs X86.abssd
+   min = zipAutoWith A.min X86.minsd
+   max = zipAutoWith A.max X86.maxsd
+   abs = mapAuto     A.abs X86.abssd
 
 
 infixl 1 `mapAuto`
@@ -257,7 +264,7 @@
 runScalar op a =
    Vector.extract (valueOf 0)
      =<< op
-     =<< Vector.insert (valueOf 0) a LLVM.undefTuple
+     =<< Vector.insert (valueOf 0) a Class.undefTuple
 
 mapAuto ::
    (Vector.Access n a va, Vector.Access n b vb) =>
@@ -277,17 +284,17 @@
    curry $ mapAuto (uncurry f) (fmap uncurry g)
 
 
-instance Real FP128  where min = A.fmin; max = A.fmax; abs = A.fabs;
-instance Real Int8   where min = A.smin; max = A.smax; abs = A.sabs;
-instance Real Int16  where min = A.smin; max = A.smax; abs = A.sabs;
-instance Real Int32  where min = A.smin; max = A.smax; abs = A.sabs;
-instance Real Int64  where min = A.smin; max = A.smax; abs = A.sabs;
-instance Real Word8  where min = A.umin; max = A.umax; abs = return;
-instance Real Word16 where min = A.umin; max = A.umax; abs = return;
-instance Real Word32 where min = A.umin; max = A.umax; abs = return;
-instance Real Word64 where min = A.umin; max = A.umax; abs = return;
+instance Real FP128  where min = A.min; max = A.max; abs = A.abs;
+instance Real Int8   where min = A.min; max = A.max; abs = A.abs;
+instance Real Int16  where min = A.min; max = A.max; abs = A.abs;
+instance Real Int32  where min = A.min; max = A.max; abs = A.abs;
+instance Real Int64  where min = A.min; max = A.max; abs = A.abs;
+instance Real Word8  where min = A.min; max = A.max; abs = return;
+instance Real Word16 where min = A.min; max = A.max; abs = return;
+instance Real Word32 where min = A.min; max = A.max; abs = return;
+instance Real Word64 where min = A.min; max = A.max; abs = return;
 
-instance (LLVM.IsPowerOf2 n, Vector.Real a) =>
+instance (TypeNum.Pos n, Vector.Real a) =>
          Real (Vector n a) where
    min = Vector.min
    max = Vector.max
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
@@ -13,10 +13,14 @@
    shiftUpMultiZero, shiftDownMultiZero,
    ShuffleMatch (shuffleMatch),
    shuffleMatchTraversable,
+   shuffleMatchAccess,
+   shuffleMatchPlain1,
+   shuffleMatchPlain2,
 
    Access (insert, extract),
    insertTraversable,
    extractTraversable,
+   extractAll,
 
    insertChunk, modify,
    map, mapChunks, zipChunksWith,
@@ -34,6 +38,7 @@
 import qualified LLVM.Extra.Extension.X86 as X86
 import qualified LLVM.Extra.Extension as Ext
 
+import qualified LLVM.Extra.Class as Class
 import qualified LLVM.Extra.Monad as M
 import qualified LLVM.Extra.Arithmetic as A
 
@@ -41,9 +46,9 @@
 import LLVM.Util.Loop (Phi, )
 import LLVM.Core
    (Value, ConstValue, valueOf, value, constOf, undef,
-    Vector, shufflevector, insertelement, extractelement, constVector,
+    Vector, insertelement, extractelement, constVector,
     IsConst, IsArithmetic, IsFloating,
-    IsPrimitive, IsPowerOf2,
+    IsPrimitive,
     CodeGenFunction, )
 
 import Data.TypeLevel.Num (D2, )
@@ -70,10 +75,10 @@
 -- * target independent functions
 
 size ::
-   (TypeNum.Nat n) =>
+   (TypeNum.Pos n) =>
    Value (Vector n a) -> Int
 size =
-   let sz :: (TypeNum.Nat n) => n -> Value (Vector n a) -> Int
+   let sz :: (TypeNum.Pos n) => n -> Value (Vector n a) -> Int
        sz n _ = TypeNum.toInt n
    in  sz undefined
 
@@ -96,15 +101,17 @@
 construct a vector out of single elements
 
 You must assert that the length of the list matches the vector size.
+
+This can be considered the inverse of 'extractAll'.
 -}
 assemble ::
    (Access n a va) =>
    [a] -> CodeGenFunction r va
 assemble =
-   foldM (\v (k,x) -> insert (valueOf k) x v) LLVM.undefTuple .
+   foldM (\v (k,x) -> insert (valueOf k) x v) Class.undefTuple .
    List.zip [0..]
 {- sends GHC into an infinite loop
-   foldM (\(k,x) -> insert (valueOf k) x) LLVM.undefTuple .
+   foldM (\(k,x) -> insert (valueOf k) x) Class.undefTuple .
    List.zip [0..]
 -}
 
@@ -127,7 +134,7 @@
    a -> CodeGenFunction r va
 iterate f x =
    fmap snd $
-   iterateCore f x LLVM.undefTuple
+   iterateCore f x Class.undefTuple
 
 iterateCore ::
    (Access n a va) =>
@@ -147,6 +154,7 @@
 In contrast to LLVM's built-in instruction it supports distinct vector sizes,
 but it allows only one input vector
 (or a tuple of vectors, but we cannot shuffle between them).
+For more complex shuffling we recommend 'extractAll' and 'assemble'.
 -}
 shuffle ::
    (Access m a ca, Access n a va) =>
@@ -226,28 +234,28 @@
       (insert (LLVM.valueOf (fromIntegral (sizeInTuple x) - 1)) x0 y)
 
 shiftUpMultiZero ::
-   (IsPrimitive a, IsPowerOf2 n) =>
+   (IsPrimitive a, TypeNum.Pos n) =>
    Int ->
    Value (Vector n a) ->
    CodeGenFunction r (Value (Vector n a))
 shiftUpMultiZero k x =
-   LLVM.shufflevector (LLVM.value LLVM.zero) x
+   shuffleMatchPlain2 (LLVM.value LLVM.zero) x
       (constVector $ List.map constOf $
        take k [0..] ++ [(fromIntegral (sizeInTuple x)) ..])
 
 shiftDownMultiZero ::
-   (IsPrimitive a, IsPowerOf2 n) =>
+   (IsPrimitive a, TypeNum.Pos n) =>
    Int ->
    Value (Vector n a) ->
    CodeGenFunction r (Value (Vector n a))
 shiftDownMultiZero k x =
-   LLVM.shufflevector x (LLVM.value LLVM.zero)
+   shuffleMatchPlain2 x (LLVM.value LLVM.zero)
       (constVector $ List.map constOf $
        [(fromIntegral k) ..])
 
 
 class
-   (LLVM.IsPowerOf2 n, Phi v) =>
+   (TypeNum.Pos n, Phi v, Class.Undefined v) =>
       ShuffleMatch n v | v -> n where
    shuffleMatch ::
       ConstValue (Vector n Word32) -> v -> CodeGenFunction r v
@@ -258,7 +266,37 @@
 shuffleMatchTraversable is v =
    Trav.mapM (shuffleMatch is) v
 
+{- |
+Implement the 'shuffleMatch' method using the methods of the 'Access' class.
+-}
+shuffleMatchAccess ::
+   (Access n a v) =>
+   ConstValue (Vector n Word32) -> v -> CodeGenFunction r v
+shuffleMatchAccess is v =
+   assemble =<<
+   mapM
+      (flip extract v <=<
+       flip extract (value is) . valueOf)
+      (take (size (value is)) [0..])
 
+
+shuffleMatchPlain1 ::
+   (TypeNum.Pos n, IsPrimitive a) =>
+   Value (Vector n a) ->
+   ConstValue (Vector n Word32) ->
+   CodeGenFunction r (Value (Vector n a))
+shuffleMatchPlain1 x =
+   shuffleMatchPlain2 x (value undef)
+
+shuffleMatchPlain2 ::
+   (TypeNum.Pos n, IsPrimitive a) =>
+   Value (Vector n a) ->
+   Value (Vector n a) ->
+   ConstValue (Vector n Word32) ->
+   CodeGenFunction r (Value (Vector n a))
+shuffleMatchPlain2 =
+   LLVM.shufflevector
+
 {- |
 Allow to work on records of vectors as if they are vectors of records.
 This is a reasonable approach for records of different element types
@@ -284,14 +322,27 @@
 extractTraversable n v =
    Trav.mapM (extract n) v
 
+{- |
+provide the elements of a vector as a list of individual virtual registers
 
+This can be considered the inverse of 'assemble'.
+-}
+extractAll ::
+   (Access n a v) =>
+   v -> LLVM.CodeGenFunction r [a]
+extractAll x =
+   mapM
+      (flip extract x . LLVM.valueOf)
+      (take (sizeInTuple x) [0..])
+
+
 instance
-   (LLVM.IsPowerOf2 n, LLVM.IsPrimitive a) =>
+   (TypeNum.Pos n, LLVM.IsPrimitive a) =>
       ShuffleMatch n (Value (Vector n a)) where
-   shuffleMatch is v = shufflevector v (value undef) is
+   shuffleMatch is v = shuffleMatchPlain1 v is
 
 instance
-   (LLVM.IsPowerOf2 n, LLVM.IsPrimitive a) =>
+   (TypeNum.Pos n, LLVM.IsPrimitive a) =>
       Access n (Value a) (Value (Vector n a)) where
    insert  k a v = insertelement v a k
    extract k v   = extractelement v k
@@ -354,17 +405,20 @@
 Like LLVM.Util.Loop.mapVector but the loop is unrolled,
 which is faster since it can be packed by the code generator.
 -}
-map ::
+map, _mapByFold ::
    (Access n a va, Access n b vb) =>
    (a -> CodeGenFunction r b) ->
    (va -> CodeGenFunction r vb)
-map f a =
+map f =
+   assemble <=< mapM f <=< extractAll
+
+_mapByFold f a =
    foldM
       (\b n ->
          extract (valueOf n) a >>=
          f >>=
          flip (insert (valueOf n)) b)
-      LLVM.undefTuple
+      Class.undefTuple
       (take (sizeInTuple a) [0..])
 
 mapChunks ::
@@ -378,7 +432,7 @@
          am >>= \ac ->
          f ac >>= \bc ->
          insertChunk (k * sizeInTuple ac) bc b)
-      LLVM.undefTuple $
+      Class.undefTuple $
    List.zip (chop a) [0..]
 
 zipChunksWith ::
@@ -414,7 +468,7 @@
 Ideally on ix86 with SSE41 this would be translated to 'dpps'.
 -}
 dotProductPartial ::
-   (LLVM.IsPowerOf2 n, LLVM.IsPrimitive a, LLVM.IsArithmetic a) =>
+   (TypeNum.Pos n, LLVM.IsPrimitive a, LLVM.IsArithmetic a) =>
    Int ->
    Value (Vector n a) ->
    Value (Vector n a) ->
@@ -423,7 +477,7 @@
    sumPartial n =<< A.mul x y
 
 sumPartial ::
-   (LLVM.IsPowerOf2 n, LLVM.IsPrimitive a, LLVM.IsArithmetic a) =>
+   (TypeNum.Pos n, LLVM.IsPrimitive a, LLVM.IsArithmetic a) =>
    Int ->
    Value (Vector n a) ->
    CodeGenFunction r (Value a)
@@ -473,13 +527,14 @@
                insert (valueOf j) x v)
             v0 $
          List.zip [0..] js)
-      LLVM.undefTuple $
+      Class.undefTuple $
    List.zip
       (ListHT.sliceVertical (sizeInTuple (head xs)) [0..])
       xs
 
 
 getLowestPair ::
+   (TypeNum.Pos n) =>
    Value (Vector n a) ->
    CodeGenFunction r (Value a, Value a)
 getLowestPair x =
@@ -490,7 +545,7 @@
 
 _reduceAddInterleaved ::
    (IsArithmetic a, IsPrimitive a,
-    IsPowerOf2 n, IsPowerOf2 m, TypeNum.Mul D2 m n) =>
+    TypeNum.Pos n, TypeNum.Pos m, TypeNum.Mul D2 m n) =>
    m ->
    Value (Vector n a) ->
    CodeGenFunction r (Value (Vector m a))
@@ -501,7 +556,7 @@
    A.add x y
 
 sumGeneric ::
-   (IsArithmetic a, IsPrimitive a, IsPowerOf2 n) =>
+   (IsArithmetic a, IsPrimitive a, TypeNum.Pos n) =>
    Value (Vector n a) ->
    CodeGenFunction r (Value a)
 sumGeneric =
@@ -509,13 +564,13 @@
    reduceSumInterleaved 1
 
 sumToPairGeneric ::
-   (Arithmetic a, IsPowerOf2 n) =>
+   (Arithmetic a, TypeNum.Pos n) =>
    Value (Vector n a) ->
    CodeGenFunction r (Value a, Value a)
 sumToPairGeneric v =
    let n2 = div (size v) 2
    in  sumInterleavedToPair =<<
-       shufflevector v (value undef)
+       shuffleMatchPlain1 v
           (constVector $
            List.map (constOf . fromIntegral) $
            concatMap (\k -> [k, k+n2]) $
@@ -538,13 +593,13 @@
 LLVM actually treats the vectors like vectors of smaller size.
 -}
 reduceSumInterleaved ::
-   (IsArithmetic a, IsPrimitive a, IsPowerOf2 n) =>
+   (IsArithmetic a, IsPrimitive a, TypeNum.Pos n) =>
    Int ->
    Value (Vector n a) ->
    CodeGenFunction r (Value (Vector n a))
 reduceSumInterleaved m x0 =
    let go ::
-          (IsArithmetic a, IsPrimitive a, IsPowerOf2 n) =>
+          (IsArithmetic a, IsPrimitive a, TypeNum.Pos n) =>
           Int ->
           Value (Vector n a) ->
           CodeGenFunction r (Value (Vector n a))
@@ -555,13 +610,13 @@
                let n2 = div n 2
                in  go n2
                       =<< A.add x
-                      =<< shufflevector x (value undef)
+                      =<< shuffleMatchPlain1 x
                              (constVector $ List.map constOf (take n2 [fromIntegral n2 ..])
                                  ++ List.repeat undef)
    in  go (size x0) x0
 
 cumulateGeneric, _cumulateSimple ::
-   (IsArithmetic a, IsPrimitive a, IsPowerOf2 n) =>
+   (IsArithmetic a, IsPrimitive a, TypeNum.Pos n) =>
    Value a -> Value (Vector n a) ->
    CodeGenFunction r (Value a, Value (Vector n a))
 _cumulateSimple a x =
@@ -570,14 +625,14 @@
          a1 <- A.add a0 =<< extract (valueOf k) x
          y1 <- insert (valueOf k) a0 y0
          return (a1,y1))
-      (a, LLVM.undefTuple)
+      (a, Class.undefTuple)
       (take (sizeInTuple x) $ [0..])
 
 cumulateGeneric =
    cumulateFrom1 cumulate1
 
 cumulateFrom1 ::
-   (IsArithmetic a, IsPrimitive a, IsPowerOf2 n) =>
+   (IsArithmetic a, IsPrimitive a, TypeNum.Pos n) =>
    (Value (Vector n a) ->
     CodeGenFunction r (Value (Vector n a))) ->
    Value a -> Value (Vector n a) ->
@@ -593,7 +648,7 @@
 Needs (log n) vector additions
 -}
 cumulate1 ::
-   (IsArithmetic a, IsPrimitive a, IsPowerOf2 n) =>
+   (IsArithmetic a, IsPrimitive a, TypeNum.Pos n) =>
    Value (Vector n a) ->
    CodeGenFunction r (Value (Vector n a))
 cumulate1 x =
@@ -604,14 +659,14 @@
 
 
 signedFraction ::
-   (IsFloating a, IsConst a, Real a, IsPowerOf2 n) =>
+   (IsFloating a, IsConst a, Real a, TypeNum.Pos n) =>
    Value (Vector n a) ->
    CodeGenFunction r (Value (Vector n a))
 signedFraction x =
    A.sub x =<< truncate x
 
 floorGeneric ::
-   (IsFloating a, IsConst a, Real a, IsPowerOf2 n) =>
+   (IsFloating a, IsConst a, Real a, TypeNum.Pos n) =>
    Value (Vector n a) ->
    CodeGenFunction r (Value (Vector n a))
 floorGeneric = floorLogical A.fcmp
@@ -625,7 +680,7 @@
 and then to a floating point number.
 -}
 fractionGeneric ::
-   (IsFloating a, IsConst a, Real a, IsPowerOf2 n) =>
+   (IsFloating a, IsConst a, Real a, TypeNum.Pos n) =>
    Value (Vector n a) ->
    CodeGenFunction r (Value (Vector n a))
 fractionGeneric = fractionLogical A.fcmp
@@ -638,7 +693,7 @@
 When this issue is fixed, this function will be replaced by LLVM.select.
 -}
 select ::
-   (LLVM.IsFirstClass a, IsPrimitive a, IsPowerOf2 n,
+   (LLVM.IsFirstClass a, IsPrimitive a, TypeNum.Pos n,
     LLVM.CmpRet a Bool) =>
    Value (Vector n Bool) ->
    Value (Vector n a) ->
@@ -652,7 +707,7 @@
 This will need jumps.
 -}
 _floorSelect ::
-   (Num a, IsFloating a, IsConst a, Real a, IsPowerOf2 n) =>
+   (Num a, IsFloating a, IsConst a, Real a, TypeNum.Pos n) =>
    Value (Vector n a) ->
    CodeGenFunction r (Value (Vector n a))
 _floorSelect x =
@@ -665,7 +720,7 @@
 This will need jumps.
 -}
 _fractionSelect ::
-   (Num a, IsFloating a, IsConst a, Real a, IsPowerOf2 n) =>
+   (Num a, IsFloating a, IsConst a, Real a, TypeNum.Pos n) =>
    Value (Vector n a) ->
    CodeGenFunction r (Value (Vector n a))
 _fractionSelect x =
@@ -690,7 +745,7 @@
 --    LLVM.IsSized a sa, LLVM.IsSized i si, sa :==: si, si :==: sa,
 --    LLVM.IsSized a s, LLVM.IsSized i s,
     LLVM.IsSized (Vector n a) s, LLVM.IsSized (Vector n i) s,
-    IsPowerOf2 n) =>
+    TypeNum.Pos n) =>
    Value (Vector n i) ->
    Value (Vector n a) ->
    Value (Vector n a) ->
@@ -705,7 +760,7 @@
 
 floorLogical ::
    (IsFloating a, IsConst a, Real a,
-    IsPrimitive i, LLVM.IsInteger i, IsPowerOf2 n) =>
+    IsPrimitive i, LLVM.IsInteger i, TypeNum.Pos n) =>
    (LLVM.FPPredicate ->
     Value (Vector n a) ->
     Value (Vector n a) ->
@@ -719,7 +774,7 @@
 
 fractionLogical ::
    (IsFloating a, IsConst a, Real a,
-    IsPrimitive i, LLVM.IsInteger i, IsPowerOf2 n) =>
+    IsPrimitive i, LLVM.IsInteger i, TypeNum.Pos n) =>
    (LLVM.FPPredicate ->
     Value (Vector n a) ->
     Value (Vector n a) ->
@@ -733,7 +788,7 @@
 
 
 orderBy ::
-   (IsPowerOf2 m,
+   (TypeNum.Pos m,
     LLVM.IsFirstClass a, IsPrimitive a,
     LLVM.IsInteger i, IsPrimitive i,
     LLVM.IsSized (Vector m a) s, LLVM.IsSized (Vector m i) s) =>
@@ -744,7 +799,7 @@
       pcmpgt x y >>= \b -> selectLogical b y x
 
 order ::
-   (IsPowerOf2 n, IsPowerOf2 m,
+   (TypeNum.Pos n, TypeNum.Pos m,
     LLVM.IsFirstClass a, IsPrimitive a,
     LLVM.IsInteger i, IsPrimitive i,
     LLVM.IsSized (Vector m a) s, LLVM.IsSized (Vector m i) s) =>
@@ -779,7 +834,7 @@
 -}
 class (IsArithmetic a, IsPrimitive a) => Arithmetic a where
    sum ::
-      (IsPowerOf2 n) =>
+      (TypeNum.Pos n) =>
       Value (Vector n a) ->
       CodeGenFunction r (Value a)
    sum = sumGeneric
@@ -790,7 +845,7 @@
    n must be at least D2.
    -}
    sumToPair ::
-      (IsPowerOf2 n) =>
+      (TypeNum.Pos n) =>
       Value (Vector n a) ->
       CodeGenFunction r (Value a, Value a)
    sumToPair = sumToPairGeneric
@@ -801,20 +856,20 @@
    n must be at least D2.
    -}
    sumInterleavedToPair ::
-      (IsPowerOf2 n) =>
+      (TypeNum.Pos n) =>
       Value (Vector n a) ->
       CodeGenFunction r (Value a, Value a)
    sumInterleavedToPair v =
       getLowestPair =<< reduceSumInterleaved 2 v
 
    cumulate ::
-      (IsPowerOf2 n) =>
+      (TypeNum.Pos n) =>
       Value a -> Value (Vector n a) ->
       CodeGenFunction r (Value a, Value (Vector n a))
    cumulate = cumulateGeneric
 
    dotProduct ::
-      (IsPowerOf2 n) =>
+      (TypeNum.Pos n) =>
       Value (Vector n a) ->
       Value (Vector n a) ->
       CodeGenFunction r (Value a)
@@ -822,7 +877,7 @@
       dotProductPartial (size x) x y
 
    mul ::
-      (IsPowerOf2 n) =>
+      (TypeNum.Pos n) =>
       Value (Vector n a) ->
       Value (Vector n a) ->
       CodeGenFunction r (Value (Vector n a))
@@ -917,19 +972,19 @@
       (Ext.with X86.pmuludq $ \pmul ->
          zipChunksWith
             (\cx cy -> do
-               evenX <- LLVM.shufflevector cx (value undef)
+               evenX <- shuffleMatchPlain1 cx
                   (constVector [constOf 0, undef, constOf 2, undef])
-               evenY <- LLVM.shufflevector cy (value undef)
+               evenY <- shuffleMatchPlain1 cy
                   (constVector [constOf 0, undef, constOf 2, undef])
                evenZ64 <- pmul evenX evenY
                evenZ <- LLVM.bitcastUnify evenZ64
-               oddX <- LLVM.shufflevector cx (value undef)
+               oddX <- shuffleMatchPlain1 cx
                   (constVector [constOf 1, undef, constOf 3, undef])
-               oddY <- LLVM.shufflevector cy (value undef)
+               oddY <- shuffleMatchPlain1 cy
                   (constVector [constOf 1, undef, constOf 3, undef])
                oddZ64 <- pmul oddX oddY
                oddZ <- LLVM.bitcastUnify oddZ64
-               LLVM.shufflevector evenZ oddZ
+               shuffleMatchPlain2 evenZ oddZ
                   (constVector [constOf 0, constOf 4, constOf 2, constOf 6]))
             x y)
       `Ext.run`
@@ -938,7 +993,7 @@
 
 
 umul32to64 ::
-   (IsPowerOf2 n) =>
+   (TypeNum.Pos n) =>
    Value (Vector n Word32) ->
    Value (Vector n Word32) ->
    CodeGenFunction r (Value (Vector n Word64))
@@ -951,18 +1006,18 @@
       zipChunksWith
          -- save an initial shuffle
          (\cx cy -> do
-            evenX <- LLVM.shufflevector cx (value undef)
+            evenX <- shuffleMatchPlain1 cx
                (constVector [constOf 0, undef, constOf 2, undef])
-            evenY <- LLVM.shufflevector cy (value undef)
+            evenY <- shuffleMatchPlain1 cy
                (constVector [constOf 0, undef, constOf 2, undef])
             evenZ <- pmul evenX evenY
-            oddX <- LLVM.shufflevector cx (value undef)
+            oddX <- shuffleMatchPlain1 cx
                (constVector [constOf 1, undef, constOf 3, undef])
-            oddY <- LLVM.shufflevector cy (value undef)
+            oddY <- shuffleMatchPlain1 cy
                (constVector [constOf 1, undef, constOf 3, undef])
             oddZ <- pmul oddX oddY
 {-
-            LLVM.shufflevector evenZ oddZ
+            shuffleMatchPlain2 evenZ oddZ
                (constVector [constOf 0, constOf 2, constOf 1, constOf 3])
 -}
             assemble =<< (sequence $
@@ -974,18 +1029,18 @@
 {-
          -- save the final shuffle
          (\cx cy -> do
-            lowerX <- LLVM.shufflevector cx (value undef)
+            lowerX <- shuffleMatchPlain1 cx
                (constVector [constOf 0, undef, constOf 1, undef])
-            lowerY <- LLVM.shufflevector cy (value undef)
+            lowerY <- shuffleMatchPlain1 cy
                (constVector [constOf 0, undef, constOf 1, undef])
             lowerZ <- pmul lowerX lowerY
-            upperX <- LLVM.shufflevector cx (value undef)
+            upperX <- shuffleMatchPlain1 cx
                (constVector [constOf 2, undef, constOf 3, undef])
-            upperY <- LLVM.shufflevector cy (value undef)
+            upperY <- shuffleMatchPlain1 cy
                (constVector [constOf 2, undef, constOf 3, undef])
             upperZ <- pmul upperX upperY
 {-
-            LLVM.shufflevector lowerZ upperZ
+            shuffleMatchPlain2 lowerZ upperZ
                (constVector [constOf 0, constOf 1, constOf 2, constOf 3])
 -}
             concat [lowerZ, upperZ])
@@ -1002,25 +1057,25 @@
 class (Arithmetic a, LLVM.CmpRet a Bool, IsConst a) =>
          Real a where
    min, max ::
-      (IsPowerOf2 n) =>
+      (TypeNum.Pos n) =>
       Value (Vector n a) ->
       Value (Vector n a) ->
       CodeGenFunction r (Value (Vector n a))
 
    abs ::
-      (IsPowerOf2 n) =>
+      (TypeNum.Pos n) =>
       Value (Vector n a) ->
       CodeGenFunction r (Value (Vector n a))
 
    truncate, floor, fraction ::
-      (IsPowerOf2 n) =>
+      (TypeNum.Pos n) =>
       Value (Vector n a) ->
       CodeGenFunction r (Value (Vector n a))
 
 instance Real Float where
-   min = zipAutoWith A.fmin X86.minps
-   max = zipAutoWith A.fmax X86.maxps
-   abs = mapAuto A.fabs X86.absps
+   min = zipAutoWith A.min X86.minps
+   max = zipAutoWith A.max X86.maxps
+   abs = mapAuto A.abs X86.absps
    {-
    An IEEE specific implementation could do some bit manipulation:
    s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm
@@ -1071,9 +1126,9 @@
           mapChunks (\c -> A.sub c =<< flip round (valueOf 1) c) x)
 
 instance Real Double where
-   min = zipAutoWith A.fmin X86.minpd
-   max = zipAutoWith A.fmax X86.maxpd
-   abs = mapAuto A.fabs X86.abspd
+   min = zipAutoWith A.min X86.minpd
+   max = zipAutoWith A.max X86.maxpd
+   abs = mapAuto A.abs X86.abspd
    truncate x =
       (LLVM.sitofp .
        (id :: Value (Vector n Int64) -> Value (Vector n Int64))
@@ -1099,33 +1154,33 @@
           mapChunks (\c -> A.sub c =<< flip round (valueOf 1) c) x)
 
 instance Real Int8 where
-   min = order A.smin X86.pcmpgtb X86.pminsb
-   max = order A.smax (fmap flip X86.pcmpgtb) X86.pmaxsb
-   abs = mapAuto A.sabs X86.pabsb
+   min = order A.min X86.pcmpgtb X86.pminsb
+   max = order A.max (fmap flip X86.pcmpgtb) X86.pmaxsb
+   abs = mapAuto A.abs X86.pabsb
    truncate = return
    floor = return
    fraction = const $ return (value LLVM.zero)
 
 instance Real Int16 where
-   min = order A.smin X86.pcmpgtw X86.pminsw
-   max = order A.smax (fmap flip X86.pcmpgtw) X86.pmaxsw
-   abs = mapAuto A.sabs X86.pabsw
+   min = order A.min X86.pcmpgtw X86.pminsw
+   max = order A.max (fmap flip X86.pcmpgtw) X86.pmaxsw
+   abs = mapAuto A.abs X86.pabsw
    truncate = return
    floor = return
    fraction = const $ return (value LLVM.zero)
 
 instance Real Int32 where
-   min = order A.smin X86.pcmpgtd X86.pminsd
-   max = order A.smax (fmap flip X86.pcmpgtd) X86.pmaxsd
-   abs = mapAuto A.sabs X86.pabsd
+   min = order A.min X86.pcmpgtd X86.pminsd
+   max = order A.max (fmap flip X86.pcmpgtd) X86.pmaxsd
+   abs = mapAuto A.abs X86.pabsd
    truncate = return
    floor = return
    fraction = const $ return (value LLVM.zero)
 
 instance Real Int64 where
-   min = zipAutoWith A.smin (orderBy X86.pcmpgtq)
-   max = zipAutoWith A.smax (orderBy (fmap flip X86.pcmpgtq))
-   abs = mapAuto A.sabs $
+   min = zipAutoWith A.min (orderBy X86.pcmpgtq)
+   max = zipAutoWith A.max (orderBy (fmap flip X86.pcmpgtq))
+   abs = mapAuto A.abs $
       Ext.with (orderBy (fmap flip X86.pcmpgtq)) $
          \smax x -> smax x =<< LLVM.neg x
    truncate = return
@@ -1133,32 +1188,32 @@
    fraction = const $ return (value LLVM.zero)
 
 instance Real Word8 where
-   min = order A.umin X86.pcmpugtb X86.pminub
-   max = order A.umax (fmap flip X86.pcmpugtb) X86.pmaxub
+   min = order A.min X86.pcmpugtb X86.pminub
+   max = order A.max (fmap flip X86.pcmpugtb) X86.pmaxub
    abs = return
    truncate = return
    floor = return
    fraction = const $ return (value LLVM.zero)
 
 instance Real Word16 where
-   min = order A.umin X86.pcmpugtw X86.pminuw
-   max = order A.umax (fmap flip X86.pcmpugtw) X86.pmaxuw
+   min = order A.min X86.pcmpugtw X86.pminuw
+   max = order A.max (fmap flip X86.pcmpugtw) X86.pmaxuw
    abs = return
    truncate = return
    floor = return
    fraction = const $ return (value LLVM.zero)
 
 instance Real Word32 where
-   min = order A.umin X86.pcmpugtd X86.pminud
-   max = order A.umax (fmap flip X86.pcmpugtd) X86.pmaxud
+   min = order A.min X86.pcmpugtd X86.pminud
+   max = order A.max (fmap flip X86.pcmpugtd) X86.pmaxud
    abs = return
    truncate = return
    floor = return
    fraction = const $ return (value LLVM.zero)
 
 instance Real Word64 where
-   min = zipAutoWith A.umin (orderBy X86.pcmpugtq)
-   max = zipAutoWith A.umax (orderBy (fmap flip X86.pcmpugtq))
+   min = zipAutoWith A.min (orderBy X86.pcmpugtq)
+   max = zipAutoWith A.max (orderBy (fmap flip X86.pcmpugtq))
    abs = return
    truncate = return
    floor = return
diff --git a/x86/cpuid/LLVM/Extra/ExtensionCheck/X86.hs b/x86/cpuid/LLVM/Extra/ExtensionCheck/X86.hs
--- a/x86/cpuid/LLVM/Extra/ExtensionCheck/X86.hs
+++ b/x86/cpuid/LLVM/Extra/ExtensionCheck/X86.hs
@@ -3,47 +3,44 @@
    ) where
 
 import qualified LLVM.Extra.Extension as Ext
-import Data.Word (Word32, )
-import Data.Bits (testBit, )
-import System.Cpuid (cpuid, )
+import qualified System.Cpuid as CPUID
 import System.IO.Unsafe (unsafePerformIO, )
 
 {-
 I expect that the cpuid does not suddenly change
 and thus calling unsafePerformIO is safe.
 -}
-subtarget :: String -> (Word32 -> Word32 -> Bool) -> Ext.Subtarget
+subtarget ::
+   String ->
+   (CPUID.FlagSet CPUID.Feature1C -> CPUID.FlagSet CPUID.Feature1D -> Bool) ->
+   Ext.Subtarget
 subtarget name q =
    Ext.Subtarget "x86" name
       (return $ unsafePerformIO $ check q)
 
-check :: (Word32 -> Word32 -> Bool) -> IO Bool
-check q = do
-   (high, _, _, _) <- cpuid 0
-   let featureId = 1
-   if featureId>high
-     then return False
-     else do
-       (_,_,ecx,edx) <- cpuid featureId
-       return (q ecx edx)
+check ::
+   (CPUID.FlagSet CPUID.Feature1C -> CPUID.FlagSet CPUID.Feature1D -> Bool) ->
+   IO Bool
+check q =
+   fmap (uncurry q) $ CPUID.features
 
 
 -- * target specific extensions
 
 sse1 :: Ext.Subtarget
-sse1 = subtarget "sse" (\_ecx edx -> testBit edx 25)
+sse1 = subtarget "sse" (\_ecx edx -> CPUID.testFlag CPUID.sse edx)
 
 sse2 :: Ext.Subtarget
-sse2 = subtarget "sse2" (\_ecx edx -> testBit edx 26)
+sse2 = subtarget "sse2" (\_ecx edx -> CPUID.testFlag CPUID.sse2 edx)
 
 sse3 :: Ext.Subtarget
-sse3 = subtarget "sse3" (\ecx _edx -> testBit ecx 0)
+sse3 = subtarget "sse3" (\ecx _edx -> CPUID.testFlag CPUID.sse3 ecx)
 
 ssse3 :: Ext.Subtarget
-ssse3 = subtarget "ssse3" (\ecx _edx -> testBit ecx 9)
+ssse3 = subtarget "ssse3" (\ecx _edx -> CPUID.testFlag CPUID.ssse3 ecx)
 
 sse41 :: Ext.Subtarget
-sse41 = subtarget "sse41" (\ecx _edx -> testBit ecx 19)
+sse41 = subtarget "sse41" (\ecx _edx -> CPUID.testFlag CPUID.sse4_1 ecx)
 
 sse42 :: Ext.Subtarget
-sse42 = subtarget "sse42" (\ecx _edx -> testBit ecx 20)
+sse42 = subtarget "sse42" (\ecx _edx -> CPUID.testFlag CPUID.sse4_2 ecx)
