Add typed holes support in Template Haskell.
[ghc.git] / compiler / prelude / primops.txt.pp
index 094c2f5..e060deb 100644 (file)
@@ -1,11 +1,11 @@
 -----------------------------------------------------------------------
--- 
+--
 -- (c) 2010 The University of Glasgow
 --
 -- Primitive Operations and Types
 --
 -- For more information on PrimOps, see
---   http://hackage.haskell.org/trac/ghc/wiki/Commentary/PrimOps
+--   http://ghc.haskell.org/trac/ghc/wiki/Commentary/PrimOps
 --
 -----------------------------------------------------------------------
 
 -- Information on how PrimOps are implemented and the steps necessary to
 -- add a new one can be found in the Commentary:
 --
---  http://hackage.haskell.org/trac/ghc/wiki/Commentary/PrimOps
+--  http://ghc.haskell.org/trac/ghc/wiki/Commentary/PrimOps
 
 -- This file is divided into named sections, each containing or more
 -- primop entries. Section headers have the format:
 --
---     section "section-name" {description}
+--      section "section-name" {description}
 --
 -- This information is used solely when producing documentation; it is
 -- otherwise ignored.  The description is optional.
 --
 -- The format of each primop entry is as follows:
 --
---     primop internal-name "name-in-program-text" type category {description} attributes
+--      primop internal-name "name-in-program-text" type category {description} attributes
 
 -- The default attribute values which apply if you don't specify
 -- other ones.  Attribute values can be True, False, or arbitrary
--- text between curly brackets.  This is a kludge to enable 
+-- text between curly brackets.  This is a kludge to enable
 -- processors of this file to easily get hold of simple info
 -- (eg, out_of_line), whilst avoiding parsing complex expressions
 -- needed for strictness info.
 
+-- The vector attribute is rather special. It takes a list of 3-tuples, each of
+-- which is of the form <ELEM_TYPE,SCALAR_TYPE,LENGTH>. ELEM_TYPE is the type of
+-- the elements in the vector; LENGTH is the length of the vector; and
+-- SCALAR_TYPE is the scalar type used to inject to/project from vector
+-- element. Note that ELEM_TYPE and SCALAR_TYPE are not the same; for example,
+-- to broadcast a scalar value to a vector whose elements are of type Int8, we
+-- use an Int#.
+
+-- When a primtype or primop has a vector attribute, it is instantiated at each
+-- 3-tuple in the list of 3-tuples. That is, the vector attribute allows us to
+-- define a family of types or primops. Vector support also adds three new
+-- keywords: VECTOR, SCALAR, and VECTUPLE. These keywords are expanded to types
+-- derived from the 3-tuple. For the 3-tuple <Int64,INT64,2>, VECTOR expands to
+-- Int64X2#, SCALAR expands to INT64, and VECTUPLE expands to (# INT64, INT64
+-- #).
+
 defaults
    has_side_effects = False
    out_of_line      = False   -- See Note Note [PrimOp can_fail and has_side_effects] in PrimOp
    can_fail         = False   -- See Note Note [PrimOp can_fail and has_side_effects] in PrimOp
    commutable       = False
    code_size        = { primOpCodeSizeDefault }
-   strictness       = { \ arity -> mkStrictSig (mkTopDmdType (replicate arity topDmd) topRes) }
+   strictness       = { \ arity -> mkClosedStrictSig (replicate arity topDmd) topRes }
    fixity           = Nothing
    llvm_only        = False
+   vector           = []
 
 -- Currently, documentation is produced using latex, so contents of
 -- description fields should be legal latex. Descriptions can contain
@@ -59,65 +76,65 @@ defaults
 #include "ghc_boot_platform.h"
 
 section "The word size story."
-       {Haskell98 specifies that signed integers (type {\tt Int})
-        must contain at least 30 bits. GHC always implements {\tt
-        Int} using the primitive type {\tt Int\#}, whose size equals
-        the {\tt MachDeps.h} constant {\tt WORD\_SIZE\_IN\_BITS}.
-        This is normally set based on the {\tt config.h} parameter
-        {\tt SIZEOF\_HSWORD}, i.e., 32 bits on 32-bit machines, 64
-        bits on 64-bit machines.  However, it can also be explicitly
-        set to a smaller number, e.g., 31 bits, to allow the
-        possibility of using tag bits. Currently GHC itself has only
-        32-bit and 64-bit variants, but 30 or 31-bit code can be
-        exported as an external core file for use in other back ends.
-
-        GHC also implements a primitive unsigned integer type {\tt
-        Word\#} which always has the same number of bits as {\tt
-        Int\#}.
-       
-        In addition, GHC supports families of explicit-sized integers
-        and words at 8, 16, 32, and 64 bits, with the usual
-        arithmetic operations, comparisons, and a range of
-        conversions.  The 8-bit and 16-bit sizes are always
-        represented as {\tt Int\#} and {\tt Word\#}, and the
-        operations implemented in terms of the the primops on these
-        types, with suitable range restrictions on the results (using
-        the {\tt narrow$n$Int\#} and {\tt narrow$n$Word\#} families
-        of primops.  The 32-bit sizes are represented using {\tt
-        Int\#} and {\tt Word\#} when {\tt WORD\_SIZE\_IN\_BITS}
-        $\geq$ 32; otherwise, these are represented using distinct
-        primitive types {\tt Int32\#} and {\tt Word32\#}. These (when
-        needed) have a complete set of corresponding operations;
-        however, nearly all of these are implemented as external C
-        functions rather than as primops.  Exactly the same story
-        applies to the 64-bit sizes.  All of these details are hidden
-        under the {\tt PrelInt} and {\tt PrelWord} modules, which use
-        {\tt \#if}-defs to invoke the appropriate types and
-        operators.
-
-        Word size also matters for the families of primops for
-        indexing/reading/writing fixed-size quantities at offsets
-        from an array base, address, or foreign pointer.  Here, a
-        slightly different approach is taken.  The names of these
-        primops are fixed, but their {\it types} vary according to
-        the value of {\tt WORD\_SIZE\_IN\_BITS}. For example, if word
-        size is at least 32 bits then an operator like
-        \texttt{indexInt32Array\#} has type {\tt ByteArray\# -> Int\#
-        -> Int\#}; otherwise it has type {\tt ByteArray\# -> Int\# ->
-        Int32\#}.  This approach confines the necessary {\tt
-        \#if}-defs to this file; no conditional compilation is needed
-        in the files that expose these primops.
-
-        Finally, there are strongly deprecated primops for coercing
+        {Haskell98 specifies that signed integers (type {\tt Int})
+         must contain at least 30 bits. GHC always implements {\tt
+         Int} using the primitive type {\tt Int\#}, whose size equals
+         the {\tt MachDeps.h} constant {\tt WORD\_SIZE\_IN\_BITS}.
+         This is normally set based on the {\tt config.h} parameter
+         {\tt SIZEOF\_HSWORD}, i.e., 32 bits on 32-bit machines, 64
+         bits on 64-bit machines.  However, it can also be explicitly
+         set to a smaller number, e.g., 31 bits, to allow the
+         possibility of using tag bits. Currently GHC itself has only
+         32-bit and 64-bit variants, but 30 or 31-bit code can be
+         exported as an external core file for use in other back ends.
+
+         GHC also implements a primitive unsigned integer type {\tt
+         Word\#} which always has the same number of bits as {\tt
+         Int\#}.
+
+         In addition, GHC supports families of explicit-sized integers
+         and words at 8, 16, 32, and 64 bits, with the usual
+         arithmetic operations, comparisons, and a range of
+         conversions.  The 8-bit and 16-bit sizes are always
+         represented as {\tt Int\#} and {\tt Word\#}, and the
+         operations implemented in terms of the the primops on these
+         types, with suitable range restrictions on the results (using
+         the {\tt narrow$n$Int\#} and {\tt narrow$n$Word\#} families
+         of primops.  The 32-bit sizes are represented using {\tt
+         Int\#} and {\tt Word\#} when {\tt WORD\_SIZE\_IN\_BITS}
+         $\geq$ 32; otherwise, these are represented using distinct
+         primitive types {\tt Int32\#} and {\tt Word32\#}. These (when
+         needed) have a complete set of corresponding operations;
+         however, nearly all of these are implemented as external C
+         functions rather than as primops.  Exactly the same story
+         applies to the 64-bit sizes.  All of these details are hidden
+         under the {\tt PrelInt} and {\tt PrelWord} modules, which use
+         {\tt \#if}-defs to invoke the appropriate types and
+         operators.
+
+         Word size also matters for the families of primops for
+         indexing/reading/writing fixed-size quantities at offsets
+         from an array base, address, or foreign pointer.  Here, a
+         slightly different approach is taken.  The names of these
+         primops are fixed, but their {\it types} vary according to
+         the value of {\tt WORD\_SIZE\_IN\_BITS}. For example, if word
+         size is at least 32 bits then an operator like
+         \texttt{indexInt32Array\#} has type {\tt ByteArray\# -> Int\#
+         -> Int\#}; otherwise it has type {\tt ByteArray\# -> Int\# ->
+         Int32\#}.  This approach confines the necessary {\tt
+         \#if}-defs to this file; no conditional compilation is needed
+         in the files that expose these primops.
+
+         Finally, there are strongly deprecated primops for coercing
          between {\tt Addr\#}, the primitive type of machine
          addresses, and {\tt Int\#}.  These are pretty bogus anyway,
          but will work on existing 32-bit and 64-bit GHC targets; they
          are completely bogus when tag bits are used in {\tt Int\#},
          so are not available in this case.  }
-       
--- Define synonyms for indexing ops. 
 
-#if WORD_SIZE_IN_BITS < 32 
+-- Define synonyms for indexing ops.
+
+#if WORD_SIZE_IN_BITS < 32
 #define INT32 Int32#
 #define WORD32 Word32#
 #else
@@ -134,32 +151,32 @@ section "The word size story."
 #endif
 
 ------------------------------------------------------------------------
-section "Char#" 
-       {Operations on 31-bit characters.}
+section "Char#"
+        {Operations on 31-bit characters.}
 ------------------------------------------------------------------------
 
 primtype Char#
 
-primop   CharGtOp  "gtCharI#"   Compare   Char# -> Char# -> Int#
-primop   CharGeOp  "geCharI#"   Compare   Char# -> Char# -> Int#
+primop   CharGtOp  "gtChar#"   Compare   Char# -> Char# -> Int#
+primop   CharGeOp  "geChar#"   Compare   Char# -> Char# -> Int#
 
-primop   CharEqOp  "eqCharI#"   Compare
+primop   CharEqOp  "eqChar#"   Compare
    Char# -> Char# -> Int#
    with commutable = True
 
-primop   CharNeOp  "neCharI#"   Compare
+primop   CharNeOp  "neChar#"   Compare
    Char# -> Char# -> Int#
    with commutable = True
 
-primop   CharLtOp  "ltCharI#"   Compare   Char# -> Char# -> Int#
-primop   CharLeOp  "leCharI#"   Compare   Char# -> Char# -> Int#
+primop   CharLtOp  "ltChar#"   Compare   Char# -> Char# -> Int#
+primop   CharLeOp  "leChar#"   Compare   Char# -> Char# -> Int#
 
 primop   OrdOp   "ord#"  GenPrimOp   Char# -> Int#
    with code_size = 0
 
 ------------------------------------------------------------------------
 section "Int#"
-       {Operations on native-size integers (30+ bits).}
+        {Operations on native-size integers (30+ bits).}
 ------------------------------------------------------------------------
 
 primtype Int#
@@ -172,28 +189,28 @@ primop   IntAddOp    "+#"    Dyadic
 primop   IntSubOp    "-#"    Dyadic   Int# -> Int# -> Int#
    with fixity = infixl 6
 
-primop   IntMulOp    "*#" 
+primop   IntMulOp    "*#"
    Dyadic   Int# -> Int# -> Int#
    {Low word of signed integer multiply.}
    with commutable = True
         fixity = infixl 7
 
-primop   IntMulMayOfloOp  "mulIntMayOflo#" 
+primop   IntMulMayOfloOp  "mulIntMayOflo#"
    Dyadic   Int# -> Int# -> Int#
    {Return non-zero if there is any possibility that the upper word of a
     signed integer multiply might contain useful information.  Return
     zero only if you are completely sure that no overflow can occur.
-    On a 32-bit platform, the recommmended implementation is to do a 
+    On a 32-bit platform, the recommmended implementation is to do a
     32 x 32 -> 64 signed multiply, and subtract result[63:32] from
-    (result[31] >>signed 31).  If this is zero, meaning that the 
+    (result[31] >>signed 31).  If this is zero, meaning that the
     upper word is merely a sign extension of the lower one, no
     overflow can occur.
 
-    On a 64-bit platform it is not always possible to 
-    acquire the top 64 bits of the result.  Therefore, a recommended 
-    implementation is to take the absolute value of both operands, and 
-    return 0 iff bits[63:31] of them are zero, since that means that their 
-    magnitudes fit within 31 bits, so the magnitude of the product must fit 
+    On a 64-bit platform it is not always possible to
+    acquire the top 64 bits of the result.  Therefore, a recommended
+    implementation is to take the absolute value of both operands, and
+    return 0 iff bits[63:31] of them are zero, since that means that their
+    magnitudes fit within 31 bits, so the magnitude of the product must fit
     into 62 bits.
 
     If in doubt, return non-zero, but do make an effort to create the
@@ -230,35 +247,41 @@ primop   NotIOp   "notI#"   Monadic   Int# -> Int#
 
 primop   IntNegOp    "negateInt#"    Monadic   Int# -> Int#
 primop   IntAddCOp   "addIntC#"    GenPrimOp   Int# -> Int# -> (# Int#, Int# #)
-        {Add with carry.  First member of result is (wrapped) sum; 
-          second member is 0 iff no overflow occured.}
+         {Add signed integers reporting overflow.
+          First member of result is the sum truncated to an {\tt Int#};
+          second member is zero if the true sum fits in an {\tt Int#},
+          nonzero if overflow occurred (the sum is either too large
+          or too small to fit in an {\tt Int#}).}
    with code_size = 2
 
 primop   IntSubCOp   "subIntC#"    GenPrimOp   Int# -> Int# -> (# Int#, Int# #)
-        {Subtract with carry.  First member of result is (wrapped) difference; 
-          second member is 0 iff no overflow occured.}
+         {Subtract signed integers reporting overflow.
+          First member of result is the difference truncated to an {\tt Int#};
+          second member is zero if the true difference fits in an {\tt Int#},
+          nonzero if overflow occurred (the difference is either too large
+          or too small to fit in an {\tt Int#}).}
    with code_size = 2
 
-primop   IntGtOp  ">$#"   Compare   Int# -> Int# -> Int#
+primop   IntGtOp  ">#"   Compare   Int# -> Int# -> Int#
    with fixity = infix 4
 
-primop   IntGeOp  ">=$#"   Compare   Int# -> Int# -> Int#
+primop   IntGeOp  ">=#"   Compare   Int# -> Int# -> Int#
    with fixity = infix 4
 
-primop   IntEqOp  "==$#"   Compare
+primop   IntEqOp  "==#"   Compare
    Int# -> Int# -> Int#
    with commutable = True
         fixity = infix 4
 
-primop   IntNeOp  "/=$#"   Compare
+primop   IntNeOp  "/=#"   Compare
    Int# -> Int# -> Int#
    with commutable = True
         fixity = infix 4
 
-primop   IntLtOp  "<$#"   Compare   Int# -> Int# -> Int#
+primop   IntLtOp  "<#"   Compare   Int# -> Int# -> Int#
    with fixity = infix 4
 
-primop   IntLeOp  "<=$#"   Compare   Int# -> Int# -> Int#
+primop   IntLeOp  "<=#"   Compare   Int# -> Int# -> Int#
    with fixity = infix 4
 
 primop   ChrOp   "chr#"   GenPrimOp   Int# -> Char#
@@ -274,18 +297,18 @@ primop   Word2FloatOp   "word2Float#"      GenPrimOp  Word# -> Float#
 primop   Word2DoubleOp   "word2Double#"          GenPrimOp  Word# -> Double#
 
 primop   ISllOp   "uncheckedIShiftL#" GenPrimOp  Int# -> Int# -> Int#
-        {Shift left.  Result undefined if shift amount is not
+         {Shift left.  Result undefined if shift amount is not
           in the range 0 to word size - 1 inclusive.}
 primop   ISraOp   "uncheckedIShiftRA#" GenPrimOp Int# -> Int# -> Int#
-        {Shift right arithmetic.  Result undefined if shift amount is not
+         {Shift right arithmetic.  Result undefined if shift amount is not
           in the range 0 to word size - 1 inclusive.}
 primop   ISrlOp   "uncheckedIShiftRL#" GenPrimOp Int# -> Int# -> Int#
-        {Shift right logical.  Result undefined if shift amount is not
+         {Shift right logical.  Result undefined if shift amount is not
           in the range 0 to word size - 1 inclusive.}
 
 ------------------------------------------------------------------------
 section "Word#"
-       {Operations on native-sized unsigned words (30+ bits).}
+        {Operations on native-sized unsigned words (30+ bits).}
 ------------------------------------------------------------------------
 
 primtype Word#
@@ -336,21 +359,21 @@ primop   XorOp   "xor#"   Dyadic   Word# -> Word# -> Word#
 primop   NotOp   "not#"   Monadic   Word# -> Word#
 
 primop   SllOp   "uncheckedShiftL#"   GenPrimOp   Word# -> Int# -> Word#
-        {Shift left logical.   Result undefined if shift amount is not
+         {Shift left logical.   Result undefined if shift amount is not
           in the range 0 to word size - 1 inclusive.}
 primop   SrlOp   "uncheckedShiftRL#"   GenPrimOp   Word# -> Int# -> Word#
-        {Shift right logical.   Result undefined if shift  amount is not
+         {Shift right logical.   Result undefined if shift  amount is not
           in the range 0 to word size - 1 inclusive.}
 
 primop   Word2IntOp   "word2Int#"   GenPrimOp   Word# -> Int#
    with code_size = 0
 
-primop   WordGtOp   "gtWordI#"   Compare   Word# -> Word# -> Int#
-primop   WordGeOp   "geWordI#"   Compare   Word# -> Word# -> Int#
-primop   WordEqOp   "eqWordI#"   Compare   Word# -> Word# -> Int#
-primop   WordNeOp   "neWordI#"   Compare   Word# -> Word# -> Int#
-primop   WordLtOp   "ltWordI#"   Compare   Word# -> Word# -> Int#
-primop   WordLeOp   "leWordI#"   Compare   Word# -> Word# -> Int#
+primop   WordGtOp   "gtWord#"   Compare   Word# -> Word# -> Int#
+primop   WordGeOp   "geWord#"   Compare   Word# -> Word# -> Int#
+primop   WordEqOp   "eqWord#"   Compare   Word# -> Word# -> Int#
+primop   WordNeOp   "neWord#"   Compare   Word# -> Word# -> Int#
+primop   WordLtOp   "ltWord#"   Compare   Word# -> Word# -> Int#
+primop   WordLeOp   "leWord#"   Compare   Word# -> Word# -> Int#
 
 primop   PopCnt8Op   "popCnt8#"   Monadic   Word# -> Word#
     {Count the number of set bits in the lower 8 bits of a word.}
@@ -363,6 +386,28 @@ primop   PopCnt64Op   "popCnt64#"   GenPrimOp   WORD64 -> Word#
 primop   PopCntOp   "popCnt#"   Monadic   Word# -> Word#
     {Count the number of set bits in a word.}
 
+primop   Clz8Op   "clz8#" Monadic   Word# -> Word#
+    {Count leading zeros in the lower 8 bits of a word.}
+primop   Clz16Op   "clz16#" Monadic   Word# -> Word#
+    {Count leading zeros in the lower 16 bits of a word.}
+primop   Clz32Op   "clz32#" Monadic   Word# -> Word#
+    {Count leading zeros in the lower 32 bits of a word.}
+primop   Clz64Op   "clz64#" GenPrimOp WORD64 -> Word#
+    {Count leading zeros in a 64-bit word.}
+primop   ClzOp     "clz#"   Monadic   Word# -> Word#
+    {Count leading zeros in a word.}
+
+primop   Ctz8Op   "ctz8#"  Monadic   Word# -> Word#
+    {Count trailing zeros in the lower 8 bits of a word.}
+primop   Ctz16Op   "ctz16#" Monadic   Word# -> Word#
+    {Count trailing zeros in the lower 16 bits of a word.}
+primop   Ctz32Op   "ctz32#" Monadic   Word# -> Word#
+    {Count trailing zeros in the lower 32 bits of a word.}
+primop   Ctz64Op   "ctz64#" GenPrimOp WORD64 -> Word#
+    {Count trailing zeros in a 64-bit word.}
+primop   CtzOp     "ctz#"   Monadic   Word# -> Word#
+    {Count trailing zeros in a word.}
+
 primop   BSwap16Op   "byteSwap16#"   Monadic   Word# -> Word#
     {Swap bytes in the lower 16 bits of a word. The higher bytes are undefined. }
 primop   BSwap32Op   "byteSwap32#"   Monadic   Word# -> Word#
@@ -373,8 +418,8 @@ primop   BSwapOp     "byteSwap#"     Monadic   Word# -> Word#
     {Swap bytes in a word.}
 
 ------------------------------------------------------------------------
-section "Narrowings" 
-       {Explicit narrowing of native-sized ints or words.}
+section "Narrowings"
+        {Explicit narrowing of native-sized ints or words.}
 ------------------------------------------------------------------------
 
 primop   Narrow8IntOp      "narrow8Int#"      Monadic   Int# -> Int#
@@ -388,40 +433,40 @@ primop   Narrow32WordOp    "narrow32Word#"    Monadic   Word# -> Word#
 #if WORD_SIZE_IN_BITS < 32
 ------------------------------------------------------------------------
 section "Int32#"
-       {Operations on 32-bit integers ({\tt Int32\#}).  This type is only used
+        {Operations on 32-bit integers ({\tt Int32\#}).  This type is only used
          if plain {\tt Int\#} has less than 32 bits.  In any case, the operations
-        are not primops; they are implemented (if needed) as ccalls instead.}
+         are not primops; they are implemented (if needed) as ccalls instead.}
 ------------------------------------------------------------------------
 
 primtype Int32#
 
 ------------------------------------------------------------------------
 section "Word32#"
-       {Operations on 32-bit unsigned words. This type is only used 
-        if plain {\tt Word\#} has less than 32 bits. In any case, the operations
-        are not primops; they are implemented (if needed) as ccalls instead.}
+        {Operations on 32-bit unsigned words. This type is only used
+         if plain {\tt Word\#} has less than 32 bits. In any case, the operations
+         are not primops; they are implemented (if needed) as ccalls instead.}
 ------------------------------------------------------------------------
 
 primtype Word32#
 
-#endif 
+#endif
 
 
 #if WORD_SIZE_IN_BITS < 64
 ------------------------------------------------------------------------
 section "Int64#"
-       {Operations on 64-bit unsigned words. This type is only used 
-        if plain {\tt Int\#} has less than 64 bits. In any case, the operations
-        are not primops; they are implemented (if needed) as ccalls instead.}
+        {Operations on 64-bit unsigned words. This type is only used
+         if plain {\tt Int\#} has less than 64 bits. In any case, the operations
+         are not primops; they are implemented (if needed) as ccalls instead.}
 ------------------------------------------------------------------------
 
 primtype Int64#
 
 ------------------------------------------------------------------------
 section "Word64#"
-       {Operations on 64-bit unsigned words. This type is only used 
-        if plain {\tt Word\#} has less than 64 bits. In any case, the operations
-        are not primops; they are implemented (if needed) as ccalls instead.}
+        {Operations on 64-bit unsigned words. This type is only used
+         if plain {\tt Word\#} has less than 64 bits. In any case, the operations
+         are not primops; they are implemented (if needed) as ccalls instead.}
 ------------------------------------------------------------------------
 
 primtype Word64#
@@ -430,31 +475,31 @@ primtype Word64#
 
 ------------------------------------------------------------------------
 section "Double#"
-       {Operations on double-precision (64 bit) floating-point numbers.}
+        {Operations on double-precision (64 bit) floating-point numbers.}
 ------------------------------------------------------------------------
 
 primtype Double#
 
-primop   DoubleGtOp ">$##"   Compare   Double# -> Double# -> Int#
+primop   DoubleGtOp ">##"   Compare   Double# -> Double# -> Int#
    with fixity = infix 4
 
-primop   DoubleGeOp ">=$##"   Compare   Double# -> Double# -> Int#
+primop   DoubleGeOp ">=##"   Compare   Double# -> Double# -> Int#
    with fixity = infix 4
 
-primop DoubleEqOp "==$##"   Compare
+primop DoubleEqOp "==##"   Compare
    Double# -> Double# -> Int#
    with commutable = True
         fixity = infix 4
 
-primop DoubleNeOp "/=$##"   Compare
+primop DoubleNeOp "/=##"   Compare
    Double# -> Double# -> Int#
    with commutable = True
         fixity = infix 4
 
-primop   DoubleLtOp "<$##"   Compare   Double# -> Double# -> Int#
+primop   DoubleLtOp "<##"   Compare   Double# -> Double# -> Int#
    with fixity = infix 4
 
-primop   DoubleLeOp "<=$##"   Compare   Double# -> Double# -> Int#
+primop   DoubleLeOp "<=##"   Compare   Double# -> Double# -> Int#
    with fixity = infix 4
 
 primop   DoubleAddOp   "+##"   Dyadic
@@ -489,71 +534,71 @@ primop   DoubleExpOp   "expDouble#"      Monadic
    with
    code_size = { primOpCodeSizeForeignCall }
 
-primop   DoubleLogOp   "logDouble#"      Monadic         
+primop   DoubleLogOp   "logDouble#"      Monadic
    Double# -> Double#
    with
    code_size = { primOpCodeSizeForeignCall }
    can_fail = True
 
-primop   DoubleSqrtOp   "sqrtDouble#"      Monadic  
+primop   DoubleSqrtOp   "sqrtDouble#"      Monadic
    Double# -> Double#
    with
    code_size = { primOpCodeSizeForeignCall }
 
-primop   DoubleSinOp   "sinDouble#"      Monadic          
+primop   DoubleSinOp   "sinDouble#"      Monadic
    Double# -> Double#
    with
    code_size = { primOpCodeSizeForeignCall }
 
-primop   DoubleCosOp   "cosDouble#"      Monadic          
+primop   DoubleCosOp   "cosDouble#"      Monadic
    Double# -> Double#
    with
    code_size = { primOpCodeSizeForeignCall }
 
-primop   DoubleTanOp   "tanDouble#"      Monadic          
+primop   DoubleTanOp   "tanDouble#"      Monadic
    Double# -> Double#
    with
    code_size = { primOpCodeSizeForeignCall }
 
-primop   DoubleAsinOp   "asinDouble#"      Monadic 
+primop   DoubleAsinOp   "asinDouble#"      Monadic
    Double# -> Double#
    with
    code_size = { primOpCodeSizeForeignCall }
    can_fail = True
 
-primop   DoubleAcosOp   "acosDouble#"      Monadic  
+primop   DoubleAcosOp   "acosDouble#"      Monadic
    Double# -> Double#
    with
    code_size = { primOpCodeSizeForeignCall }
    can_fail = True
 
-primop   DoubleAtanOp   "atanDouble#"      Monadic  
+primop   DoubleAtanOp   "atanDouble#"      Monadic
    Double# -> Double#
    with
    code_size = { primOpCodeSizeForeignCall }
 
-primop   DoubleSinhOp   "sinhDouble#"      Monadic  
+primop   DoubleSinhOp   "sinhDouble#"      Monadic
    Double# -> Double#
    with
    code_size = { primOpCodeSizeForeignCall }
 
-primop   DoubleCoshOp   "coshDouble#"      Monadic  
+primop   DoubleCoshOp   "coshDouble#"      Monadic
    Double# -> Double#
    with
    code_size = { primOpCodeSizeForeignCall }
 
-primop   DoubleTanhOp   "tanhDouble#"      Monadic  
+primop   DoubleTanhOp   "tanhDouble#"      Monadic
    Double# -> Double#
    with
    code_size = { primOpCodeSizeForeignCall }
 
-primop   DoublePowerOp   "**##" Dyadic  
+primop   DoublePowerOp   "**##" Dyadic
    Double# -> Double# -> Double#
    {Exponentiation.}
    with
    code_size = { primOpCodeSizeForeignCall }
 
-primop   DoubleDecode_2IntOp   "decodeDouble_2Int#" GenPrimOp    
+primop   DoubleDecode_2IntOp   "decodeDouble_2Int#" GenPrimOp
    Double# -> (# Int#, Word#, Word#, Int# #)
    {Convert to integer.
     First component of the result is -1 or 1, indicating the sign of the
@@ -561,38 +606,43 @@ primop   DoubleDecode_2IntOp   "decodeDouble_2Int#" GenPrimOp
     respectively, and the last is the exponent.}
    with out_of_line = True
 
+primop   DoubleDecode_Int64Op   "decodeDouble_Int64#" GenPrimOp
+   Double# -> (# INT64, Int# #)
+   {Decode {\tt Double\#} into mantissa and base-2 exponent.}
+   with out_of_line = True
+
 ------------------------------------------------------------------------
-section "Float#" 
-       {Operations on single-precision (32-bit) floating-point numbers.}
+section "Float#"
+        {Operations on single-precision (32-bit) floating-point numbers.}
 ------------------------------------------------------------------------
 
 primtype Float#
 
-primop   FloatGtOp  "gtFloatI#"   Compare   Float# -> Float# -> Int#
-primop   FloatGeOp  "geFloatI#"   Compare   Float# -> Float# -> Int#
+primop   FloatGtOp  "gtFloat#"   Compare   Float# -> Float# -> Int#
+primop   FloatGeOp  "geFloat#"   Compare   Float# -> Float# -> Int#
 
-primop   FloatEqOp  "eqFloatI#"   Compare
+primop   FloatEqOp  "eqFloat#"   Compare
    Float# -> Float# -> Int#
    with commutable = True
 
-primop   FloatNeOp  "neFloatI#"   Compare
+primop   FloatNeOp  "neFloat#"   Compare
    Float# -> Float# -> Int#
    with commutable = True
 
-primop   FloatLtOp  "ltFloatI#"   Compare   Float# -> Float# -> Int#
-primop   FloatLeOp  "leFloatI#"   Compare   Float# -> Float# -> Int#
+primop   FloatLtOp  "ltFloat#"   Compare   Float# -> Float# -> Int#
+primop   FloatLeOp  "leFloat#"   Compare   Float# -> Float# -> Int#
 
-primop   FloatAddOp   "plusFloat#"      Dyadic            
+primop   FloatAddOp   "plusFloat#"      Dyadic
    Float# -> Float# -> Float#
    with commutable = True
 
 primop   FloatSubOp   "minusFloat#"      Dyadic      Float# -> Float# -> Float#
 
-primop   FloatMulOp   "timesFloat#"      Dyadic    
+primop   FloatMulOp   "timesFloat#"      Dyadic
    Float# -> Float# -> Float#
    with commutable = True
 
-primop   FloatDivOp   "divideFloat#"      Dyadic  
+primop   FloatDivOp   "divideFloat#"      Dyadic
    Float# -> Float# -> Float#
    with can_fail = True
 
@@ -603,70 +653,70 @@ primop   Float2IntOp   "float2Int#"      GenPrimOp  Float# -> Int#
     Results are undefined if the truncation if truncation yields
     a value outside the range of {\tt Int#}.}
 
-primop   FloatExpOp   "expFloat#"      Monadic          
+primop   FloatExpOp   "expFloat#"      Monadic
    Float# -> Float#
    with
    code_size = { primOpCodeSizeForeignCall }
 
-primop   FloatLogOp   "logFloat#"      Monadic          
+primop   FloatLogOp   "logFloat#"      Monadic
    Float# -> Float#
    with
    code_size = { primOpCodeSizeForeignCall }
    can_fail = True
 
-primop   FloatSqrtOp   "sqrtFloat#"      Monadic          
+primop   FloatSqrtOp   "sqrtFloat#"      Monadic
    Float# -> Float#
    with
    code_size = { primOpCodeSizeForeignCall }
 
-primop   FloatSinOp   "sinFloat#"      Monadic          
+primop   FloatSinOp   "sinFloat#"      Monadic
    Float# -> Float#
    with
    code_size = { primOpCodeSizeForeignCall }
 
-primop   FloatCosOp   "cosFloat#"      Monadic          
+primop   FloatCosOp   "cosFloat#"      Monadic
    Float# -> Float#
    with
    code_size = { primOpCodeSizeForeignCall }
 
-primop   FloatTanOp   "tanFloat#"      Monadic          
+primop   FloatTanOp   "tanFloat#"      Monadic
    Float# -> Float#
    with
    code_size = { primOpCodeSizeForeignCall }
 
-primop   FloatAsinOp   "asinFloat#"      Monadic          
+primop   FloatAsinOp   "asinFloat#"      Monadic
    Float# -> Float#
    with
    code_size = { primOpCodeSizeForeignCall }
    can_fail = True
 
-primop   FloatAcosOp   "acosFloat#"      Monadic          
+primop   FloatAcosOp   "acosFloat#"      Monadic
    Float# -> Float#
    with
    code_size = { primOpCodeSizeForeignCall }
    can_fail = True
 
-primop   FloatAtanOp   "atanFloat#"      Monadic          
+primop   FloatAtanOp   "atanFloat#"      Monadic
    Float# -> Float#
    with
    code_size = { primOpCodeSizeForeignCall }
 
-primop   FloatSinhOp   "sinhFloat#"      Monadic          
+primop   FloatSinhOp   "sinhFloat#"      Monadic
    Float# -> Float#
    with
    code_size = { primOpCodeSizeForeignCall }
 
-primop   FloatCoshOp   "coshFloat#"      Monadic          
+primop   FloatCoshOp   "coshFloat#"      Monadic
    Float# -> Float#
    with
    code_size = { primOpCodeSizeForeignCall }
 
-primop   FloatTanhOp   "tanhFloat#"      Monadic          
+primop   FloatTanhOp   "tanhFloat#"      Monadic
    Float# -> Float#
    with
    code_size = { primOpCodeSizeForeignCall }
 
-primop   FloatPowerOp   "powerFloat#"      Dyadic   
+primop   FloatPowerOp   "powerFloat#"      Dyadic
    Float# -> Float# -> Float#
    with
    code_size = { primOpCodeSizeForeignCall }
@@ -681,7 +731,7 @@ primop   FloatDecode_IntOp   "decodeFloat_Int#" GenPrimOp
 
 ------------------------------------------------------------------------
 section "Arrays"
-       {Operations on {\tt Array\#}.}
+        {Operations on {\tt Array\#}.}
 ------------------------------------------------------------------------
 
 primtype Array# a
@@ -745,54 +795,74 @@ primop  UnsafeThawArrayOp  "unsafeThawArray#" GenPrimOp
 
 primop  CopyArrayOp "copyArray#" GenPrimOp
   Array# a -> Int# -> MutableArray# s a -> Int# -> Int# -> State# s -> State# s
-  {Copy a range of the Array# to the specified region in the MutableArray#.
-   Both arrays must fully contain the specified ranges, but this is not checked.
-   The two arrays must not be the same array in different states, but this is not checked either.}
+  {Given a source array, an offset into the source array, a
+   destination array, an offset into the destination array, and a
+   number of elements to copy, copy the elements from the source array
+   to the destination array. Both arrays must fully contain the
+   specified ranges, but this is not checked. The two arrays must not
+   be the same array in different states, but this is not checked
+   either.}
   with
+  out_of_line      = True
   has_side_effects = True
   can_fail         = True
-  code_size = { primOpCodeSizeForeignCall + 4 }
 
 primop  CopyMutableArrayOp "copyMutableArray#" GenPrimOp
   MutableArray# s a -> Int# -> MutableArray# s a -> Int# -> Int# -> State# s -> State# s
-  {Copy a range of the first MutableArray# to the specified region in the second MutableArray#.
-   Both arrays must fully contain the specified ranges, but this is not checked.}
+  {Given a source array, an offset into the source array, a
+   destination array, an offset into the destination array, and a
+   number of elements to copy, copy the elements from the source array
+   to the destination array. The source and destination arrays can
+   refer to the same array. Both arrays must fully contain the
+   specified ranges, but this is not checked.}
   with
+  out_of_line      = True
   has_side_effects = True
   can_fail         = True
-  code_size = { primOpCodeSizeForeignCall + 4 }
 
 primop  CloneArrayOp "cloneArray#" GenPrimOp
   Array# a -> Int# -> Int# -> Array# a
-  {Return a newly allocated Array# with the specified subrange of the provided Array#. 
-   The provided Array# should contain the full subrange specified by the two Int#s, but this is not checked.}
+  {Given a source array, an offset into the source array, and a number
+   of elements to copy, create a new array with the elements from the
+   source array. The provided array must fully contain the specified
+   range, but this is not checked.}
   with
+  out_of_line      = True
   has_side_effects = True
-  code_size = { primOpCodeSizeForeignCall + 4 }
+  can_fail         = True
 
 primop  CloneMutableArrayOp "cloneMutableArray#" GenPrimOp
   MutableArray# s a -> Int# -> Int# -> State# s -> (# State# s, MutableArray# s a #)
-  {Return a newly allocated Array# with the specified subrange of the provided Array#.
-   The provided MutableArray# should contain the full subrange specified by the two Int#s, but this is not checked.}
+  {Given a source array, an offset into the source array, and a number
+   of elements to copy, create a new array with the elements from the
+   source array. The provided array must fully contain the specified
+   range, but this is not checked.}
   with
+  out_of_line      = True
   has_side_effects = True
-  code_size = { primOpCodeSizeForeignCall + 4 }
+  can_fail         = True
 
 primop  FreezeArrayOp "freezeArray#" GenPrimOp
   MutableArray# s a -> Int# -> Int# -> State# s -> (# State# s, Array# a #)
-  {Return a newly allocated Array# with the specified subrange of the provided MutableArray#.
-   The provided MutableArray# should contain the full subrange specified by the two Int#s, but this is not checked.}
+  {Given a source array, an offset into the source array, and a number
+   of elements to copy, create a new array with the elements from the
+   source array. The provided array must fully contain the specified
+   range, but this is not checked.}
   with
+  out_of_line      = True
   has_side_effects = True
-  code_size = { primOpCodeSizeForeignCall + 4 }
+  can_fail         = True
 
 primop  ThawArrayOp "thawArray#" GenPrimOp
   Array# a -> Int# -> Int# -> State# s -> (# State# s, MutableArray# s a #)
-  {Return a newly allocated Array# with the specified subrange of the provided MutableArray#.
-   The provided Array# should contain the full subrange specified by the two Int#s, but this is not checked.}
+  {Given a source array, an offset into the source array, and a number
+   of elements to copy, create a new array with the elements from the
+   source array. The provided array must fully contain the specified
+   range, but this is not checked.}
   with
+  out_of_line      = True
   has_side_effects = True
-  code_size = { primOpCodeSizeForeignCall + 4 }
+  can_fail         = True
 
 primop CasArrayOp  "casArray#" GenPrimOp
    MutableArray# s a -> Int# -> a -> a -> State# s -> (# State# s, Int#, a #)
@@ -803,8 +873,170 @@ primop CasArrayOp  "casArray#" GenPrimOp
 
 
 ------------------------------------------------------------------------
+section "Small Arrays"
+
+        {Operations on {\tt SmallArray\#}. A {\tt SmallArray\#} works
+         just like an {\tt Array\#}, but with different space use and
+         performance characteristics (that are often useful with small
+         arrays). The {\tt SmallArray\#} and {\tt SmallMutableArray#}
+         lack a `card table'. The purpose of a card table is to avoid
+         having to scan every element of the array on each GC by
+         keeping track of which elements have changed since the last GC
+         and only scanning those that have changed. So the consequence
+         of there being no card table is that the representation is
+         somewhat smaller and the writes are somewhat faster (because
+         the card table does not need to be updated). The disadvantage
+         of course is that for a {\tt SmallMutableArray#} the whole
+         array has to be scanned on each GC. Thus it is best suited for
+         use cases where the mutable array is not long lived, e.g.
+         where a mutable array is initialised quickly and then frozen
+         to become an immutable {\tt SmallArray\#}.
+        }
+
+------------------------------------------------------------------------
+
+primtype SmallArray# a
+
+primtype SmallMutableArray# s a
+
+primop  NewSmallArrayOp "newSmallArray#" GenPrimOp
+   Int# -> a -> State# s -> (# State# s, SmallMutableArray# s a #)
+   {Create a new mutable array with the specified number of elements,
+    in the specified state thread,
+    with each element containing the specified initial value.}
+   with
+   out_of_line = True
+   has_side_effects = True
+
+primop  SameSmallMutableArrayOp "sameSmallMutableArray#" GenPrimOp
+   SmallMutableArray# s a -> SmallMutableArray# s a -> Int#
+
+primop  ReadSmallArrayOp "readSmallArray#" GenPrimOp
+   SmallMutableArray# s a -> Int# -> State# s -> (# State# s, a #)
+   {Read from specified index of mutable array. Result is not yet evaluated.}
+   with
+   has_side_effects = True
+   can_fail         = True
+
+primop  WriteSmallArrayOp "writeSmallArray#" GenPrimOp
+   SmallMutableArray# s a -> Int# -> a -> State# s -> State# s
+   {Write to specified index of mutable array.}
+   with
+   has_side_effects = True
+   can_fail         = True
+
+primop  SizeofSmallArrayOp "sizeofSmallArray#" GenPrimOp
+   SmallArray# a -> Int#
+   {Return the number of elements in the array.}
+
+primop  SizeofSmallMutableArrayOp "sizeofSmallMutableArray#" GenPrimOp
+   SmallMutableArray# s a -> Int#
+   {Return the number of elements in the array.}
+
+primop  IndexSmallArrayOp "indexSmallArray#" GenPrimOp
+   SmallArray# a -> Int# -> (# a #)
+   {Read from specified index of immutable array. Result is packaged into
+    an unboxed singleton; the result itself is not yet evaluated.}
+   with
+   can_fail         = True
+
+primop  UnsafeFreezeSmallArrayOp "unsafeFreezeSmallArray#" GenPrimOp
+   SmallMutableArray# s a -> State# s -> (# State# s, SmallArray# a #)
+   {Make a mutable array immutable, without copying.}
+   with
+   has_side_effects = True
+
+primop  UnsafeThawSmallArrayOp  "unsafeThawSmallArray#" GenPrimOp
+   SmallArray# a -> State# s -> (# State# s, SmallMutableArray# s a #)
+   {Make an immutable array mutable, without copying.}
+   with
+   out_of_line = True
+   has_side_effects = True
+
+-- The code_size is only correct for the case when the copy family of
+-- primops aren't inlined. It would be nice to keep track of both.
+
+primop  CopySmallArrayOp "copySmallArray#" GenPrimOp
+  SmallArray# a -> Int# -> SmallMutableArray# s a -> Int# -> Int# -> State# s -> State# s
+  {Given a source array, an offset into the source array, a
+   destination array, an offset into the destination array, and a
+   number of elements to copy, copy the elements from the source array
+   to the destination array. Both arrays must fully contain the
+   specified ranges, but this is not checked. The two arrays must not
+   be the same array in different states, but this is not checked
+   either.}
+  with
+  out_of_line      = True
+  has_side_effects = True
+  can_fail         = True
+
+primop  CopySmallMutableArrayOp "copySmallMutableArray#" GenPrimOp
+  SmallMutableArray# s a -> Int# -> SmallMutableArray# s a -> Int# -> Int# -> State# s -> State# s
+  {Given a source array, an offset into the source array, a
+   destination array, an offset into the destination array, and a
+   number of elements to copy, copy the elements from the source array
+   to the destination array. The source and destination arrays can
+   refer to the same array. Both arrays must fully contain the
+   specified ranges, but this is not checked.}
+  with
+  out_of_line      = True
+  has_side_effects = True
+  can_fail         = True
+
+primop  CloneSmallArrayOp "cloneSmallArray#" GenPrimOp
+  SmallArray# a -> Int# -> Int# -> SmallArray# a
+  {Given a source array, an offset into the source array, and a number
+   of elements to copy, create a new array with the elements from the
+   source array. The provided array must fully contain the specified
+   range, but this is not checked.}
+  with
+  out_of_line      = True
+  has_side_effects = True
+  can_fail         = True
+
+primop  CloneSmallMutableArrayOp "cloneSmallMutableArray#" GenPrimOp
+  SmallMutableArray# s a -> Int# -> Int# -> State# s -> (# State# s, SmallMutableArray# s a #)
+  {Given a source array, an offset into the source array, and a number
+   of elements to copy, create a new array with the elements from the
+   source array. The provided array must fully contain the specified
+   range, but this is not checked.}
+  with
+  out_of_line      = True
+  has_side_effects = True
+  can_fail         = True
+
+primop  FreezeSmallArrayOp "freezeSmallArray#" GenPrimOp
+  SmallMutableArray# s a -> Int# -> Int# -> State# s -> (# State# s, SmallArray# a #)
+  {Given a source array, an offset into the source array, and a number
+   of elements to copy, create a new array with the elements from the
+   source array. The provided array must fully contain the specified
+   range, but this is not checked.}
+  with
+  out_of_line      = True
+  has_side_effects = True
+  can_fail         = True
+
+primop  ThawSmallArrayOp "thawSmallArray#" GenPrimOp
+  SmallArray# a -> Int# -> Int# -> State# s -> (# State# s, SmallMutableArray# s a #)
+  {Given a source array, an offset into the source array, and a number
+   of elements to copy, create a new array with the elements from the
+   source array. The provided array must fully contain the specified
+   range, but this is not checked.}
+  with
+  out_of_line      = True
+  has_side_effects = True
+  can_fail         = True
+
+primop CasSmallArrayOp  "casSmallArray#" GenPrimOp
+   SmallMutableArray# s a -> Int# -> a -> a -> State# s -> (# State# s, Int#, a #)
+   {Unsafe, machine-level atomic compare and swap on an element within an array.}
+   with
+   out_of_line = True
+   has_side_effects = True
+
+------------------------------------------------------------------------
 section "Byte Arrays"
-       {Operations on {\tt ByteArray\#}. A {\tt ByteArray\#} is a just a region of
+        {Operations on {\tt ByteArray\#}. A {\tt ByteArray\#} is a just a region of
          raw memory in the garbage-collected heap, which is not
          scanned for pointers. It carries its own size (in bytes).
          There are
@@ -847,19 +1079,49 @@ primop  ByteArrayContents_Char "byteArrayContents#" GenPrimOp
 primop  SameMutableByteArrayOp "sameMutableByteArray#" GenPrimOp
    MutableByteArray# s -> MutableByteArray# s -> Int#
 
+primop  ShrinkMutableByteArrayOp_Char "shrinkMutableByteArray#" GenPrimOp
+   MutableByteArray# s -> Int# -> State# s -> State# s
+   {Shrink mutable byte array to new specified size (in bytes), in
+    the specified state thread. The new size argument must be less than or
+    equal to the current size as reported by {\tt sizeofMutableArray\#}.}
+   with out_of_line = True
+        has_side_effects = True
+
+primop  ResizeMutableByteArrayOp_Char "resizeMutableByteArray#" GenPrimOp
+   MutableByteArray# s -> Int# -> State# s -> (# State# s,MutableByteArray# s #)
+   {Resize (unpinned) mutable byte array to new specified size (in bytes).
+    The returned {\tt MutableByteArray\#} is either the original
+    {\tt MutableByteArray\#} resized in-place or, if not possible, a newly
+    allocated (unpinned) {\tt MutableByteArray\#} (with the original content
+    copied over).
+
+    To avoid undefined behaviour, the original {\tt MutableByteArray\#} shall
+    not be accessed anymore after a {\tt resizeMutableByteArray\#} has been
+    performed.  Moreover, no reference to the old one should be kept in order
+    to allow garbage collection of the original {\tt MutableByteArray\#} in
+    case a new {\tt MutableByteArray\#} had to be allocated.}
+   with out_of_line = True
+        has_side_effects = True
+
 primop  UnsafeFreezeByteArrayOp "unsafeFreezeByteArray#" GenPrimOp
    MutableByteArray# s -> State# s -> (# State# s, ByteArray# #)
    {Make a mutable byte array immutable, without copying.}
    with
    has_side_effects = True
 
-primop  SizeofByteArrayOp "sizeofByteArray#" GenPrimOp  
+primop  SizeofByteArrayOp "sizeofByteArray#" GenPrimOp
    ByteArray# -> Int#
    {Return the size of the array in bytes.}
 
 primop  SizeofMutableByteArrayOp "sizeofMutableByteArray#" GenPrimOp
    MutableByteArray# s -> Int#
-   {Return the size of the array in bytes.}
+   {Return the size of the array in bytes. Note that this is deprecated as it is
+   unsafe in the presence of concurrent resize operations on the same byte
+   array. See {\tt getSizeofMutableByteArray}.}
+
+primop  GetSizeofMutableByteArrayOp "getSizeofMutableByteArray#" GenPrimOp
+   MutableByteArray# s -> State# s -> (# State# s, Int# #)
+   {Return the number of elements in the array.}
 
 primop IndexByteArrayOp_Char "indexCharArray#" GenPrimOp
    ByteArray# -> Int# -> Char#
@@ -897,34 +1159,42 @@ primop IndexByteArrayOp_StablePtr "indexStablePtrArray#" GenPrimOp
 
 primop IndexByteArrayOp_Int8 "indexInt8Array#" GenPrimOp
    ByteArray# -> Int# -> Int#
+   {Read 8-bit integer; offset in bytes.}
    with can_fail = True
 
 primop IndexByteArrayOp_Int16 "indexInt16Array#" GenPrimOp
    ByteArray# -> Int# -> Int#
+   {Read 16-bit integer; offset in 16-bit words.}
    with can_fail = True
 
 primop IndexByteArrayOp_Int32 "indexInt32Array#" GenPrimOp
    ByteArray# -> Int# -> INT32
+   {Read 32-bit integer; offset in 32-bit words.}
    with can_fail = True
 
 primop IndexByteArrayOp_Int64 "indexInt64Array#" GenPrimOp
    ByteArray# -> Int# -> INT64
+   {Read 64-bit integer; offset in 64-bit words.}
    with can_fail = True
 
 primop IndexByteArrayOp_Word8 "indexWord8Array#" GenPrimOp
    ByteArray# -> Int# -> Word#
+   {Read 8-bit word; offset in bytes.}
    with can_fail = True
 
 primop IndexByteArrayOp_Word16 "indexWord16Array#" GenPrimOp
    ByteArray# -> Int# -> Word#
+   {Read 16-bit word; offset in 16-bit words.}
    with can_fail = True
 
 primop IndexByteArrayOp_Word32 "indexWord32Array#" GenPrimOp
    ByteArray# -> Int# -> WORD32
+   {Read 32-bit word; offset in 32-bit words.}
    with can_fail = True
 
 primop IndexByteArrayOp_Word64 "indexWord64Array#" GenPrimOp
    ByteArray# -> Int# -> WORD64
+   {Read 64-bit word; offset in 64-bit words.}
    with can_fail = True
 
 primop  ReadByteArrayOp_Char "readCharArray#" GenPrimOp
@@ -941,11 +1211,13 @@ primop  ReadByteArrayOp_WideChar "readWideCharArray#" GenPrimOp
 
 primop  ReadByteArrayOp_Int "readIntArray#" GenPrimOp
    MutableByteArray# s -> Int# -> State# s -> (# State# s, Int# #)
+   {Read intger; offset in words.}
    with has_side_effects = True
         can_fail = True
 
 primop  ReadByteArrayOp_Word "readWordArray#" GenPrimOp
    MutableByteArray# s -> Int# -> State# s -> (# State# s, Word# #)
+   {Read word; offset in words.}
    with has_side_effects = True
         can_fail = True
 
@@ -1110,6 +1382,42 @@ primop  CopyMutableByteArrayOp "copyMutableByteArray#" GenPrimOp
   code_size = { primOpCodeSizeForeignCall + 4 }
   can_fail = True
 
+primop  CopyByteArrayToAddrOp "copyByteArrayToAddr#" GenPrimOp
+  ByteArray# -> Int# -> Addr# -> Int# -> State# s -> State# s
+  {Copy a range of the ByteArray# to the memory range starting at the Addr#.
+   The ByteArray# and the memory region at Addr# must fully contain the
+   specified ranges, but this is not checked. The Addr# must not point into the
+   ByteArray# (e.g. if the ByteArray# were pinned), but this is not checked
+   either.}
+  with
+  has_side_effects = True
+  code_size = { primOpCodeSizeForeignCall + 4}
+  can_fail = True
+
+primop  CopyMutableByteArrayToAddrOp "copyMutableByteArrayToAddr#" GenPrimOp
+  MutableByteArray# s -> Int# -> Addr# -> Int# -> State# s -> State# s
+  {Copy a range of the MutableByteArray# to the memory range starting at the
+   Addr#. The MutableByteArray# and the memory region at Addr# must fully
+   contain the specified ranges, but this is not checked. The Addr# must not
+   point into the MutableByteArray# (e.g. if the MutableByteArray# were
+   pinned), but this is not checked either.}
+  with
+  has_side_effects = True
+  code_size = { primOpCodeSizeForeignCall + 4}
+  can_fail = True
+
+primop  CopyAddrToByteArrayOp "copyAddrToByteArray#" GenPrimOp
+  Addr# -> MutableByteArray# s -> Int# -> Int# -> State# s -> State# s
+  {Copy a memory range starting at the Addr# to the specified range in the
+   MutableByteArray#. The memory region at Addr# and the ByteArray# must fully
+   contain the specified ranges, but this is not checked. The Addr# must not
+   point into the MutableByteArray# (e.g. if the MutableByteArray# were pinned),
+   but this is not checked either.}
+  with
+  has_side_effects = True
+  code_size = { primOpCodeSizeForeignCall + 4}
+  can_fail = True
+
 primop  SetByteArrayOp "setByteArray#" GenPrimOp
   MutableByteArray# s -> Int# -> Int# -> Int# -> State# s -> State# s
   {Set the range of the MutableByteArray# to the specified character.}
@@ -1118,28 +1426,88 @@ primop  SetByteArrayOp "setByteArray#" GenPrimOp
   code_size = { primOpCodeSizeForeignCall + 4 }
   can_fail = True
 
+-- Atomic operations
+
+primop  AtomicReadByteArrayOp_Int "atomicReadIntArray#" GenPrimOp
+   MutableByteArray# s -> Int# -> State# s -> (# State# s, Int# #)
+   {Given an array and an offset in Int units, read an element. The
+    index is assumed to be in bounds. Implies a full memory barrier.}
+   with has_side_effects = True
+        can_fail = True
+
+primop  AtomicWriteByteArrayOp_Int "atomicWriteIntArray#" GenPrimOp
+   MutableByteArray# s -> Int# -> Int# -> State# s -> State# s
+   {Given an array and an offset in Int units, write an element. The
+    index is assumed to be in bounds. Implies a full memory barrier.}
+   with has_side_effects = True
+        can_fail = True
+
 primop CasByteArrayOp_Int "casIntArray#" GenPrimOp
    MutableByteArray# s -> Int# -> Int# -> Int# -> State# s -> (# State# s, Int# #)
-   {Machine-level atomic compare and swap on a word within a ByteArray.}
-   with
-   out_of_line = True
-   has_side_effects = True
+   {Given an array, an offset in Int units, the expected old value, and
+    the new value, perform an atomic compare and swap i.e. write the new
+    value if the current value matches the provided old value. Returns
+    the value of the element before the operation. Implies a full memory
+    barrier.}
+   with has_side_effects = True
+        can_fail = True
 
 primop FetchAddByteArrayOp_Int "fetchAddIntArray#" GenPrimOp
-   MutableByteArray# s -> Int# -> Int# -> State# s -> (# State# s, Int# #) 
-   {Machine-level word-sized fetch-and-add within a ByteArray.}
-   with
-   out_of_line = True
-   has_side_effects = True
+   MutableByteArray# s -> Int# -> Int# -> State# s -> (# State# s, Int# #)
+   {Given an array, and offset in Int units, and a value to add,
+    atomically add the value to the element. Returns the value of the
+    element before the operation. Implies a full memory barrier.}
+   with has_side_effects = True
+        can_fail = True
+
+primop FetchSubByteArrayOp_Int "fetchSubIntArray#" GenPrimOp
+   MutableByteArray# s -> Int# -> Int# -> State# s -> (# State# s, Int# #)
+   {Given an array, and offset in Int units, and a value to subtract,
+    atomically substract the value to the element. Returns the value of
+    the element before the operation. Implies a full memory barrier.}
+   with has_side_effects = True
+        can_fail = True
+
+primop FetchAndByteArrayOp_Int "fetchAndIntArray#" GenPrimOp
+   MutableByteArray# s -> Int# -> Int# -> State# s -> (# State# s, Int# #)
+   {Given an array, and offset in Int units, and a value to AND,
+    atomically AND the value to the element. Returns the value of the
+    element before the operation. Implies a full memory barrier.}
+   with has_side_effects = True
+        can_fail = True
+
+primop FetchNandByteArrayOp_Int "fetchNandIntArray#" GenPrimOp
+   MutableByteArray# s -> Int# -> Int# -> State# s -> (# State# s, Int# #)
+   {Given an array, and offset in Int units, and a value to NAND,
+    atomically NAND the value to the element. Returns the value of the
+    element before the operation. Implies a full memory barrier.}
+   with has_side_effects = True
+        can_fail = True
+
+primop FetchOrByteArrayOp_Int "fetchOrIntArray#" GenPrimOp
+   MutableByteArray# s -> Int# -> Int# -> State# s -> (# State# s, Int# #)
+   {Given an array, and offset in Int units, and a value to OR,
+    atomically OR the value to the element. Returns the value of the
+    element before the operation. Implies a full memory barrier.}
+   with has_side_effects = True
+        can_fail = True
+
+primop FetchXorByteArrayOp_Int "fetchXorIntArray#" GenPrimOp
+   MutableByteArray# s -> Int# -> Int# -> State# s -> (# State# s, Int# #)
+   {Given an array, and offset in Int units, and a value to XOR,
+    atomically XOR the value to the element. Returns the value of the
+    element before the operation. Implies a full memory barrier.}
+   with has_side_effects = True
+        can_fail = True
 
 
 ------------------------------------------------------------------------
 section "Arrays of arrays"
-       {Operations on {\tt ArrayArray\#}. An {\tt ArrayArray\#} contains references to {\em unpointed}
-        arrays, such as {\tt ByteArray\#s}. Hence, it is not parameterised by the element types,
-        just like a {\tt ByteArray\#}, but it needs to be scanned during GC, just like an {\tt Array#}.
-        We represent an {\tt ArrayArray\#} exactly as a {\tt Array\#}, but provide element-type-specific
-        indexing, reading, and writing.}
+        {Operations on {\tt ArrayArray\#}. An {\tt ArrayArray\#} contains references to {\em unpointed}
+         arrays, such as {\tt ByteArray\#s}. Hence, it is not parameterised by the element types,
+         just like a {\tt ByteArray\#}, but it needs to be scanned during GC, just like an {\tt Array#}.
+         We represent an {\tt ArrayArray\#} exactly as a {\tt Array\#}, but provide element-type-specific
+         indexing, reading, and writing.}
 ------------------------------------------------------------------------
 
 primtype ArrayArray#
@@ -1226,9 +1594,9 @@ primop  CopyArrayArrayOp "copyArrayArray#" GenPrimOp
    Both arrays must fully contain the specified ranges, but this is not checked.
    The two arrays must not be the same array in different states, but this is not checked either.}
   with
+  out_of_line      = True
   has_side_effects = True
-  can_fail = True
-  code_size = { primOpCodeSizeForeignCall }
+  can_fail         = True
 
 primop  CopyMutableArrayArrayOp "copyMutableArrayArray#" GenPrimOp
   MutableArrayArray# s -> Int# -> MutableArrayArray# s -> Int# -> Int# -> State# s -> State# s
@@ -1236,43 +1604,43 @@ primop  CopyMutableArrayArrayOp "copyMutableArrayArray#" GenPrimOp
    MutableArrayArray#.
    Both arrays must fully contain the specified ranges, but this is not checked.}
   with
+  out_of_line      = True
   has_side_effects = True
-  code_size = { primOpCodeSizeForeignCall }
-  can_fail = True
+  can_fail         = True
 
 ------------------------------------------------------------------------
 section "Addr#"
 ------------------------------------------------------------------------
 
 primtype Addr#
-       { An arbitrary machine address assumed to point outside
-        the garbage-collected heap. }
+        { An arbitrary machine address assumed to point outside
+         the garbage-collected heap. }
 
 pseudoop "nullAddr#" Addr#
-       { The null address. }
-
-primop  AddrAddOp "plusAddr#" GenPrimOp Addr# -> Int# -> Addr#
-primop  AddrSubOp "minusAddr#" GenPrimOp Addr# -> Addr# -> Int#
-        {Result is meaningless if two {\tt Addr\#}s are so far apart that their
-        difference doesn't fit in an {\tt Int\#}.}
-primop  AddrRemOp "remAddr#" GenPrimOp Addr# -> Int# -> Int#
-        {Return the remainder when the {\tt Addr\#} arg, treated like an {\tt Int\#},
-         is divided by the {\tt Int\#} arg.}
+        { The null address. }
+
+primop   AddrAddOp "plusAddr#" GenPrimOp Addr# -> Int# -> Addr#
+primop   AddrSubOp "minusAddr#" GenPrimOp Addr# -> Addr# -> Int#
+         {Result is meaningless if two {\tt Addr\#}s are so far apart that their
+         difference doesn't fit in an {\tt Int\#}.}
+primop   AddrRemOp "remAddr#" GenPrimOp Addr# -> Int# -> Int#
+         {Return the remainder when the {\tt Addr\#} arg, treated like an {\tt Int\#},
+          is divided by the {\tt Int\#} arg.}
 #if (WORD_SIZE_IN_BITS == 32 || WORD_SIZE_IN_BITS == 64)
 primop   Addr2IntOp  "addr2Int#"     GenPrimOp   Addr# -> Int#
-       {Coerce directly from address to int. Strongly deprecated.}
+        {Coerce directly from address to int. Strongly deprecated.}
    with code_size = 0
 primop   Int2AddrOp   "int2Addr#"    GenPrimOp  Int# -> Addr#
-       {Coerce directly from int to address. Strongly deprecated.}
+        {Coerce directly from int to address. Strongly deprecated.}
    with code_size = 0
 #endif
 
-primop   AddrGtOp  "gtAddrI#"   Compare   Addr# -> Addr# -> Int#
-primop   AddrGeOp  "geAddrI#"   Compare   Addr# -> Addr# -> Int#
-primop   AddrEqOp  "eqAddrI#"   Compare   Addr# -> Addr# -> Int#
-primop   AddrNeOp  "neAddrI#"   Compare   Addr# -> Addr# -> Int#
-primop   AddrLtOp  "ltAddrI#"   Compare   Addr# -> Addr# -> Int#
-primop   AddrLeOp  "leAddrI#"   Compare   Addr# -> Addr# -> Int#
+primop   AddrGtOp  "gtAddr#"   Compare   Addr# -> Addr# -> Int#
+primop   AddrGeOp  "geAddr#"   Compare   Addr# -> Addr# -> Int#
+primop   AddrEqOp  "eqAddr#"   Compare   Addr# -> Addr# -> Int#
+primop   AddrNeOp  "neAddr#"   Compare   Addr# -> Addr# -> Int#
+primop   AddrLtOp  "ltAddr#"   Compare   Addr# -> Addr# -> Int#
+primop   AddrLeOp  "leAddr#"   Compare   Addr# -> Addr# -> Int#
 
 primop IndexOffAddrOp_Char "indexCharOffAddr#" GenPrimOp
    Addr# -> Int# -> Char#
@@ -1504,11 +1872,11 @@ primop  WriteOffAddrOp_Word64 "writeWord64OffAddr#" GenPrimOp
 
 ------------------------------------------------------------------------
 section "Mutable variables"
-       {Operations on MutVar\#s.}
+        {Operations on MutVar\#s.}
 ------------------------------------------------------------------------
 
 primtype MutVar# s a
-       {A {\tt MutVar\#} behaves like a single-element mutable array.}
+        {A {\tt MutVar\#} behaves like a single-element mutable array.}
 
 primop  NewMutVarOp "newMutVar#" GenPrimOp
    a -> State# s -> (# State# s, MutVar# s a #)
@@ -1557,40 +1925,73 @@ primop  CasMutVarOp "casMutVar#" GenPrimOp
 section "Exceptions"
 ------------------------------------------------------------------------
 
+{- Note [Strictness for mask/unmask/catch]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider this example, which comes from GHC.IO.Handle.Internals:
+   wantReadableHandle3 f ma b st
+     = case ... of
+         DEFAULT -> case ma of MVar a -> ...
+         0#      -> maskAsynchExceptions# (\st -> case ma of MVar a -> ...)
+The outer case just decides whether to mask exceptions, but we don't want
+thereby to hide the strictness in 'ma'!  Hence the use of strictApply1Dmd.
+
+For catch, we know that the first branch will be evaluated, but not
+necessarily the second.  Hence strictApply1Dmd and lazyApply1Dmd
+
+Howver, consider
+    catch# (\st -> case x of ...) (..handler..) st
+We'll see that the entire thing is strict in 'x', so 'x' may be evaluated
+before the catch#.  So fi evaluting 'x' causes a divide-by-zero exception,
+it won't be caught.  This seems acceptable:
+  - x might be evaluated somewhere else outside the catch# anyway
+  - It's an imprecise eception anyway.  Synchronous exceptions (in the
+    IO monad) will never move in this way.
+There was originally a comment
+  "Catch is actually strict in its first argument
+   but we don't want to tell the strictness
+   analyser about that, so that exceptions stay inside it."
+but tracing it back through the commit logs did not give any
+rationale.  And making catch# lazy has performance costs for everyone.
+-}
+
 primop  CatchOp "catch#" GenPrimOp
           (State# RealWorld -> (# State# RealWorld, a #) )
-       -> (b -> State# RealWorld -> (# State# RealWorld, a #) ) 
+       -> (b -> State# RealWorld -> (# State# RealWorld, a #) )
        -> State# RealWorld
        -> (# State# RealWorld, a #)
    with
-       -- Catch is actually strict in its first argument
-       -- but we don't want to tell the strictness
-       -- analyser about that!
-        -- might use caught action multiply
+   strictness  = { \ _arity -> mkClosedStrictSig [strictApply1Dmd,lazyApply2Dmd,topDmd] topRes }
+                 -- See Note [Strictness for mask/unmask/catch]
    out_of_line = True
    has_side_effects = True
 
 primop  RaiseOp "raise#" GenPrimOp
-   a -> b
+   b -> o
+      -- NB: the type variable "o" is "a", but with OpenKind
    with
-   strictness  = { \ _arity -> mkStrictSig (mkTopDmdType [topDmd] botRes) }
+   strictness  = { \ _arity -> mkClosedStrictSig [topDmd] botRes }
       -- NB: result is bottom
    out_of_line = True
+   has_side_effects = True
+     -- raise# certainly throws a Haskell exception and hence has_side_effects
+     -- It doesn't actually make much difference because the fact that it
+     -- returns bottom independently ensures that we are careful not to discard
+     -- it.  But still, it's better to say the Right Thing.
 
 -- raiseIO# needs to be a primop, because exceptions in the IO monad
 -- must be *precise* - we don't want the strictness analyser turning
 -- one kind of bottom into another, as it is allowed to do in pure code.
 --
--- But we *do* want to know that it returns bottom after 
+-- But we *do* want to know that it returns bottom after
 -- being applied to two arguments, so that this function is strict in y
---     f x y | x>0      = raiseIO blah
---           | y>0      = return 1
---           | otherwise = return 2 
+--     f x y | x>0       = raiseIO blah
+--           | y>0       = return 1
+--           | otherwise = return 2
 
 primop  RaiseIOOp "raiseIO#" GenPrimOp
    a -> State# RealWorld -> (# State# RealWorld, b #)
    with
-   strictness  = { \ _arity -> mkStrictSig (mkTopDmdType [topDmd, topDmd] botRes) }
+   strictness  = { \ _arity -> mkClosedStrictSig [topDmd, topDmd] botRes }
    out_of_line = True
    has_side_effects = True
 
@@ -1598,6 +1999,8 @@ primop  MaskAsyncExceptionsOp "maskAsyncExceptions#" GenPrimOp
         (State# RealWorld -> (# State# RealWorld, a #))
      -> (State# RealWorld -> (# State# RealWorld, a #))
    with
+   strictness  = { \ _arity -> mkClosedStrictSig [strictApply1Dmd,topDmd] topRes }
+                 -- See Note [Strictness for mask/unmask/catch]
    out_of_line = True
    has_side_effects = True
 
@@ -1605,6 +2008,7 @@ primop  MaskUninterruptibleOp "maskUninterruptible#" GenPrimOp
         (State# RealWorld -> (# State# RealWorld, a #))
      -> (State# RealWorld -> (# State# RealWorld, a #))
    with
+   strictness  = { \ _arity -> mkClosedStrictSig [strictApply1Dmd,topDmd] topRes }
    out_of_line = True
    has_side_effects = True
 
@@ -1612,6 +2016,8 @@ primop  UnmaskAsyncExceptionsOp "unmaskAsyncExceptions#" GenPrimOp
         (State# RealWorld -> (# State# RealWorld, a #))
      -> (State# RealWorld -> (# State# RealWorld, a #))
    with
+   strictness  = { \ _arity -> mkClosedStrictSig [strictApply1Dmd,topDmd] topRes }
+                 -- See Note [Strictness for mask/unmask/catch]
    out_of_line = True
    has_side_effects = True
 
@@ -1627,10 +2033,12 @@ section "STM-accessible Mutable Variables"
 
 primtype TVar# s a
 
-primop AtomicallyOp "atomically#" GenPrimOp
+primop  AtomicallyOp "atomically#" GenPrimOp
       (State# RealWorld -> (# State# RealWorld, a #) )
    -> State# RealWorld -> (# State# RealWorld, a #)
    with
+   strictness  = { \ _arity -> mkClosedStrictSig [strictApply1Dmd,topDmd] topRes }
+                 -- See Note [Strictness for mask/unmask/catch]
    out_of_line = True
    has_side_effects = True
 
@@ -1646,8 +2054,8 @@ primop    AtomicallyOp "atomically#" GenPrimOp
 -- where 'e' would be unreachable anyway.  See Trac #8091.
 primop  RetryOp "retry#" GenPrimOp
    State# RealWorld -> (# State# RealWorld, a #)
-   with 
-   strictness  = { \ _arity -> mkStrictSig (mkTopDmdType [topDmd] botRes) }
+   with
+   strictness  = { \ _arity -> mkClosedStrictSig [topDmd] botRes }
    out_of_line = True
    has_side_effects = True
 
@@ -1655,7 +2063,9 @@ primop  CatchRetryOp "catchRetry#" GenPrimOp
       (State# RealWorld -> (# State# RealWorld, a #) )
    -> (State# RealWorld -> (# State# RealWorld, a #) )
    -> (State# RealWorld -> (# State# RealWorld, a #) )
-   with 
+   with
+   strictness  = { \ _arity -> mkClosedStrictSig [strictApply1Dmd,lazyApply1Dmd,topDmd] topRes }
+                 -- See Note [Strictness for mask/unmask/catch]
    out_of_line = True
    has_side_effects = True
 
@@ -1663,18 +2073,20 @@ primop  CatchSTMOp "catchSTM#" GenPrimOp
       (State# RealWorld -> (# State# RealWorld, a #) )
    -> (b -> State# RealWorld -> (# State# RealWorld, a #) )
    -> (State# RealWorld -> (# State# RealWorld, a #) )
-   with 
+   with
+   strictness  = { \ _arity -> mkClosedStrictSig [strictApply1Dmd,lazyApply2Dmd,topDmd] topRes }
+                 -- See Note [Strictness for mask/unmask/catch]
    out_of_line = True
    has_side_effects = True
 
 primop  Check "check#" GenPrimOp
       (State# RealWorld -> (# State# RealWorld, a #) )
-   -> (State# RealWorld -> (# State# RealWorld, () #) )
-   with 
+   -> (State# RealWorld -> State# RealWorld)
+   with
    out_of_line = True
    has_side_effects = True
 
-primop NewTVarOp "newTVar#" GenPrimOp
+primop  NewTVarOp "newTVar#" GenPrimOp
        a
     -> State# s -> (# State# s, TVar# s a #)
    {Create a new {\tt TVar\#} holding a specified initial value.}
@@ -1682,12 +2094,12 @@ primop  NewTVarOp "newTVar#" GenPrimOp
    out_of_line  = True
    has_side_effects = True
 
-primop ReadTVarOp "readTVar#" GenPrimOp
+primop  ReadTVarOp "readTVar#" GenPrimOp
        TVar# s a
     -> State# s -> (# State# s, a #)
    {Read contents of {\tt TVar\#}.  Result is not yet evaluated.}
    with
-   out_of_line = True
+   out_of_line  = True
    has_side_effects = True
 
 primop ReadTVarIOOp "readTVarIO#" GenPrimOp
@@ -1695,16 +2107,16 @@ primop ReadTVarIOOp "readTVarIO#" GenPrimOp
     -> State# s -> (# State# s, a #)
    {Read contents of {\tt TVar\#} outside an STM transaction}
    with
-   out_of_line = True
+   out_of_line      = True
    has_side_effects = True
 
-primop WriteTVarOp "writeTVar#" GenPrimOp
+primop  WriteTVarOp "writeTVar#" GenPrimOp
        TVar# s a
     -> a
     -> State# s -> State# s
    {Write contents of {\tt TVar\#}.}
    with
-   out_of_line     = True
+   out_of_line      = True
    has_side_effects = True
 
 primop  SameTVarOp "sameTVar#" GenPrimOp
@@ -1713,13 +2125,13 @@ primop  SameTVarOp "sameTVar#" GenPrimOp
 
 ------------------------------------------------------------------------
 section "Synchronized Mutable Variables"
-       {Operations on {\tt MVar\#}s. }
+        {Operations on {\tt MVar\#}s. }
 ------------------------------------------------------------------------
 
 primtype MVar# s a
-       { A shared mutable variable ({\it not} the same as a {\tt MutVar\#}!).
-       (Note: in a non-concurrent implementation, {\tt (MVar\# a)} can be
-       represented by {\tt (MutVar\# (Maybe a))}.) }
+        { A shared mutable variable ({\it not} the same as a {\tt MutVar\#}!).
+        (Note: in a non-concurrent implementation, {\tt (MVar\# a)} can be
+        represented by {\tt (MutVar\# (Maybe a))}.) }
 
 primop  NewMVarOp "newMVar#"  GenPrimOp
    State# s -> (# State# s, MVar# s a #)
@@ -1841,21 +2253,21 @@ section "Concurrency primitives"
 ------------------------------------------------------------------------
 
 primtype State# s
-       { {\tt State\#} is the primitive, unlifted type of states.  It has
-       one type parameter, thus {\tt State\# RealWorld}, or {\tt State\# s},
-       where s is a type variable. The only purpose of the type parameter
-       is to keep different state threads separate.  It is represented by
-       nothing at all. }
+        { {\tt State\#} is the primitive, unlifted type of states.  It has
+        one type parameter, thus {\tt State\# RealWorld}, or {\tt State\# s},
+        where s is a type variable. The only purpose of the type parameter
+        is to keep different state threads separate.  It is represented by
+        nothing at all. }
 
 primtype RealWorld
-       { {\tt RealWorld} is deeply magical.  It is {\it primitive}, but it is not
-       {\it unlifted} (hence {\tt ptrArg}).  We never manipulate values of type
-       {\tt RealWorld}; it's only used in the type system, to parameterise {\tt State\#}. }
+        { {\tt RealWorld} is deeply magical.  It is {\it primitive}, but it is not
+        {\it unlifted} (hence {\tt ptrArg}).  We never manipulate values of type
+        {\tt RealWorld}; it's only used in the type system, to parameterise {\tt State\#}. }
 
 primtype ThreadId#
-       {(In a non-concurrent implementation, this can be a singleton
-       type, whose (unique) value is returned by {\tt myThreadId\#}.  The 
-       other operations can be omitted.)}
+        {(In a non-concurrent implementation, this can be a singleton
+        type, whose (unique) value is returned by {\tt myThreadId\#}.  The
+        other operations can be omitted.)}
 
 primop  ForkOp "fork#" GenPrimOp
    a -> State# RealWorld -> (# State# RealWorld, ThreadId# #)
@@ -1892,7 +2304,7 @@ primop LabelThreadOp "labelThread#" GenPrimOp
    with
    has_side_effects = True
    out_of_line      = True
-   
+
 primop  IsCurrentThreadBoundOp "isCurrentThreadBound#" GenPrimOp
    State# RealWorld -> (# State# RealWorld, Int# #)
    with
@@ -1920,7 +2332,8 @@ primtype Weak# b
 -- note that tyvar "o" denotes openAlphaTyVar
 
 primop  MkWeakOp "mkWeak#" GenPrimOp
-   o -> b -> c -> State# RealWorld -> (# State# RealWorld, Weak# b #)
+   o -> b -> (State# RealWorld -> (# State# RealWorld, c #))
+     -> State# RealWorld -> (# State# RealWorld, Weak# b #)
    with
    has_side_effects = True
    out_of_line      = True
@@ -1951,8 +2364,13 @@ primop  DeRefWeakOp "deRefWeak#" GenPrimOp
    out_of_line      = True
 
 primop  FinalizeWeakOp "finalizeWeak#" GenPrimOp
-   Weak# a -> State# RealWorld -> (# State# RealWorld, Int#, 
-              (State# RealWorld -> (# State# RealWorld, () #)) #)
+   Weak# a -> State# RealWorld -> (# State# RealWorld, Int#,
+              (State# RealWorld -> (# State# RealWorld, b #) ) #)
+   { Finalize a weak pointer. The return value is an unboxed tuple
+     containing the new state of the world and an "unboxed Maybe",
+     represented by an {\tt Int#} and a (possibly invalid) finalization
+     action. An {\tt Int#} of {\tt 1} indicates that the finalizer is valid. The
+     return value {\tt b} from the finalizer should be ignored. }
    with
    has_side_effects = True
    out_of_line      = True
@@ -2002,7 +2420,7 @@ primop  StableNameToIntOp "stableNameToInt#" GenPrimOp
 
 ------------------------------------------------------------------------
 section "Unsafe pointer equality"
---  (#1 Bad Guy: Alistair Reid :)   
+--  (#1 Bad Guy: Alistair Reid :)
 ------------------------------------------------------------------------
 
 primop  ReallyUnsafePtrEqualityOp "reallyUnsafePtrEquality#" GenPrimOp
@@ -2048,92 +2466,53 @@ primop NumSparks "numSparks#" GenPrimOp
    has_side_effects = True
    out_of_line = True
 
--- HWL: The first 4 Int# in all par... annotations denote:
---   name, granularity info, size of result, degree of parallelism
---      Same  structure as _seq_ i.e. returns Int#
--- KSW: v, the second arg in parAt# and parAtForNow#, is used only to determine
---   `the processor containing the expression v'; it is not evaluated
-
-primop  ParGlobalOp  "parGlobal#"  GenPrimOp
-   a -> Int# -> Int# -> Int# -> Int# -> b -> Int#
-   with
-   has_side_effects = True
-
-primop  ParLocalOp  "parLocal#"  GenPrimOp
-   a -> Int# -> Int# -> Int# -> Int# -> b -> Int#
-   with
-   has_side_effects = True
-
-primop  ParAtOp  "parAt#"  GenPrimOp
-   b -> a -> Int# -> Int# -> Int# -> Int# -> c -> Int#
-   with
-   has_side_effects = True
-
-primop  ParAtAbsOp  "parAtAbs#"  GenPrimOp
-   a -> Int# -> Int# -> Int# -> Int# -> Int# -> b -> Int#
-   with
-   has_side_effects = True
-
-primop  ParAtRelOp  "parAtRel#" GenPrimOp
-   a -> Int# -> Int# -> Int# -> Int# -> Int# -> b -> Int#
-   with
-   has_side_effects = True
-
-primop  ParAtForNowOp  "parAtForNow#" GenPrimOp
-   b -> a -> Int# -> Int# -> Int# -> Int# -> c -> Int#
-   with
-   has_side_effects = True
-
--- copyable# and noFollow# are yet to be implemented (for GpH)
---
---primop  CopyableOp  "copyable#" GenPrimOp
---   a -> Int#
---   with
---   has_side_effects = True
---
---primop  NoFollowOp "noFollow#" GenPrimOp
---   a -> Int#
---   with
---   has_side_effects = True
-
-
 ------------------------------------------------------------------------
 section "Tag to enum stuff"
-       {Convert back and forth between values of enumerated types
-       and small integers.}
+        {Convert back and forth between values of enumerated types
+        and small integers.}
 ------------------------------------------------------------------------
 
 primop  DataToTagOp "dataToTag#" GenPrimOp
    a -> Int#
    with
-   strictness  = { \ _arity -> mkStrictSig (mkTopDmdType [evalDmd] topRes) }
+   strictness  = { \ _arity -> mkClosedStrictSig [evalDmd] topRes }
 
-       -- dataToTag# must have an evaluated argument
+        -- dataToTag# must have an evaluated argument
 
-primop  TagToEnumOp "tagToEnum#" GenPrimOp     
+primop  TagToEnumOp "tagToEnum#" GenPrimOp
    Int# -> a
 
 ------------------------------------------------------------------------
-section "Bytecode operations" 
-       {Support for the bytecode interpreter and linker.}
+section "Bytecode operations"
+        {Support for manipulating bytecode objects used by the interpreter and
+        linker.
+
+        Bytecode objects are heap objects which represent top-level bindings and
+        contain a list of instructions and data needed by these instructions.}
 ------------------------------------------------------------------------
 
 primtype BCO#
-   {Primitive bytecode type.}
+   { Primitive bytecode type. }
 
 primop   AddrToAnyOp "addrToAny#" GenPrimOp
    Addr# -> (# a #)
-   {Convert an {\tt Addr\#} to a followable Any type.}
+   { Convert an {\tt Addr\#} to a followable Any type. }
    with
    code_size = 0
 
 primop   MkApUpd0_Op "mkApUpd0#" GenPrimOp
    BCO# -> (# a #)
+   { Wrap a BCO in a {\tt AP_UPD} thunk which will be updated with the value of
+     the BCO when evaluated. }
    with
    out_of_line = True
 
 primop  NewBCOOp "newBCO#" GenPrimOp
    ByteArray# -> ByteArray# -> Array# a -> Int# -> ByteArray# -> State# s -> (# State# s, BCO# #)
+   { {\tt newBCO\# instrs lits ptrs arity bitmap} creates a new bytecode object. The
+     resulting object encodes a function of the given arity with the instructions
+     encoded in {\tt instrs}, and a static reference table usage bitmap given by
+     {\tt bitmap}. }
    with
    has_side_effects = True
    out_of_line      = True
@@ -2165,42 +2544,66 @@ primop  GetCurrentCCSOp "getCurrentCCS#" GenPrimOp
      ("CAF"). }
 
 ------------------------------------------------------------------------
-section "Etc" 
-       {Miscellaneous built-ins}
+section "Etc"
+        {Miscellaneous built-ins}
 ------------------------------------------------------------------------
 
+primtype Proxy# a
+   { The type constructor {\tt Proxy#} is used to bear witness to some
+   type variable. It's used when you want to pass around proxy values
+   for doing things like modelling type applications. A {\tt Proxy#}
+   is not only unboxed, it also has a polymorphic kind, and has no
+   runtime representation, being totally free. }
+
+pseudoop "proxy#"
+   Proxy# a
+   { Witness for an unboxed {\tt Proxy#} value, which has no runtime
+   representation. }
+
 pseudoop   "seq"
    a -> b -> b
-   { Evaluates its first argument to head normal form, and then returns its second
-       argument as the result. }
+   { The value of {\tt seq a b} is bottom if {\tt a} is bottom, and
+     otherwise equal to {\tt b}. {\tt seq} is usually introduced to
+     improve performance by avoiding unneeded laziness.
 
-primtype Any k
-       { The type constructor {\tt Any} is type to which you can unsafely coerce any
-       lifted type, and back. 
+     A note on evaluation order: the expression {\tt seq a b} does
+     {\it not} guarantee that {\tt a} will be evaluated before {\tt b}.
+     The only guarantee given by {\tt seq} is that the both {\tt a}
+     and {\tt b} will be evaluated before {\tt seq} returns a value.
+     In particular, this means that {\tt b} may be evaluated before
+     {\tt a}. If you need to guarantee a specific order of evaluation,
+     you must use the function {\tt pseq} from the "parallel" package. }
 
-         * It is lifted, and hence represented by a pointer
+primtype Any
+        { The type constructor {\tt Any} is type to which you can unsafely coerce any
+        lifted type, and back.
 
-         * It does not claim to be a {\it data} type, and that's important for
-           the code generator, because the code gen may {\it enter} a data value
-           but never enters a function value.  
+          * It is lifted, and hence represented by a pointer
 
-       It's also used to instantiate un-constrained type variables after type
-       checking.  For example, {\tt length} has type
+          * It does not claim to be a {\it data} type, and that's important for
+            the code generator, because the code gen may {\it enter} a data value
+            but never enters a function value.
 
-       {\tt length :: forall a. [a] -> Int}
+        It's also used to instantiate un-constrained type variables after type
+        checking.  For example, {\tt length} has type
 
-       and the list datacon for the empty list has type
+        {\tt length :: forall a. [a] -> Int}
 
-       {\tt [] :: forall a. [a]}
+        and the list datacon for the empty list has type
 
-       In order to compose these two terms as {\tt length []} a type
-       application is required, but there is no constraint on the
-       choice.  In this situation GHC uses {\tt Any}:
+        {\tt [] :: forall a. [a]}
 
-       {\tt length (Any *) ([] (Any *))}
+        In order to compose these two terms as {\tt length []} a type
+        application is required, but there is no constraint on the
+        choice.  In this situation GHC uses {\tt Any}:
 
-        Note that {\tt Any} is kind polymorphic, and takes a kind {\tt k} as its
-        first argument. The kind of {\tt Any} is thus {\tt forall k. k -> k}.}
+        {\tt length (Any *) ([] (Any *))}
+
+        Above, we print kinds explicitly, as if with
+        {\tt -fprint-explicit-kinds}.
+
+        Note that {\tt Any} is kind polymorphic; its kind is thus
+        {\tt forall k. k}.}
 
 primtype AnyK
         { The kind {\tt AnyK} is the kind level counterpart to {\tt Any}. In a
@@ -2220,10 +2623,10 @@ primtype AnyK
 pseudoop   "unsafeCoerce#"
    a -> b
    { The function {\tt unsafeCoerce\#} allows you to side-step the typechecker entirely. That
-       is, it allows you to coerce any type into any other type. If you use this function,
-       you had better get it right, otherwise segmentation faults await. It is generally
-       used when you want to write a program that you know is well-typed, but where Haskell's
-       type system is not expressive enough to prove that it is well typed.
+        is, it allows you to coerce any type into any other type. If you use this function,
+        you had better get it right, otherwise segmentation faults await. It is generally
+        used when you want to write a program that you know is well-typed, but where Haskell's
+        type system is not expressive enough to prove that it is well typed.
 
         The following uses of {\tt unsafeCoerce\#} are supposed to work (i.e. not lead to
         spurious compile-time or run-time crashes):
@@ -2237,18 +2640,18 @@ pseudoop   "unsafeCoerce#"
 
          * Casting between two types that have the same runtime representation.  One case is when
            the two types differ only in "phantom" type parameters, for example
-           {\tt Ptr Int} to {\tt Ptr Float}, or {\tt [Int]} to {\tt [Float]} when the list is 
+           {\tt Ptr Int} to {\tt Ptr Float}, or {\tt [Int]} to {\tt [Float]} when the list is
            known to be empty.  Also, a {\tt newtype} of a type {\tt T} has the same representation
            at runtime as {\tt T}.
 
         Other uses of {\tt unsafeCoerce\#} are undefined.  In particular, you should not use
-       {\tt unsafeCoerce\#} to cast a T to an algebraic data type D, unless T is also
-       an algebraic data type.  For example, do not cast {\tt Int->Int} to {\tt Bool}, even if
+        {\tt unsafeCoerce\#} to cast a T to an algebraic data type D, unless T is also
+        an algebraic data type.  For example, do not cast {\tt Int->Int} to {\tt Bool}, even if
         you later cast that {\tt Bool} back to {\tt Int->Int} before applying it.  The reasons
         have to do with GHC's internal representation details (for the congnoscenti, data values
-       can be entered but function closures cannot).  If you want a safe type to cast things
-       to, use {\tt Any}, which is not an algebraic data type.
-       
+        can be entered but function closures cannot).  If you want a safe type to cast things
+        to, use {\tt Any}, which is not an algebraic data type.
+
         }
 
 -- NB. It is tempting to think that casting a value to a type that it doesn't have is safe
@@ -2279,499 +2682,356 @@ primop  TraceMarkerOp "traceMarker#" GenPrimOp
    has_side_effects = True
    out_of_line      = True
 
-
 ------------------------------------------------------------------------
-section "Float SIMD Vectors" 
-       {Operations on SIMD vectors of 4 single-precision (32-bit)
-         floating-point numbers.}
+section "Safe coercions"
 ------------------------------------------------------------------------
 
-primtype FloatX4#
+pseudoop   "coerce"
+   Coercible a b => a -> b
+   { The function {\tt coerce} allows you to safely convert between values of
+     types that have the same representation with no run-time overhead. In the
+     simplest case you can use it instead of a newtype constructor, to go from
+     the newtype's concrete type to the abstract type. But it also works in
+     more complicated settings, e.g. converting a list of newtypes to a list of
+     concrete types.
+   }
+
+------------------------------------------------------------------------
+section "SIMD Vectors"
+        {Operations on SIMD vectors.}
+------------------------------------------------------------------------
+
+#define ALL_VECTOR_TYPES \
+  [<Int8,Int#,16>,<Int16,Int#,8>,<Int32,INT32,4>,<Int64,INT64,2> \
+  ,<Int8,Int#,32>,<Int16,Int#,16>,<Int32,INT32,8>,<Int64,INT64,4> \
+  ,<Int8,Int#,64>,<Int16,Int#,32>,<Int32,INT32,16>,<Int64,INT64,8> \
+  ,<Word8,Word#,16>,<Word16,Word#,8>,<Word32,WORD32,4>,<Word64,WORD64,2> \
+  ,<Word8,Word#,32>,<Word16,Word#,16>,<Word32,WORD32,8>,<Word64,WORD64,4> \
+  ,<Word8,Word#,64>,<Word16,Word#,32>,<Word32,WORD32,16>,<Word64,WORD64,8> \
+  ,<Float,Float#,4>,<Double,Double#,2> \
+  ,<Float,Float#,8>,<Double,Double#,4> \
+  ,<Float,Float#,16>,<Double,Double#,8>]
+
+#define SIGNED_VECTOR_TYPES \
+  [<Int8,Int#,16>,<Int16,Int#,8>,<Int32,INT32,4>,<Int64,INT64,2> \
+  ,<Int8,Int#,32>,<Int16,Int#,16>,<Int32,INT32,8>,<Int64,INT64,4> \
+  ,<Int8,Int#,64>,<Int16,Int#,32>,<Int32,INT32,16>,<Int64,INT64,8> \
+  ,<Float,Float#,4>,<Double,Double#,2> \
+  ,<Float,Float#,8>,<Double,Double#,4> \
+  ,<Float,Float#,16>,<Double,Double#,8>]
+
+#define FLOAT_VECTOR_TYPES \
+  [<Float,Float#,4>,<Double,Double#,2> \
+  ,<Float,Float#,8>,<Double,Double#,4> \
+  ,<Float,Float#,16>,<Double,Double#,8>]
+
+#define INT_VECTOR_TYPES \
+  [<Int8,Int#,16>,<Int16,Int#,8>,<Int32,INT32,4>,<Int64,INT64,2> \
+  ,<Int8,Int#,32>,<Int16,Int#,16>,<Int32,INT32,8>,<Int64,INT64,4> \
+  ,<Int8,Int#,64>,<Int16,Int#,32>,<Int32,INT32,16>,<Int64,INT64,8> \
+  ,<Word8,Word#,16>,<Word16,Word#,8>,<Word32,WORD32,4>,<Word64,WORD64,2> \
+  ,<Word8,Word#,32>,<Word16,Word#,16>,<Word32,WORD32,8>,<Word64,WORD64,4> \
+  ,<Word8,Word#,64>,<Word16,Word#,32>,<Word32,WORD32,16>,<Word64,WORD64,8>]
+
+primtype VECTOR
    with llvm_only = True
+        vector = ALL_VECTOR_TYPES
 
-primop FloatToFloatX4Op "floatToFloatX4#" GenPrimOp     
-   Float# -> FloatX4#
+primop VecBroadcastOp "broadcast#" GenPrimOp
+   SCALAR -> VECTOR
+   { Broadcast a scalar to all elements of a vector. }
    with llvm_only = True
+        vector = ALL_VECTOR_TYPES
 
-primop FloatX4PackOp "packFloatX4#" GenPrimOp         
-   Float# -> Float# -> Float# -> Float# -> FloatX4#
+primop VecPackOp "pack#" GenPrimOp
+   VECTUPLE -> VECTOR
+   { Pack the elements of an unboxed tuple into a vector. }
    with llvm_only = True
+        vector = ALL_VECTOR_TYPES
 
-primop FloatX4UnpackOp "unpackFloatX4#" GenPrimOp         
-   FloatX4# -> (# Float#, Float#, Float#, Float# #)
+primop VecUnpackOp "unpack#" GenPrimOp
+   VECTOR -> VECTUPLE
+   { Unpack the elements of a vector into an unboxed tuple. #}
    with llvm_only = True
+        vector = ALL_VECTOR_TYPES
 
-primop FloatX4InsertOp "insertFloatX4#" GenPrimOp     
-   FloatX4# -> Float# -> Int# -> FloatX4#
+primop VecInsertOp "insert#" GenPrimOp
+   VECTOR -> SCALAR -> Int# -> VECTOR
+   { Insert a scalar at the given position in a vector. }
    with can_fail = True
         llvm_only = True
+        vector = ALL_VECTOR_TYPES
 
-primop FloatX4AddOp "plusFloatX4#" Dyadic            
-   FloatX4# -> FloatX4# -> FloatX4#
+primop VecAddOp "plus#" Dyadic
+   VECTOR -> VECTOR -> VECTOR
+   { Add two vectors element-wise. }
    with commutable = True
         llvm_only = True
+        vector = ALL_VECTOR_TYPES
 
-primop FloatX4SubOp "minusFloatX4#" Dyadic
-  FloatX4# -> FloatX4# -> FloatX4#
+primop VecSubOp "minus#" Dyadic
+   VECTOR -> VECTOR -> VECTOR
+   { Subtract two vectors element-wise. }
    with llvm_only = True
+        vector = ALL_VECTOR_TYPES
 
-primop FloatX4MulOp "timesFloatX4#" Dyadic    
-   FloatX4# -> FloatX4# -> FloatX4#
+primop VecMulOp "times#" Dyadic
+   VECTOR -> VECTOR -> VECTOR
+   { Multiply two vectors element-wise. }
    with commutable = True
         llvm_only = True
+        vector = ALL_VECTOR_TYPES
 
-primop FloatX4DivOp "divideFloatX4#" Dyadic  
-   FloatX4# -> FloatX4# -> FloatX4#
+primop VecDivOp "divide#" Dyadic
+   VECTOR -> VECTOR -> VECTOR
+   { Divide two vectors element-wise. }
    with can_fail = True
         llvm_only = True
+        vector = FLOAT_VECTOR_TYPES
 
-primop FloatX4NegOp "negateFloatX4#" Monadic
-   FloatX4# -> FloatX4#
-   with llvm_only = True
-
-primop IndexByteArrayOp_FloatX4 "indexFloatX4Array#" GenPrimOp
-   ByteArray# -> Int# -> FloatX4#
+primop VecQuotOp "quot#" Dyadic
+   VECTOR -> VECTOR -> VECTOR
+   { Rounds towards zero element-wise. }
    with can_fail = True
         llvm_only = True
+        vector = INT_VECTOR_TYPES
 
-primop ReadByteArrayOp_FloatX4 "readFloatX4Array#" GenPrimOp
-   MutableByteArray# s -> Int# -> State# s -> (# State# s, FloatX4# #)
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
-
-primop WriteByteArrayOp_FloatX4 "writeFloatX4Array#" GenPrimOp
-   MutableByteArray# s -> Int# -> FloatX4# -> State# s -> State# s
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
-
-primop IndexOffAddrOp_FloatX4 "indexFloatX4OffAddr#" GenPrimOp
-   Addr# -> Int# -> FloatX4#
+primop VecRemOp "rem#" Dyadic
+   VECTOR -> VECTOR -> VECTOR
+   { Satisfies \texttt{(quot\# x y) times\# y plus\# (rem\# x y) == x}. }
    with can_fail = True
         llvm_only = True
+        vector = INT_VECTOR_TYPES
 
-primop ReadOffAddrOp_FloatX4 "readFloatX4OffAddr#" GenPrimOp
-   Addr# -> Int# -> State# s -> (# State# s, FloatX4# #)
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
-
-primop  WriteOffAddrOp_FloatX4 "writeFloatX4OffAddr#" GenPrimOp
-   Addr# -> Int# -> FloatX4# -> State# s -> State# s
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
-
-primop IndexByteArrayOp_FloatAsFloatX4 "indexFloatArrayAsFloatX4#" GenPrimOp
-   ByteArray# -> Int# -> FloatX4#
-   with can_fail = True
-        llvm_only = True
-
-primop ReadByteArrayOp_FloatAsFloatX4 "readFloatArrayAsFloatX4#" GenPrimOp
-   MutableByteArray# s -> Int# -> State# s -> (# State# s, FloatX4# #)
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
-
-primop WriteByteArrayOp_FloatAsFloatX4 "writeFloatArrayAsFloatX4#" GenPrimOp
-   MutableByteArray# s -> Int# -> FloatX4# -> State# s -> State# s
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
-
-primop IndexOffAddrOp_FloatAsFloatX4 "indexFloatOffAddrAsFloatX4#" GenPrimOp
-   Addr# -> Int# -> FloatX4#
-   with can_fail = True
-        llvm_only = True
-
-primop ReadOffAddrOp_FloatAsFloatX4 "readFloatOffAddrAsFloatX4#" GenPrimOp
-   Addr# -> Int# -> State# s -> (# State# s, FloatX4# #)
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
-
-primop  WriteOffAddrOp_FloatAsFloatX4 "writeFloatOffAddrAsFloatX4#" GenPrimOp
-   Addr# -> Int# -> FloatX4# -> State# s -> State# s
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
-
-------------------------------------------------------------------------
-section "Double SIMD Vectors" 
-       {Operations on SIMD vectors of 2 double-precision (64-bit)
-         floating-point numbers.}
-------------------------------------------------------------------------
-
-primtype DoubleX2#
-   with llvm_only = True
-
-primop DoubleToDoubleX2Op "doubleToDoubleX2#" GenPrimOp     
-   Double# -> DoubleX2#
-   with llvm_only = True
-
-primop DoubleX2InsertOp "insertDoubleX2#" GenPrimOp     
-   DoubleX2# -> Double# -> Int# -> DoubleX2#
-   with can_fail = True
-        llvm_only = True
-
-primop DoubleX2PackOp "packDoubleX2#" GenPrimOp         
-   Double# -> Double# -> DoubleX2#
-   with llvm_only = True
-
-primop DoubleX2UnpackOp "unpackDoubleX2#" GenPrimOp         
-   DoubleX2# -> (# Double#, Double# #)
-   with llvm_only = True
-
-primop DoubleX2AddOp "plusDoubleX2#" Dyadic            
-   DoubleX2# -> DoubleX2# -> DoubleX2#
-   with commutable = True
-        llvm_only = True
-
-primop DoubleX2SubOp "minusDoubleX2#" Dyadic
-  DoubleX2# -> DoubleX2# -> DoubleX2#
-   with llvm_only = True
-
-primop DoubleX2MulOp "timesDoubleX2#" Dyadic    
-   DoubleX2# -> DoubleX2# -> DoubleX2#
-   with commutable = True
-        llvm_only = True
-
-primop DoubleX2DivOp "divideDoubleX2#" Dyadic  
-   DoubleX2# -> DoubleX2# -> DoubleX2#
-   with can_fail = True
-        llvm_only = True
-
-primop DoubleX2NegOp "negateDoubleX2#" Monadic
-   DoubleX2# -> DoubleX2#
+primop VecNegOp "negate#" Monadic
+   VECTOR -> VECTOR
+   { Negate element-wise. }
    with llvm_only = True
+        vector = SIGNED_VECTOR_TYPES
 
-primop IndexByteArrayOp_DoubleX2 "indexDoubleX2Array#" GenPrimOp
-   ByteArray# -> Int# -> DoubleX2#
+primop VecIndexByteArrayOp "indexArray#" GenPrimOp
+   ByteArray# -> Int# -> VECTOR
+   { Read a vector from specified index of immutable array. }
    with can_fail = True
         llvm_only = True
+        vector = ALL_VECTOR_TYPES
 
-primop ReadByteArrayOp_DoubleX2 "readDoubleX2Array#" GenPrimOp
-   MutableByteArray# s -> Int# -> State# s -> (# State# s, DoubleX2# #)
+primop VecReadByteArrayOp "readArray#" GenPrimOp
+   MutableByteArray# s -> Int# -> State# s -> (# State# s, VECTOR #)
+   { Read a vector from specified index of mutable array. }
    with has_side_effects = True
         can_fail = True
         llvm_only = True
+        vector = ALL_VECTOR_TYPES
 
-primop WriteByteArrayOp_DoubleX2 "writeDoubleX2Array#" GenPrimOp
-   MutableByteArray# s -> Int# -> DoubleX2# -> State# s -> State# s
+primop VecWriteByteArrayOp "writeArray#" GenPrimOp
+   MutableByteArray# s -> Int# -> VECTOR -> State# s -> State# s
+   { Write a vector to specified index of mutable array. }
    with has_side_effects = True
         can_fail = True
         llvm_only = True
+        vector = ALL_VECTOR_TYPES
 
-primop IndexOffAddrOp_DoubleX2 "indexDoubleX2OffAddr#" GenPrimOp
-   Addr# -> Int# -> DoubleX2#
+primop VecIndexOffAddrOp "indexOffAddr#" GenPrimOp
+   Addr# -> Int# -> VECTOR
+   { Reads vector; offset in bytes. }
    with can_fail = True
         llvm_only = True
+        vector = ALL_VECTOR_TYPES
 
-primop ReadOffAddrOp_DoubleX2 "readDoubleX2OffAddr#" GenPrimOp
-   Addr# -> Int# -> State# s -> (# State# s, DoubleX2# #)
+primop VecReadOffAddrOp "readOffAddr#" GenPrimOp
+   Addr# -> Int# -> State# s -> (# State# s, VECTOR #)
+   { Reads vector; offset in bytes. }
    with has_side_effects = True
         can_fail = True
         llvm_only = True
+        vector = ALL_VECTOR_TYPES
 
-primop  WriteOffAddrOp_DoubleX2 "writeDoubleX2OffAddr#" GenPrimOp
-   Addr# -> Int# -> DoubleX2# -> State# s -> State# s
+primop VecWriteOffAddrOp "writeOffAddr#" GenPrimOp
+   Addr# -> Int# -> VECTOR -> State# s -> State# s
+   { Write vector; offset in bytes. }
    with has_side_effects = True
         can_fail = True
         llvm_only = True
+        vector = ALL_VECTOR_TYPES
+
 
-primop IndexByteArrayOp_DoubleAsDoubleX2 "indexDoubleArrayAsDoubleX2#" GenPrimOp
-   ByteArray# -> Int# -> DoubleX2#
+primop VecIndexScalarByteArrayOp "indexArrayAs#" GenPrimOp
+   ByteArray# -> Int# -> VECTOR
+   { Read a vector from specified index of immutable array of scalars; offset is in scalar elements. }
    with can_fail = True
         llvm_only = True
+        vector = ALL_VECTOR_TYPES
 
-primop ReadByteArrayOp_DoubleAsDoubleX2 "readDoubleArrayAsDoubleX2#" GenPrimOp
-   MutableByteArray# s -> Int# -> State# s -> (# State# s, DoubleX2# #)
+primop VecReadScalarByteArrayOp "readArrayAs#" GenPrimOp
+   MutableByteArray# s -> Int# -> State# s -> (# State# s, VECTOR #)
+   { Read a vector from specified index of mutable array of scalars; offset is in scalar elements. }
    with has_side_effects = True
         can_fail = True
         llvm_only = True
+        vector = ALL_VECTOR_TYPES
 
-primop WriteByteArrayOp_DoubleAsDoubleX2 "writeDoubleArrayAsDoubleX2#" GenPrimOp
-   MutableByteArray# s -> Int# -> DoubleX2# -> State# s -> State# s
+primop VecWriteScalarByteArrayOp "writeArrayAs#" GenPrimOp
+   MutableByteArray# s -> Int# -> VECTOR -> State# s -> State# s
+   { Write a vector to specified index of mutable array of scalars; offset is in scalar elements. }
    with has_side_effects = True
         can_fail = True
         llvm_only = True
+        vector = ALL_VECTOR_TYPES
 
-primop IndexOffAddrOp_DoubleAsDoubleX2 "indexDoubleOffAddrAsDoubleX2#" GenPrimOp
-   Addr# -> Int# -> DoubleX2#
+primop VecIndexScalarOffAddrOp "indexOffAddrAs#" GenPrimOp
+   Addr# -> Int# -> VECTOR
+   { Reads vector; offset in scalar elements. }
    with can_fail = True
         llvm_only = True
+        vector = ALL_VECTOR_TYPES
 
-primop ReadOffAddrOp_DoubleAsDoubleX2 "readDoubleOffAddrAsDoubleX2#" GenPrimOp
-   Addr# -> Int# -> State# s -> (# State# s, DoubleX2# #)
+primop VecReadScalarOffAddrOp "readOffAddrAs#" GenPrimOp
+   Addr# -> Int# -> State# s -> (# State# s, VECTOR #)
+   { Reads vector; offset in scalar elements. }
    with has_side_effects = True
         can_fail = True
         llvm_only = True
+        vector = ALL_VECTOR_TYPES
 
-primop  WriteOffAddrOp_DoubleAsDoubleX2 "writeDoubleOffAddrAsDoubleX2#" GenPrimOp
-   Addr# -> Int# -> DoubleX2# -> State# s -> State# s
+primop VecWriteScalarOffAddrOp "writeOffAddrAs#" GenPrimOp
+   Addr# -> Int# -> VECTOR -> State# s -> State# s
+   { Write vector; offset in scalar elements. }
    with has_side_effects = True
         can_fail = True
         llvm_only = True
+        vector = ALL_VECTOR_TYPES
 
 ------------------------------------------------------------------------
-section "Int32 SIMD Vectors" 
-       {Operations on SIMD vectors of 4 32-bit signed integers.}
-------------------------------------------------------------------------
 
-primtype Int32X4#
-   with llvm_only = True
+section "Prefetch"
+        {Prefetch operations: Note how every prefetch operation has a name
+  with the pattern prefetch*N#, where N is either 0,1,2, or 3.
 
-primop Int32ToInt32X4Op "int32ToInt32X4#" GenPrimOp     
-   INT32 -> Int32X4#
-   with llvm_only = True
+  This suffix number, N, is the "locality level" of the prefetch, following the
+  convention in GCC and other compilers.
+  Higher locality numbers correspond to the memory being loaded in more
+  levels of the cpu cache, and being retained after initial use. The naming
+  convention follows the naming convention of the prefetch intrinsic found
+  in the GCC and Clang C compilers.
 
-primop Int32X4InsertOp "insertInt32X4#" GenPrimOp     
-   Int32X4# -> INT32 -> Int# -> Int32X4#
-   with can_fail = True
-        llvm_only = True
+  On the LLVM backend, prefetch*N# uses the LLVM prefetch intrinsic
+  with locality level N. The code generated by LLVM is target architecture
+  dependent, but should agree with the GHC NCG on x86 systems.
 
-primop Int32X4PackOp "packInt32X4#" GenPrimOp         
-   INT32 -> INT32 -> INT32 -> INT32 -> Int32X4#
-   with llvm_only = True
+  On the Sparc and PPC native backends, prefetch*N is a No-Op.
 
-primop Int32X4UnpackOp "unpackInt32X4#" GenPrimOp         
-   Int32X4# -> (# INT32, INT32, INT32, INT32 #)
-   with llvm_only = True
+  On the x86 NCG, N=0 will generate prefetchNTA,
+  N=1 generates prefetcht2, N=2 generates prefetcht1, and
+  N=3 generates prefetcht0.
 
-primop Int32X4AddOp "plusInt32X4#" Dyadic            
-   Int32X4# -> Int32X4# -> Int32X4#
-   with commutable = True
-        llvm_only = True
+  For streaming workloads, the prefetch*0 operations are recommended.
+  For workloads which do many reads or writes to a memory location in a short period of time,
+  prefetch*3 operations are recommended.
 
-primop Int32X4SubOp "minusInt32X4#" Dyadic
-  Int32X4# -> Int32X4# -> Int32X4#
-   with llvm_only = True
+  For further reading about prefetch and associated systems performance optimization,
+  the instruction set and optimization manuals by Intel and other CPU vendors are
+  excellent starting place.
 
-primop Int32X4MulOp "timesInt32X4#" Dyadic    
-   Int32X4# -> Int32X4# -> Int32X4#
-   with commutable = True
-        llvm_only = True
 
-primop Int32X4QuotOp "quotInt32X4#" Dyadic  
-   Int32X4# -> Int32X4# -> Int32X4#
-   with can_fail = True
-        llvm_only = True
-   
-primop Int32X4RemOp "remInt32X4#" Dyadic  
-   Int32X4# -> Int32X4# -> Int32X4#
-   with can_fail = True
-        llvm_only = True
+  The "Intel 64 and IA-32 Architectures Optimization Reference Manual" is
+  especially a helpful read, even if your software is meant for other CPU
+  architectures or vendor hardware. The manual can be found at
+  http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-optimization-manual.html .
 
-primop Int32X4NegOp "negateInt32X4#" Monadic
-   Int32X4# -> Int32X4#
-   with llvm_only = True
+  The {\tt prefetch*} family of operations has the order of operations
+  determined by passing around the {\tt State#} token.
 
-primop IndexByteArrayOp_Int32X4 "indexInt32X4Array#" GenPrimOp
-   ByteArray# -> Int# -> Int32X4#
-   with can_fail = True
-        llvm_only = True
+  To get a "pure" version of these operations, use {\tt inlinePerformIO} which is quite safe in this context.
 
-primop ReadByteArrayOp_Int32X4 "readInt32X4Array#" GenPrimOp
-   MutableByteArray# s -> Int# -> State# s -> (# State# s, Int32X4# #)
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
+  It is important to note that while the prefetch operations will never change the
+  answer to a pure computation, They CAN change the memory locations resident
+  in a CPU cache and that may change the performance and timing characteristics
+  of an application. The prefetch operations are marked has_side_effects=True
+  to reflect that these operations have side effects with respect to the runtime
+  performance characteristics of the resulting code. Additionally, if the prefetchValue
+  operations did not have this attribute, GHC does a float out transformation that
+  results in a let/app violation, at least with the current design.
+  }
 
-primop WriteByteArrayOp_Int32X4 "writeInt32X4Array#" GenPrimOp
-   MutableByteArray# s -> Int# -> Int32X4# -> State# s -> State# s
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
-
-primop IndexOffAddrOp_Int32X4 "indexInt32X4OffAddr#" GenPrimOp
-   Addr# -> Int# -> Int32X4#
-   with can_fail = True
-        llvm_only = True
-
-primop ReadOffAddrOp_Int32X4 "readInt32X4OffAddr#" GenPrimOp
-   Addr# -> Int# -> State# s -> (# State# s, Int32X4# #)
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
-
-primop  WriteOffAddrOp_Int32X4 "writeInt32X4OffAddr#" GenPrimOp
-   Addr# -> Int# -> Int32X4# -> State# s -> State# s
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
-
-primop IndexByteArrayOp_Int32AsInt32X4 "indexInt32ArrayAsInt32X4#" GenPrimOp
-   ByteArray# -> Int# -> Int32X4#
-   with can_fail = True
-        llvm_only = True
-
-primop ReadByteArrayOp_Int32AsInt32X4 "readInt32ArrayAsInt32X4#" GenPrimOp
-   MutableByteArray# s -> Int# -> State# s -> (# State# s, Int32X4# #)
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
-
-primop WriteByteArrayOp_Int32AsInt32X4 "writeInt32ArrayAsInt32X4#" GenPrimOp
-   MutableByteArray# s -> Int# -> Int32X4# -> State# s -> State# s
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
-
-primop IndexOffAddrOp_Int32AsInt32X4 "indexInt32OffAddrAsInt32X4#" GenPrimOp
-   Addr# -> Int# -> Int32X4#
-   with can_fail = True
-        llvm_only = True
-
-primop ReadOffAddrOp_Int32AsInt32X4 "readInt32OffAddrAsInt32X4#" GenPrimOp
-   Addr# -> Int# -> State# s -> (# State# s, Int32X4# #)
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
 
-primop  WriteOffAddrOp_Int32AsInt32X4 "writeInt32OffAddrAsInt32X4#" GenPrimOp
-   Addr# -> Int# -> Int32X4# -> State# s -> State# s
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
 
 ------------------------------------------------------------------------
-section "Int64 SIMD Vectors" 
-       {Operations on SIMD vectors of 2 64-bit signed integers.}
-------------------------------------------------------------------------
-
-primtype Int64X2#
-   with llvm_only = True
-
-primop Int64ToInt64X2Op "int64ToInt64X2#" GenPrimOp     
-   INT64 -> Int64X2#
-   with llvm_only = True
-
-primop Int64X2InsertOp "insertInt64X2#" GenPrimOp     
-   Int64X2# -> INT64 -> Int# -> Int64X2#
-   with can_fail = True
-        llvm_only = True
-
-primop Int64X2PackOp "packInt64X2#" GenPrimOp         
-   INT64 -> INT64 -> Int64X2#
-   with llvm_only = True
-
-primop Int64X2UnpackOp "unpackInt64X2#" GenPrimOp         
-   Int64X2# -> (# INT64, INT64 #)
-   with llvm_only = True
-
-primop Int64X2AddOp "plusInt64X2#" Dyadic            
-   Int64X2# -> Int64X2# -> Int64X2#
-   with commutable = True
-        llvm_only = True
 
-primop Int64X2SubOp "minusInt64X2#" Dyadic
-  Int64X2# -> Int64X2# -> Int64X2#
-   with llvm_only = True
-
-primop Int64X2MulOp "timesInt64X2#" Dyadic    
-   Int64X2# -> Int64X2# -> Int64X2#
-   with commutable = True
-        llvm_only = True
 
-primop Int64X2QuotOp "quotInt64X2#" Dyadic  
-   Int64X2# -> Int64X2# -> Int64X2#
-   with can_fail = True
-        llvm_only = True
-   
-primop Int64X2RemOp "remInt64X2#" Dyadic  
-   Int64X2# -> Int64X2# -> Int64X2#
-   with can_fail = True
-        llvm_only = True
+--- the Int# argument for prefetch is the byte offset on the byteArray or  Addr#
 
-primop Int64X2NegOp "negateInt64X2#" Monadic
-   Int64X2# -> Int64X2#
-   with llvm_only = True
+---
+primop PrefetchByteArrayOp3 "prefetchByteArray3#" GenPrimOp
+  ByteArray# -> Int# ->  State# s -> State# s
+  with has_side_effects =  True
 
-primop IndexByteArrayOp_Int64X2 "indexInt64X2Array#" GenPrimOp
-   ByteArray# -> Int# -> Int64X2#
-   with can_fail = True
-        llvm_only = True
+primop PrefetchMutableByteArrayOp3 "prefetchMutableByteArray3#" GenPrimOp
+  MutableByteArray# s -> Int# -> State# s -> State# s
+  with has_side_effects =  True
 
-primop ReadByteArrayOp_Int64X2 "readInt64X2Array#" GenPrimOp
-   MutableByteArray# s -> Int# -> State# s -> (# State# s, Int64X2# #)
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
+primop PrefetchAddrOp3 "prefetchAddr3#" GenPrimOp
+  Addr# -> Int# -> State# s -> State# s
+  with has_side_effects =  True
 
-primop WriteByteArrayOp_Int64X2 "writeInt64X2Array#" GenPrimOp
-   MutableByteArray# s -> Int# -> Int64X2# -> State# s -> State# s
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
+primop PrefetchValueOp3 "prefetchValue3#" GenPrimOp
+   a -> State# s -> State# s
+   with strictness  = { \ _arity -> mkClosedStrictSig [botDmd, topDmd] topRes }
+        has_side_effects =  True
+----
 
-primop IndexOffAddrOp_Int64X2 "indexInt64X2OffAddr#" GenPrimOp
-   Addr# -> Int# -> Int64X2#
-   with can_fail = True
-        llvm_only = True
+primop PrefetchByteArrayOp2 "prefetchByteArray2#" GenPrimOp
+  ByteArray# -> Int# ->  State# s -> State# s
+  with has_side_effects =  True
 
-primop ReadOffAddrOp_Int64X2 "readInt64X2OffAddr#" GenPrimOp
-   Addr# -> Int# -> State# s -> (# State# s, Int64X2# #)
-   with has_side_effects = True
-        llvm_only = True
+primop PrefetchMutableByteArrayOp2 "prefetchMutableByteArray2#" GenPrimOp
+  MutableByteArray# s -> Int# -> State# s -> State# s
+  with has_side_effects =  True
 
-primop  WriteOffAddrOp_Int64X2 "writeInt64X2OffAddr#" GenPrimOp
-   Addr# -> Int# -> Int64X2# -> State# s -> State# s
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
+primop PrefetchAddrOp2 "prefetchAddr2#" GenPrimOp
+  Addr# -> Int# ->  State# s -> State# s
+  with has_side_effects =  True
 
-primop IndexByteArrayOp_Int64AsInt64X2 "indexInt64ArrayAsInt64X2#" GenPrimOp
-   ByteArray# -> Int# -> Int64X2#
-   with can_fail = True
-        llvm_only = True
+primop PrefetchValueOp2 "prefetchValue2#" GenPrimOp
+   a ->  State# s -> State# s
+   with strictness  = { \ _arity -> mkClosedStrictSig [botDmd, topDmd] topRes }
+        has_side_effects =  True
+----
 
-primop ReadByteArrayOp_Int64AsInt64X2 "readInt64ArrayAsInt64X2#" GenPrimOp
-   MutableByteArray# s -> Int# -> State# s -> (# State# s, Int64X2# #)
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
+primop PrefetchByteArrayOp1 "prefetchByteArray1#" GenPrimOp
+   ByteArray# -> Int# -> State# s -> State# s
+   with has_side_effects =  True
 
-primop WriteByteArrayOp_Int64AsInt64X2 "writeInt64ArrayAsInt64X2#" GenPrimOp
-   MutableByteArray# s -> Int# -> Int64X2# -> State# s -> State# s
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
+primop PrefetchMutableByteArrayOp1 "prefetchMutableByteArray1#" GenPrimOp
+  MutableByteArray# s -> Int# -> State# s -> State# s
+  with has_side_effects =  True
 
-primop IndexOffAddrOp_Int64AsInt64X2 "indexInt64OffAddrAsInt64X2#" GenPrimOp
-   Addr# -> Int# -> Int64X2#
-   with can_fail = True
-        llvm_only = True
+primop PrefetchAddrOp1 "prefetchAddr1#" GenPrimOp
+  Addr# -> Int# -> State# s -> State# s
+  with has_side_effects =  True
 
-primop ReadOffAddrOp_Int64AsInt64X2 "readInt64OffAddrAsInt64X2#" GenPrimOp
-   Addr# -> Int# -> State# s -> (# State# s, Int64X2# #)
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
+primop PrefetchValueOp1 "prefetchValue1#" GenPrimOp
+   a -> State# s -> State# s
+   with strictness  = { \ _arity -> mkClosedStrictSig [botDmd, topDmd] topRes }
+        has_side_effects =  True
+----
 
-primop  WriteOffAddrOp_Int64AsInt64X2 "writeInt64OffAddrAsInt64X2#" GenPrimOp
-   Addr# -> Int# -> Int64X2# -> State# s -> State# s
-   with has_side_effects = True
-        can_fail = True
-        llvm_only = True
-   
-------------------------------------------------------------------------
-section "Prefetch" 
-       {Prefetch operations}
-------------------------------------------------------------------------
+primop PrefetchByteArrayOp0 "prefetchByteArray0#" GenPrimOp
+  ByteArray# -> Int# ->  State# s -> State# s
+  with has_side_effects =  True
 
-primop PrefetchByteArrayOp "prefetchByteArray#" GenPrimOp
-   ByteArray# -> Int# -> ByteArray#
-   with llvm_only = True
+primop PrefetchMutableByteArrayOp0 "prefetchMutableByteArray0#" GenPrimOp
+  MutableByteArray# s -> Int# -> State# s -> State# s
+  with has_side_effects =  True
 
-primop PrefetchMutableByteArrayOp "prefetchMutableByteArray#" GenPrimOp
-   MutableByteArray# s -> Int# -> State# s -> State# s
-   with has_side_effects = True
-        llvm_only = True
+primop PrefetchAddrOp0 "prefetchAddr0#" GenPrimOp
+  Addr# -> Int# -> State# s -> State# s
+  with has_side_effects =  True
 
-primop PrefetchAddrOp "prefetchAddr#" GenPrimOp
-   Addr# -> Int# -> Addr#
-   with llvm_only = True
+primop PrefetchValueOp0 "prefetchValue0#" GenPrimOp
+   a -> State# s -> State# s
+   with strictness  = { \ _arity -> mkClosedStrictSig [botDmd, topDmd] topRes }
+        has_side_effects =  True
 
 ------------------------------------------------------------------------
 ---                                                                  ---