packages feed

ghc-lib 9.4.3.20221104 → 9.4.4.20221225

raw patch · 27 files changed

+949/−322 lines, 27 filesdep ~ghc-lib-parserPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: ghc-lib-parser

API changes (from Hackage documentation)

+ GHC: Opt_SuppressCoercionTypes :: GeneralFlag
+ GHC: Opt_SuppressStgReps :: GeneralFlag
+ GHC.Builtin.PrimOps.Casts: getCasts :: PrimRep -> PrimRep -> [(PrimOp, Type)]
+ GHC.Cmm.Lexer: CmmT_Acquire :: CmmToken
+ GHC.Cmm.Lexer: CmmT_Relaxed :: CmmToken
+ GHC.Cmm.Lexer: CmmT_Release :: CmmToken
+ GHC.Cmm.Lexer: CmmT_SeqCst :: CmmToken
- GHC: funResultTy :: Type -> Type
+ GHC: funResultTy :: HasDebugCallStack => Type -> Type
- GHC.Plugins: funResultTy :: Type -> Type
+ GHC.Plugins: funResultTy :: HasDebugCallStack => Type -> Type
- GHC.StgToCmm.ExtCode: emitStore :: CmmExpr -> CmmExpr -> CmmParse ()
+ GHC.StgToCmm.ExtCode: emitStore :: Maybe MemoryOrdering -> CmmExpr -> CmmExpr -> CmmParse ()

Files

+ compiler/GHC/Builtin/PrimOps/Casts.hs view
@@ -0,0 +1,212 @@+{-+This module contains helpers to cast variables+between different Int/WordReps in StgLand.++-}++module GHC.Builtin.PrimOps.Casts+    ( getCasts )+where++import GHC.Prelude++import GHC.Core.TyCon+import GHC.Utils.Outputable+import GHC.Utils.Panic+import GHC.Utils.Panic.Plain+import GHC.Types.RepType+import GHC.Core.Type+import GHC.Builtin.Types.Prim++import GHC.Builtin.PrimOps+import GHC.Plugins (HasDebugCallStack)++{- Note [PrimRep based casting]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+This module contains a number of utility functions useful when+converting between variables of differing PrimReps.++The general pattern is:+* We have two primReps `from_rep` and `to_rep`.+* We want a list of PrimOps we can apply to a variable of rep `from_rep`.+Applying the list of primOps in order takes us to `to_rep` from `from_rep` giving+us a variable of the returned type at each step.++E.g. we call `getCasts from_rep to_rep` and get back [(op1#,ty1),(op2#,ty2)].+We can use this result to construct a function of type+`StgExpr -> StgExpr` by construction an expression++    case op1# <from> of (x' :: ty1) -> case op2# x' of x' -> <rhs_hole>++Ideally backends will compile the sequence of PrimOps to a no-op. E.g. by reusing+the same register but just relabeling it as another width.+However this is might not always be possible or the required optimizations+simply not implemented in the backend. This means currently many of these casts+will be cheap but not all of them will be completely zero-cost.++-}++-- | `getCasts from_rep to_rep` gives us a list of primops which when applied in order convert from_rep to to_rep.+-- See Note [PrimRep based casting]+getCasts :: PrimRep -> PrimRep -> [(PrimOp,Type)]+getCasts from_rep to_rep+  -- No-op+  | -- pprTrace "getCasts" (ppr (from_rep,to_rep)) $+    to_rep == from_rep+  = []++  -- Float <-> Double+  | to_rep == FloatRep =+    assertPpr (from_rep == DoubleRep) (ppr from_rep <+> ppr to_rep) $+    [(DoubleToFloatOp,floatPrimTy)]+  | to_rep == DoubleRep =+    assertPpr (from_rep == FloatRep) (ppr from_rep <+> ppr to_rep) $+    [(FloatToDoubleOp,doublePrimTy)]++  -- Addr <-> Word/Int+  | to_rep == AddrRep = wordOrIntToAddrRep from_rep+  | from_rep == AddrRep = addrToWordOrIntRep to_rep++  -- Int* -> Int*+  | primRepIsInt from_rep+  , primRepIsInt to_rep+  = sizedIntToSizedInt from_rep to_rep++  -- Word* -> Word*+  | primRepIsWord from_rep+  , primRepIsWord to_rep+  = sizedWordToSizedWord from_rep to_rep++  -- Word* -> Int*+  | primRepIsWord from_rep+  , primRepIsInt to_rep+  = let (op1,r1) = wordToIntRep from_rep+    in (op1,primRepToType r1):sizedIntToSizedInt r1 to_rep++  -- Int* -> Word*+  | primRepIsInt from_rep+  , primRepIsWord to_rep+  = let (op1,r1) = intToWordRep from_rep+    in (op1,primRepToType r1):sizedWordToSizedWord r1 to_rep++  | otherwise = pprPanic "getCasts:Unexpect rep combination"+                          (ppr (from_rep,to_rep))++wordOrIntToAddrRep :: HasDebugCallStack => PrimRep -> [(PrimOp,Type)]+wordOrIntToAddrRep AddrRep = [] -- No-op argument is already AddrRep+wordOrIntToAddrRep IntRep = [(IntToAddrOp, addrPrimTy)]+wordOrIntToAddrRep WordRep = [(WordToIntOp,intPrimTy), (IntToAddrOp,addrPrimTy)]+wordOrIntToAddrRep r+    | primRepIsInt r = (intToMachineInt r,intPrimTy):[(IntToAddrOp,addrPrimTy)]+    | primRepIsWord r =+        let (op1,r1) = wordToIntRep r+        in (op1, primRepToType r1):[(intToMachineInt r1,intPrimTy), (IntToAddrOp,addrPrimTy)]+    | otherwise = pprPanic "Rep not word or int rep" (ppr r)++addrToWordOrIntRep :: HasDebugCallStack => PrimRep -> [(PrimOp,Type)]+-- Machine sizes+addrToWordOrIntRep IntRep = [(AddrToIntOp, intPrimTy)]+addrToWordOrIntRep WordRep = [(AddrToIntOp,intPrimTy), (IntToWordOp,wordPrimTy)]+-- Explicitly sized reps+addrToWordOrIntRep r+    | primRepIsWord r = (AddrToIntOp,intPrimTy) : (IntToWordOp,wordPrimTy) : sizedWordToSizedWord WordRep r+    | primRepIsInt r = (AddrToIntOp,intPrimTy) : sizedIntToSizedInt IntRep r+    | otherwise = pprPanic "Target rep not word or int rep" (ppr r)+++-- WordX# -> IntX# (same size), argument is source rep+wordToIntRep :: HasDebugCallStack => PrimRep -> (PrimOp,PrimRep)+wordToIntRep rep+    = case rep of+        (WordRep) -> (WordToIntOp, IntRep)+        (Word8Rep) -> (Word8ToInt8Op, Int8Rep)+        (Word16Rep) -> (Word16ToInt16Op, Int16Rep)+        (Word32Rep) -> (Word32ToInt32Op, Int32Rep)+        (Word64Rep) -> (Word64ToInt64Op, Int64Rep)+        _ -> pprPanic "Rep not a wordRep" (ppr rep)++-- IntX# -> WordX#, argument is source rep+intToWordRep :: HasDebugCallStack => PrimRep -> (PrimOp,PrimRep)+intToWordRep rep+    = case rep of+        (IntRep) -> (IntToWordOp, WordRep)+        (Int8Rep) -> (Int8ToWord8Op, Word8Rep)+        (Int16Rep) -> (Int16ToWord16Op, Word16Rep)+        (Int32Rep) -> (Int32ToWord32Op, Word32Rep)+        (Int64Rep) -> (Int64ToWord64Op, Word64Rep)+        _ -> pprPanic "Rep not a wordRep" (ppr rep)++-- Casts between any size int to any other size of int+sizedIntToSizedInt :: HasDebugCallStack => PrimRep -> PrimRep -> [(PrimOp,Type)]+sizedIntToSizedInt r1 r2+    | r1 == r2 = []+-- Cast to Int#+sizedIntToSizedInt r IntRep = [(intToMachineInt r,intPrimTy)]+-- Cast from Int#+sizedIntToSizedInt IntRep r = [(intFromMachineInt r,primRepToType r)]+-- Sized to differently sized must go over machine word.+sizedIntToSizedInt r1 r2 = (intToMachineInt r1,intPrimTy) : [(intFromMachineInt r2,primRepToType r2)]++-- Casts between any size Word to any other size of Word+sizedWordToSizedWord :: HasDebugCallStack => PrimRep -> PrimRep -> [(PrimOp,Type)]+sizedWordToSizedWord r1 r2+    | r1 == r2 = []+-- Cast to Word#+sizedWordToSizedWord r WordRep = [(wordToMachineWord r,wordPrimTy)]+-- Cast from Word#+sizedWordToSizedWord WordRep r = [(wordFromMachineWord r, primRepToType r)]+-- Conversion between different non-machine sizes must go via machine word.+sizedWordToSizedWord r1 r2 = (wordToMachineWord r1,wordPrimTy) : [(wordFromMachineWord r2, primRepToType r2)]+++-- Prefer the definitions above this line if possible+----------------------+++-- Int*# to Int#+{-# INLINE intToMachineInt #-}+intToMachineInt :: HasDebugCallStack => PrimRep -> PrimOp+intToMachineInt r =+    assertPpr (primRepIsInt r) (ppr r) $+    case r of+        (Int8Rep) -> Int8ToIntOp+        (Int16Rep) -> Int16ToIntOp+        (Int32Rep) -> Int32ToIntOp+        (Int64Rep) -> Int64ToIntOp+        _ -> pprPanic "Source rep not int" $ ppr r++-- Int# to Int*#+{-# INLINE intFromMachineInt #-}+intFromMachineInt :: HasDebugCallStack => PrimRep -> PrimOp+intFromMachineInt r =+    assertPpr (primRepIsInt r) (ppr r) $+    case r of+        Int8Rep -> IntToInt8Op+        Int16Rep -> IntToInt16Op+        Int32Rep -> IntToInt32Op+        Int64Rep -> IntToInt64Op+        _ -> pprPanic "Dest rep not sized int" $ ppr r++-- Word# to Word*#+{-# INLINE wordFromMachineWord #-}+wordFromMachineWord :: HasDebugCallStack => PrimRep -> PrimOp+wordFromMachineWord r =+    assert (primRepIsWord r) $+    case r of+        Word8Rep -> WordToWord8Op+        Word16Rep -> WordToWord16Op+        Word32Rep -> WordToWord32Op+        Word64Rep -> WordToWord64Op+        _ -> pprPanic "Dest rep not sized word" $ ppr r++-- Word*# to Word#+{-# INLINE wordToMachineWord #-}+wordToMachineWord :: HasDebugCallStack => PrimRep -> PrimOp+wordToMachineWord r =+    assertPpr (primRepIsWord r) (text "Not a word rep:" <> ppr r) $+    case r of+        Word8Rep -> Word8ToWordOp+        Word16Rep -> Word16ToWordOp+        Word32Rep -> Word32ToWordOp+        Word64Rep -> Word64ToWordOp+        _ -> pprPanic "Dest rep not sized word" $ ppr r
compiler/GHC/Cmm/ContFlowOpt.hs view
@@ -12,7 +12,7 @@  import GHC.Prelude hiding (succ, unzip, zip) -import GHC.Cmm.Dataflow.Block+import GHC.Cmm.Dataflow.Block hiding (blockConcat) import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Graph import GHC.Cmm.Dataflow.Label
compiler/GHC/Cmm/Lexer.x view
@@ -94,6 +94,10 @@   "!="                  { kw CmmT_Ne }   "&&"                  { kw CmmT_BoolAnd }   "||"                  { kw CmmT_BoolOr }+  "%relaxed"            { kw CmmT_Relaxed }+  "%acquire"            { kw CmmT_Acquire }+  "%release"            { kw CmmT_Release }+  "%seq_cst"            { kw CmmT_SeqCst  }    "True"                { kw CmmT_True  }   "False"               { kw CmmT_False }@@ -183,6 +187,10 @@   | CmmT_False   | CmmT_True   | CmmT_likely+  | CmmT_Relaxed+  | CmmT_Acquire+  | CmmT_Release+  | CmmT_SeqCst   deriving (Show)  -- -----------------------------------------------------------------------------
compiler/GHC/Cmm/Lint.hs view
@@ -170,9 +170,21 @@             platform <- getPlatform             erep <- lintCmmExpr expr             let reg_ty = cmmRegType platform reg-            if (erep `cmmEqType_ignoring_ptrhood` reg_ty)-                then return ()-                else cmmLintAssignErr (CmmAssign reg expr) erep reg_ty+            unless (compat_regs erep reg_ty) $+              cmmLintAssignErr (CmmAssign reg expr) erep reg_ty+    where+      compat_regs :: CmmType -> CmmType -> Bool+      compat_regs ty1 ty2+        -- As noted in #22297, SIMD vector registers can be used for+        -- multiple different purposes, e.g. xmm1 can be used to hold 4 Floats,+        -- or 4 Int32s, or 2 Word64s, ...+        -- To allow this, we relax the check: we only ensure that the widths+        -- match, until we can find a more robust solution.+        | isVecType ty1+        , isVecType ty2+        = typeWidth ty1 == typeWidth ty2+        | otherwise+        = cmmEqType_ignoring_ptrhood ty1 ty2    CmmStore l r _alignment -> do             _ <- lintCmmExpr l
compiler/GHC/Cmm/Parser.y view
@@ -194,7 +194,28 @@ a 32-bit machine) then the call will push as many words as necessary to the stack to accommodate it (e.g. 2). +Memory ordering+--------------- +Cmm respects the C11 memory model and distinguishes between non-atomic and+atomic memory accesses. In C11 fashion, atomic accesses can provide a number of+memory ordering guarantees. These are supported in Cmm syntax as follows:++    W_[ptr] = ...;            // a non-atomic store+    %relaxed W_[ptr] = ...;   // an atomic store with relaxed ordering semantics+    %release W_[ptr] = ...;   // an atomic store with release ordering semantics++    x = W_(ptr);              // a non-atomic load+    x = %relaxed W_[ptr];     // an atomic load with relaxed ordering+    x = %acquire W_[ptr];     // an atomic load with acquire ordering+    // or equivalently...+    x = prim %load_acquire64(ptr);++Here we used W_ as an example but these operations can be used on all Cmm+types.++See Note [Heap memory barriers] in SMP.h for details.+ ----------------------------------------------------------------------------- -}  {@@ -317,6 +338,10 @@         'True'  { L _ (CmmT_True ) }         'False' { L _ (CmmT_False) }         'likely'{ L _ (CmmT_likely)}+        'relaxed'{ L _ (CmmT_Relaxed)}+        'acquire'{ L _ (CmmT_Acquire)}+        'release'{ L _ (CmmT_Release)}+        'seq_cst'{ L _ (CmmT_SeqCst)}          'CLOSURE'       { L _ (CmmT_CLOSURE) }         'INFO_TABLE'    { L _ (CmmT_INFO_TABLE) }@@ -632,8 +657,23 @@          | lreg '=' expr ';'                 { do reg <- $1; e <- $3; withSourceNote $2 $4 (emitAssign reg e) }++        -- Use lreg instead of local_reg to avoid ambiguity+        | lreg '=' mem_ordering type '[' expr ']' ';'+                { do reg <- $1;+                     let lreg = case reg of+                                  { CmmLocal r -> r+                                  ; other -> pprPanic "CmmParse:" (ppr reg <> text "not a local register")+                                  } ;+                     mord <- $3;+                     let { ty = $4; w = typeWidth ty };+                     e <- $6;+                     let op = MO_AtomicRead w mord;+                     withSourceNote $2 $7 $ code (emitPrimCall [lreg] op [e]) }+        | mem_ordering type '[' expr ']' '=' expr ';'+                { do mord <- $1; withSourceNote $3 $8 (doStore (Just mord) $2 $4 $7) }         | type '[' expr ']' '=' expr ';'-                { withSourceNote $2 $7 (doStore $1 $3 $6) }+                { withSourceNote $2 $7 (doStore Nothing $1 $3 $6) }          -- Gah! We really want to say "foreign_results" but that causes         -- a shift/reduce conflict with assignment.  We either@@ -683,6 +723,14 @@         | GLOBALREG '=' expr_or_unknown                 { do e <- $3; return [($1, e)] } +-- | A memory ordering+mem_ordering :: { CmmParse MemoryOrdering }+mem_ordering+        : 'relaxed' { do return MemOrderRelaxed }+        | 'release' { do return MemOrderRelease }+        | 'acquire' { do return MemOrderAcquire }+        | 'seq_cst' { do return MemOrderSeqCst }+ -- | Used by unwind to indicate unknown unwinding values. expr_or_unknown         :: { CmmParse (Maybe CmmExpr) }@@ -957,6 +1005,7 @@     platform = profilePlatform profile  -- we understand a subset of C-- primitives:+machOps :: UniqFM FastString (Width -> MachOp) machOps = listToUFM $         map (\(x, y) -> (mkFastString x, y)) [         ( "add",        MO_Add ),@@ -1078,37 +1127,32 @@         ( "suspendThread", (MO_SuspendThread,) ),         ( "resumeThread",  (MO_ResumeThread,) ), -        ("prefetch0", (MO_Prefetch_Data 0,)),-        ("prefetch1", (MO_Prefetch_Data 1,)),-        ("prefetch2", (MO_Prefetch_Data 2,)),-        ("prefetch3", (MO_Prefetch_Data 3,)),--        ( "popcnt8",  (MO_PopCnt W8,)),-        ( "popcnt16", (MO_PopCnt W16,)),-        ( "popcnt32", (MO_PopCnt W32,)),-        ( "popcnt64", (MO_PopCnt W64,)),--        ( "pdep8",  (MO_Pdep W8,)),-        ( "pdep16", (MO_Pdep W16,)),-        ( "pdep32", (MO_Pdep W32,)),-        ( "pdep64", (MO_Pdep W64,)),--        ( "pext8",  (MO_Pext W8,)),-        ( "pext16", (MO_Pext W16,)),-        ( "pext32", (MO_Pext W32,)),-        ( "pext64", (MO_Pext W64,)),--        ( "cmpxchg8",  (MO_Cmpxchg W8,)),-        ( "cmpxchg16", (MO_Cmpxchg W16,)),-        ( "cmpxchg32", (MO_Cmpxchg W32,)),-        ( "cmpxchg64", (MO_Cmpxchg W64,)),--        ( "xchg8",  (MO_Xchg W8,)),-        ( "xchg16", (MO_Xchg W16,)),-        ( "xchg32", (MO_Xchg W32,)),-        ( "xchg64", (MO_Xchg W64,))+        ( "prefetch0", (MO_Prefetch_Data 0,)),+        ( "prefetch1", (MO_Prefetch_Data 1,)),+        ( "prefetch2", (MO_Prefetch_Data 2,)),+        ( "prefetch3", (MO_Prefetch_Data 3,))+    ] ++ concat+    [ allWidths "popcnt" MO_PopCnt+    , allWidths "pdep" MO_Pdep+    , allWidths "pext" MO_Pext+    , allWidths "cmpxchg" MO_Cmpxchg+    , allWidths "xchg" MO_Xchg+    , allWidths "load_relaxed" (\w -> MO_AtomicRead w MemOrderAcquire)+    , allWidths "load_acquire" (\w -> MO_AtomicRead w MemOrderAcquire)+    , allWidths "load_seqcst" (\w -> MO_AtomicRead w MemOrderSeqCst)+    , allWidths "store_release" (\w -> MO_AtomicWrite w MemOrderRelease)+    , allWidths "store_seqcst" (\w -> MO_AtomicWrite w MemOrderSeqCst)     ]   where+    allWidths+        :: String+        -> (Width -> CallishMachOp)+        -> [(FastString, a -> (CallishMachOp, a))]+    allWidths name f =+        [ (mkFastString $ name ++ show (widthInBits w), (f w,))+        | w <- [W8, W16, W32, W64]+        ]+     memcpyLikeTweakArgs :: (Int -> CallishMachOp) -> [CmmExpr] -> (CallishMachOp, [CmmExpr])     memcpyLikeTweakArgs op [] = pgmError "memcpy-like function requires at least one argument"     memcpyLikeTweakArgs op args@(_:_) =@@ -1352,8 +1396,12 @@                 let (p, args') = f args                 code (emitPrimCall (map fst results) p args') -doStore :: CmmType -> CmmParse CmmExpr  -> CmmParse CmmExpr -> CmmParse ()-doStore rep addr_code val_code+doStore :: Maybe MemoryOrdering+        -> CmmType+        -> CmmParse CmmExpr   -- ^ address+        -> CmmParse CmmExpr   -- ^ value+        -> CmmParse ()+doStore mem_ord rep addr_code val_code   = do platform <- getPlatform        addr <- addr_code        val <- val_code@@ -1367,7 +1415,7 @@        let coerce_val                 | val_width /= rep_width = CmmMachOp (MO_UU_Conv val_width rep_width) [val]                 | otherwise              = val-       emitStore addr coerce_val+       emitStore mem_ord addr coerce_val  -- ----------------------------------------------------------------------------- -- If-then-else and boolean expressions
compiler/GHC/Cmm/Utils.hs view
@@ -115,7 +115,7 @@    AddrRep          -> bWord platform    FloatRep         -> f32    DoubleRep        -> f64-   (VecRep len rep) -> vec len (primElemRepCmmType rep)+   VecRep len rep   -> vec len (primElemRepCmmType rep)  slotCmmType :: Platform -> SlotTy -> CmmType slotCmmType platform = \case@@ -125,6 +125,7 @@    Word64Slot      -> b64    FloatSlot       -> f32    DoubleSlot      -> f64+   VecSlot l e     -> vec l (primElemRepCmmType e)  primElemRepCmmType :: PrimElemRep -> CmmType primElemRepCmmType Int8ElemRep   = b8
compiler/GHC/CmmToAsm/AArch64/CodeGen.hs view
@@ -1535,8 +1535,8 @@          -- -- Atomic read-modify-write.         MO_AtomicRMW w amop -> mkCCall (atomicRMWLabel w amop)-        MO_AtomicRead w     -> mkCCall (atomicReadLabel w)-        MO_AtomicWrite w    -> mkCCall (atomicWriteLabel w)+        MO_AtomicRead w _   -> mkCCall (atomicReadLabel w)+        MO_AtomicWrite w _  -> mkCCall (atomicWriteLabel w)         MO_Cmpxchg w        -> mkCCall (cmpxchgLabel w)         -- -- Should be an AtomicRMW variant eventually.         -- -- Sequential consistent.
compiler/GHC/CmmToAsm/PPC/CodeGen.hs view
@@ -1174,7 +1174,7 @@                           (n_reg, n_code) <- getSomeReg n                           return  (op dst dst (RIReg n_reg), n_code) -genCCall (PrimTarget (MO_AtomicRead width)) [dst] [addr]+genCCall (PrimTarget (MO_AtomicRead width _)) [dst] [addr]  = do let fmt      = intFormat width           reg_dst  = getLocalRegReg dst           form     = if widthInBits width == 64 then DS else D@@ -1201,7 +1201,7 @@ -- This is also what gcc does.  -genCCall (PrimTarget (MO_AtomicWrite width)) [] [addr, val] = do+genCCall (PrimTarget (MO_AtomicWrite width _)) [] [addr, val] = do     code <- assignMem_IntCode (intFormat width) addr val     return $ unitOL HWSYNC `appOL` code @@ -2068,8 +2068,8 @@                     MO_AtomicRMW {} -> unsupported                     MO_Cmpxchg w -> (cmpxchgLabel w, False)                     MO_Xchg w    -> (xchgLabel w, False)-                    MO_AtomicRead _  -> unsupported-                    MO_AtomicWrite _ -> unsupported+                    MO_AtomicRead _ _  -> unsupported+                    MO_AtomicWrite _ _ -> unsupported                      MO_S_Mul2    {}  -> unsupported                     MO_S_QuotRem {}  -> unsupported
compiler/GHC/CmmToAsm/X86/CodeGen.hs view
@@ -2167,8 +2167,8 @@ genSimplePrim bid (MO_Pext width)      [dst]   [src,mask]     = genPext bid width dst src mask genSimplePrim bid (MO_Clz width)       [dst]   [src]          = genClz bid width dst src genSimplePrim bid (MO_UF_Conv width)   [dst]   [src]          = genWordToFloat bid width dst src-genSimplePrim _   (MO_AtomicRead w)    [dst]   [addr]         = genAtomicRead w dst addr-genSimplePrim _   (MO_AtomicWrite w)   []      [addr,val]     = genAtomicWrite w addr val+genSimplePrim _   (MO_AtomicRead w mo)  [dst]  [addr]         = genAtomicRead w mo dst addr+genSimplePrim _   (MO_AtomicWrite w mo) []     [addr,val]     = genAtomicWrite w mo addr val genSimplePrim bid (MO_Cmpxchg width)   [dst]   [addr,old,new] = genCmpXchg bid width dst addr old new genSimplePrim _   (MO_Xchg width)      [dst]   [addr, value]  = genXchg width dst addr value genSimplePrim _   (MO_AddWordC w)      [r,c]   [x,y]          = genAddSubRetCarry w ADD_CC (const Nothing) CARRY r c x y@@ -3941,15 +3941,20 @@   -- TODO: generate assembly instead   genPrimCCall bid (word2FloatLabel width) [dst] [src] -genAtomicRead :: Width -> LocalReg -> CmmExpr -> NatM InstrBlock-genAtomicRead width dst addr = do+genAtomicRead :: Width -> MemoryOrdering -> LocalReg -> CmmExpr -> NatM InstrBlock+genAtomicRead width _mord dst addr = do   load_code <- intLoadCode (MOV (intFormat width)) addr   return (load_code (getLocalRegReg dst)) -genAtomicWrite :: Width -> CmmExpr -> CmmExpr -> NatM InstrBlock-genAtomicWrite width addr val = do+genAtomicWrite :: Width -> MemoryOrdering -> CmmExpr -> CmmExpr -> NatM InstrBlock+genAtomicWrite width mord addr val = do   code <- assignMem_IntCode (intFormat width) addr val-  return $ code `snocOL` MFENCE+  let needs_fence = case mord of+        MemOrderSeqCst  -> True+        MemOrderRelease -> True+        MemOrderAcquire -> pprPanic "genAtomicWrite: acquire ordering on write" empty+        MemOrderRelaxed -> False+  return $ if needs_fence then code `snocOL` MFENCE else code  genCmpXchg   :: BlockId
compiler/GHC/CmmToC.hs view
@@ -949,8 +949,9 @@         MO_AtomicRMW w amop -> ftext (atomicRMWLabel w amop)         MO_Cmpxchg w        -> ftext (cmpxchgLabel w)         MO_Xchg w           -> ftext (xchgLabel w)-        MO_AtomicRead w     -> ftext (atomicReadLabel w)-        MO_AtomicWrite w    -> ftext (atomicWriteLabel w)+        -- TODO: handle orderings+        MO_AtomicRead w _   -> ftext (atomicReadLabel w)+        MO_AtomicWrite w _  -> ftext (atomicWriteLabel w)         MO_UF_Conv w        -> ftext (word2FloatLabel w)          MO_S_Mul2     {} -> unsupported
compiler/GHC/CmmToLlvm/CodeGen.hs view
@@ -46,7 +46,7 @@ import Data.List ( nub ) import Data.Maybe ( catMaybes ) -type Atomic = Bool+type Atomic = Maybe MemoryOrdering type LlvmStatements = OrdList LlvmStatement  data Signage = Signed | Unsigned deriving (Eq, Show)@@ -266,9 +266,9 @@     retVar <- doExprW targetTy $ AtomicRMW op ptrVar nVar SyncSeqCst     statement $ Store retVar dstVar Nothing -genCall (PrimTarget (MO_AtomicRead _)) [dst] [addr] = runStmtsDecls $ do+genCall (PrimTarget (MO_AtomicRead _ mem_ord)) [dst] [addr] = runStmtsDecls $ do     dstV <- getCmmRegW (CmmLocal dst)-    v1 <- genLoadW True addr (localRegType dst) NaturallyAligned+    v1 <- genLoadW (Just mem_ord) addr (localRegType dst) NaturallyAligned     statement $ Store v1 dstV Nothing  genCall (PrimTarget (MO_Cmpxchg _width))@@ -295,13 +295,14 @@     resVar <- doExprW (getVarType valVar) (AtomicRMW LAO_Xchg ptrVar valVar SyncSeqCst)     statement $ Store resVar dstV Nothing -genCall (PrimTarget (MO_AtomicWrite _width)) [] [addr, val] = runStmtsDecls $ do+genCall (PrimTarget (MO_AtomicWrite _width mem_ord)) [] [addr, val] = runStmtsDecls $ do     addrVar <- exprToVarW addr     valVar <- exprToVarW val     let ptrTy = pLift $ getVarType valVar         ptrExpr = Cast LM_Inttoptr addrVar ptrTy     ptrVar <- doExprW ptrTy ptrExpr-    statement $ Expr $ AtomicRMW LAO_Xchg ptrVar valVar SyncSeqCst+    let ordering = convertMemoryOrdering mem_ord+    statement $ Expr $ AtomicRMW LAO_Xchg ptrVar valVar ordering  -- Handle memcpy function specifically since llvm's intrinsic version takes -- some extra parameters.@@ -1013,11 +1014,11 @@     MO_Touch         -> unsupported     MO_UF_Conv _     -> unsupported -    MO_AtomicRead _  -> unsupported-    MO_AtomicRMW _ _ -> unsupported-    MO_AtomicWrite _ -> unsupported-    MO_Cmpxchg _     -> unsupported-    MO_Xchg _        -> unsupported+    MO_AtomicRead _ _  -> unsupported+    MO_AtomicRMW _ _   -> unsupported+    MO_AtomicWrite _ _ -> unsupported+    MO_Cmpxchg _       -> unsupported+    MO_Xchg _          -> unsupported      MO_I64_ToI       -> dontReach64     MO_I64_FromI     -> dontReach64@@ -1369,7 +1370,7 @@         -> genLit opt lit      CmmLoad e' ty align-        -> genLoad False e' ty align+        -> genLoad Nothing e' ty align      -- Cmmreg in expression is the value, so must load. If you want actual     -- reg pointer, call getCmmReg directly.@@ -1901,7 +1902,8 @@  mkLoad :: Atomic -> LlvmVar -> AlignmentSpec -> LlvmExpression mkLoad atomic vptr alignment-  | atomic      = ALoad SyncSeqCst False vptr+  | Just mem_ord <- atomic+                = ALoad (convertMemoryOrdering mem_ord) False vptr   | otherwise   = Load vptr align   where     ty = pLower (getVarType vptr)@@ -2037,6 +2039,12 @@ -- ----------------------------------------------------------------------------- -- * Misc --++convertMemoryOrdering :: MemoryOrdering -> LlvmSyncOrdering+convertMemoryOrdering MemOrderRelaxed = SyncMonotonic+convertMemoryOrdering MemOrderAcquire = SyncAcquire+convertMemoryOrdering MemOrderRelease = SyncRelease+convertMemoryOrdering MemOrderSeqCst  = SyncSeqCst  -- | Find CmmRegs that get assigned and allocate them on the stack --
compiler/GHC/Core/Opt/DmdAnal.hs view
@@ -248,8 +248,10 @@ dmdAnalBind top_lvl env dmd bind anal_body = case bind of   NonRec id rhs     | useLetUp top_lvl id-    -> dmdAnalBindLetUp   top_lvl env     id rhs anal_body-  _ -> dmdAnalBindLetDown top_lvl env dmd bind   anal_body+    -> dmdAnalBindLetUp   top_lvl env_rhs     id rhs anal_body+  _ -> dmdAnalBindLetDown top_lvl env_rhs dmd bind   anal_body+  where+    env_rhs = enterDFun bind env  -- | Annotates uninteresting top level functions ('isInterestingTopLevelFn') -- with 'topDmd', the rest with the given demand.@@ -448,8 +450,9 @@         !(!bndrs', !scrut_sd)           | DataAlt _ <- alt           -- See Note [Demand on the scrutinee of a product case]+          , let !scrut_sd = scrutSubDmd case_bndr_sd fld_dmds           -- See Note [Demand on case-alternative binders]-          , (!scrut_sd, fld_dmds') <- addCaseBndrDmd case_bndr_sd fld_dmds+          , let !fld_dmds' = fieldBndrDmds scrut_sd (length fld_dmds)           , let !bndrs' = setBndrsDemandInfo bndrs fld_dmds'           = (bndrs', scrut_sd)           | otherwise@@ -559,7 +562,7 @@   | otherwise   = False -dmdAnalSumAlt :: AnalEnv -> SubDemand -> Id -> Alt Var -> WithDmdType (Alt Var)+dmdAnalSumAlt :: AnalEnv -> SubDemand -> Id -> Alt Var -> WithDmdType CoreAlt dmdAnalSumAlt env dmd case_bndr (Alt con bndrs rhs)   | WithDmdType rhs_ty rhs' <- dmdAnal env dmd rhs   , WithDmdType alt_ty dmds <- findBndrsDmds env rhs_ty bndrs@@ -567,27 +570,29 @@         -- See Note [Demand on case-alternative binders]         -- we can't use the scrut_sd, because it says 'Prod' and we'll use         -- topSubDmd anyway for scrutinees of sum types.-        (!_scrut_sd, dmds') = addCaseBndrDmd case_bndr_sd dmds+        scrut_sd = scrutSubDmd case_bndr_sd dmds+        dmds' = fieldBndrDmds scrut_sd (length dmds)         -- Do not put a thunk into the Alt         !new_ids            = setBndrsDemandInfo bndrs dmds'   = WithDmdType alt_ty (Alt con new_ids rhs') --- Precondition: The SubDemand is not a Call -- See Note [Demand on the scrutinee of a product case]--- and Note [Demand on case-alternative binders]-addCaseBndrDmd :: SubDemand -- On the case binder-               -> [Demand]  -- On the fields of the constructor-               -> (SubDemand, [Demand])-                            -- SubDemand on the case binder incl. field demands-                            -- and final demands for the components of the constructor-addCaseBndrDmd case_sd fld_dmds-  | Just (_, ds) <- viewProd (length fld_dmds) scrut_sd-  = (scrut_sd, ds)-  | otherwise-  = pprPanic "was a call demand" (ppr case_sd $$ ppr fld_dmds) -- See the Precondition-  where-    scrut_sd = case_sd `plusSubDmd` mkProd Unboxed fld_dmds+scrutSubDmd :: SubDemand -> [Demand] -> SubDemand+scrutSubDmd case_sd fld_dmds =+  -- pprTraceWith "scrutSubDmd" (\scrut_sd -> ppr case_sd $$ ppr fld_dmds $$ ppr scrut_sd) $+  case_sd `plusSubDmd` mkProd Unboxed fld_dmds +-- See Note [Demand on case-alternative binders]+fieldBndrDmds :: SubDemand -- on the scrutinee+              -> Arity+              -> [Demand]  -- Final demands for the components of the DataCon+fieldBndrDmds scrut_sd n_flds =+  case viewProd n_flds scrut_sd of+    Just (_, ds) -> ds+    Nothing      -> replicate n_flds topDmd+                      -- Either an arity mismatch or scrut_sd was a call demand.+                      -- See Note [Untyped demand on case-alternative binders]+ {- Note [Analysing with absent demand] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -769,6 +774,44 @@ This is needed even for non-product types, in case the case-binder is used but the components of the case alternative are not. +Note [Untyped demand on case-alternative binders]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+With unsafeCoerce, #8037 and #22039 taught us that the demand on the case binder+may be a call demand or have a different number of fields than the constructor+of the case alternative it is used in. From T22039:++  blarg :: (Int, Int) -> Int+  blarg (x,y) = x+y+  -- blarg :: <1!P(1L,1L)>++  f :: Either Int Int -> Int+  f Left{} = 0+  f e = blarg (unsafeCoerce e)+  ==> { desugars to }+  f = \ (ds_d1nV :: Either Int Int) ->+      case ds_d1nV of wild_X1 {+        Left ds_d1oV -> lvl_s1Q6;+        Right ipv_s1Pl ->+          blarg+            (case unsafeEqualityProof @(*) @(Either Int Int) @(Int, Int) of+             { UnsafeRefl co_a1oT ->+             wild_X1 `cast` (Sub (Sym co_a1oT) :: Either Int Int ~R# (Int, Int))+             })+      }++The case binder `e`/`wild_X1` has demand 1!P(1L,1L), with two fields, from the call+to `blarg`, but `Right` only has one field. Although the code will crash when+executed, we must be able to analyse it in 'fieldBndrDmds' and conservatively+approximate with Top instead of panicking because of the mismatch.+In #22039, this kind of code was guarded behind a safe `cast` and thus dead+code, but nevertheless led to a panic of the compiler.++You might wonder why the same problem doesn't come up when scrutinising a+product type instead of a sum type. It appears that for products, `wild_X1`+will be inlined before DmdAnal.++See also Note [mkWWstr and unsafeCoerce] for a related issue.+ Note [Aggregated demand for cardinality] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FIXME: This Note should be named [LetUp vs. LetDown] and probably predates@@ -829,8 +872,9 @@ -- See Note [What are demand signatures?] in "GHC.Types.Demand" dmdTransform env var sd   -- Data constructors-  | isDataConWorkId var-  = dmdTransformDataConSig (idArity var) sd+  | Just con <- isDataConWorkId_maybe var+  = -- pprTraceWith "dmdTransform:DataCon" (\ty -> ppr con $$ ppr sd $$ ppr ty) $+    dmdTransformDataConSig (dataConRepStrictness con) sd   -- Dictionary component selectors   -- Used to be controlled by a flag.   -- See #18429 for some perf measurements.@@ -1492,13 +1536,18 @@  Historical note: #14955 describes how I got this fix wrong the first time. -Note that the simplicity of this fix implies that INLINE functions (such as-wrapper functions after the WW run) will never say that they unbox class-dictionaries. That's not ideal, but not worth losing sleep over, as INLINE-functions will have been inlined by the time we run demand analysis so we'll-see the unboxing around the worker in client modules. I got aware of the issue-in T5075 by the change in boxity of loop between demand analysis runs.+2. -fspecialise-aggressively.  As #21286 shows, the same phenomenon can occur+   occur without INLINABLE, when we use -fexpose-all-unfoldings and+   -fspecialise-aggressively to do vigorous cross-module specialisation. +3. #18421 found that unboxing a dictionary can also make the worker less likely+   to inline; the inlining heuristics seem to prefer to inline a function+   applied to a dictionary over a function applied to a bunch of functions.++TL;DR we /never/ unbox class dictionaries. Unboxing the dictionary, and passing+a raft of higher-order functions isn't a huge win anyway -- you really want to+specialise the function.+ Note [Worker argument budget] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In 'finaliseArgBoxities' we don't want to generate workers with zillions of@@ -1842,14 +1891,6 @@         -- L demand doesn't get both'd with the Bot coming up from the inner         -- call to f.  So we just get an L demand for x for g. -{--Note [Do not strictify the argument dictionaries of a dfun]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-The typechecker can tie recursive knots involving dfuns, so we do the-conservative thing and refrain from strictifying a dfun's argument-dictionaries.--}- setBndrsDemandInfo :: HasCallStack => [Var] -> [Demand] -> [Var] setBndrsDemandInfo (b:bs) ds   | isTyVar b = b : setBndrsDemandInfo bs ds@@ -1988,6 +2029,16 @@          , ae_rec_dc       = memoiseUniqueFun (isRecDataCon fam_envs 3)          } +-- | Unset the 'dmd_strict_dicts' flag if any of the given bindings is a DFun+-- binding. Part of the mechanism that detects+-- Note [Do not strictify a DFun's parameter dictionaries].+enterDFun :: CoreBind -> AnalEnv -> AnalEnv+enterDFun bind env+  | any isDFunId (bindersOf bind)+  = env { ae_opts = (ae_opts env) { dmd_strict_dicts = False } }+  | otherwise+  = env+ emptySigEnv :: SigEnv emptySigEnv = emptyVarEnv @@ -2039,58 +2090,74 @@     id_ty = idType id      strictify dmd-      -- See Note [Making dictionaries strict]+      -- See Note [Making dictionary parameters strict]+      -- and Note [Do not strictify a DFun's parameter dictionaries]       | dmd_strict_dicts (ae_opts env)-             -- We never want to strictify a recursive let. At the moment-             -- findBndrDmd is never called for recursive lets; if that-             -- changes, we need a RecFlag parameter and another guard here.       = strictifyDictDmd id_ty dmd       | otherwise       = dmd      fam_envs = ae_fam_envs env -{- Note [Making dictionaries strict]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+{- Note [Making dictionary parameters strict]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Opt_DictsStrict flag makes GHC use call-by-value for dictionaries.  Why?  * Generally CBV is more efficient. -* Dictionaries are always non-bottom; and never take much work to-  compute.  E.g. a dfun from an instance decl always returns a dicionary+* A datatype dictionary is always non-bottom and never takes much work to+  compute.  E.g. a DFun from an instance decl always returns a dictionary   record immediately.  See DFunUnfolding in CoreSyn.   See also Note [Recursive superclasses] in TcInstDcls. -* The strictness analyser will then unbox dictionaries and pass the-  methods individually, rather than in a bundle.  If there are a lot of-  methods that might be bad; but worker/wrapper already does throttling.+See #17758 for more background and perf numbers. +Wrinkles:+ * A newtype dictionary is *not* always non-bottom.  E.g.       class C a where op :: a -> a       instance C Int where op = error "urk"   Now a value of type (C Int) is just a newtype wrapper (a cast) around   the error thunk.  Don't strictify these! -See #17758 for more background and perf numbers.+* Strictifying DFuns risks destroying the invariant that DFuns never take much+  work to compute, so we don't do it.+  See Note [Do not strictify a DFun's parameter dictionaries] for details. +* Although worker/wrapper *could* unbox strictly used dictionaries, we do not do+  so; see Note [Do not unbox class dictionaries].+ The implementation is extremly simple: just make the strictness analyser strictify the demand on a dictionary binder in-'findBndrDmd'.+'findBndrDmd' if the binder does not belong to a DFun. -However there is one case where this can make performance worse.-For the principle consider some function at the core level:-    myEq :: Eq a => a -> a -> Bool-    myEq eqDict x y = ((==) eqDict) x y-If we make the dictionary strict then WW can fire turning this into:-    $wmyEq :: (a -> a -> Bool) -> a -> a -> Bool-    $wmyEq eq x y = eq x y-Which *usually* performs better. However if the dictionary is known we-are far more likely to inline a function applied to the dictionary than-to inline one applied to a function. Sometimes this makes just enough-of a difference to stop a function from inlining. This is documented in #18421.+Note [Do not strictify a DFun's parameter dictionaries]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+The typechecker can tie recursive knots involving (non-recursive) DFuns, so+we must not strictify a DFun's parameter dictionaries (#22549).+T22549 has an example involving undecidable instances that <<loop>>s when we+strictify the DFun of, e.g., `$fEqSeqT`: -It's somewhat similar to Note [Do not unbox class dictionaries] although-here our problem is with the inliner, not the specializer.+  Main.$fEqSeqT+    = \@m @a ($dEq :: Eq (m (ViewT m a))) ($dMonad :: Monad m) ->+        GHC.Classes.C:Eq @(SeqT m a) ($c== @m @a $dEq $dMonad)+                                     ($c/= @m @a $dEq $dMonad)++  Rec {+    $dEq_a = Main.$fEqSeqT @Identity @Int $dEq_b Main.$fMonadIdentity+    $dEq_b = ... $dEq_a ... <another strict context due to DFun>+  }++If we make `$fEqSeqT` strict in `$dEq`, we'll collapse the Rec group into a+giant, <<loop>>ing thunk.++To prevent that, we never strictify dictionary params when inside a DFun.+That is implemented by unsetting 'dmd_strict_dicts' when entering a DFun.++See also Note [Speculative evaluation] in GHC.CoreToStg.Prep which has a rather+similar example in #20836. We may never speculate *arguments* of (recursive)+DFun calls, likewise we should not mark *formal parameters* of recursive DFuns+as strict.  Note [Initialising strictness] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compiler/GHC/CoreToStg/Prep.hs view
@@ -1733,6 +1733,10 @@ The problem is very similar to Note [Eta reduction in recursive RHSs]. Here as well as there it is *unsound* to change the termination properties of the very function whose termination properties we are exploiting.++It is also similar to Note [Do not strictify a DFun's parameter dictionaries],+where marking recursive DFuns (of undecidable *instances*) strict in dictionary+*parameters* leads to quite the same change in termination as above. -}  data FloatingBind
compiler/GHC/Driver/Make.hs view
@@ -727,8 +727,8 @@                     Just n  -> return n      setSession $ hscUpdateHUG (unitEnv_map pruneHomeUnitEnv) hsc_env-    hsc_env <- getSession-    (upsweep_ok, hsc_env1) <- withDeferredDiagnostics $+    (upsweep_ok, hsc_env1) <- withDeferredDiagnostics $ do+      hsc_env <- getSession       liftIO $ upsweep n_jobs hsc_env mhmi_cache mHscMessage (toCache pruned_cache) build_plan     setSession hsc_env1     case upsweep_ok of
compiler/GHC/HsToCore/Expr.hs view
@@ -945,7 +945,8 @@            ; body' <- dsLExpr $ noLocA $ HsDo body_ty ctx (noLocA stmts)             ; let match_args (pat, fail_op) (vs,body)-                   = do { var   <- selectSimpleMatchVarL Many pat+                   = putSrcSpanDs (getLocA pat) $+                     do { var   <- selectSimpleMatchVarL Many pat                         ; match <- matchSinglePatVar var Nothing (StmtCtxt (HsDoStmt ctx)) pat                                    body_ty (cantFailMatchResult body)                         ; match_code <- dsHandleMonadicFailure ctx pat match fail_op
compiler/GHC/Linker/Windows.hs view
@@ -50,10 +50,8 @@            newTempName logger tmpfs (tmpDir dflags) TFL_GhcSession (objectSuf dflags)           writeFile rc_filename $-             "1 24 MOVEABLE PURE " ++ show manifest_filename ++ "\n"+             "1 24 MOVEABLE PURE \"" ++ manifest_filename ++ "\"\n"                -- magic numbers :-)-               -- show is a bit hackish above, but we need to escape the-               -- backslashes in the path.           runWindres logger dflags $ map GHC.SysTools.Option $                ["--input="++rc_filename,
compiler/GHC/Settings/IO.hs view
@@ -79,11 +79,11 @@   myExtraGccViaCFlags <- getSetting "GCC extra via C opts"   cc_prog <- getToolSetting "C compiler command"   cxx_prog <- getToolSetting "C++ compiler command"-  cc_args_str <- getSetting "C compiler flags"-  cxx_args_str <- getSetting "C++ compiler flags"+  cc_args_str <- getToolSetting "C compiler flags"+  cxx_args_str <- getToolSetting "C++ compiler flags"   gccSupportsNoPie <- getBooleanSetting "C compiler supports -no-pie"   cpp_prog <- getToolSetting "Haskell CPP command"-  cpp_args_str <- getSetting "Haskell CPP flags"+  cpp_args_str <- getToolSetting "Haskell CPP flags"    platform <- either pgmError pure $ getTargetPlatform settingsFile mySettings @@ -125,13 +125,13 @@     -- Other things being equal, as and ld are simply gcc-  cc_link_args_str <- getSetting "C compiler link flags"+  cc_link_args_str <- getToolSetting "C compiler link flags"   let   as_prog  = cc_prog         as_args  = map Option cc_args         ld_prog  = cc_prog         ld_args  = map Option (cc_args ++ words cc_link_args_str)   ld_r_prog <- getToolSetting "Merge objects command"-  ld_r_args <- getSetting "Merge objects flags"+  ld_r_args <- getToolSetting "Merge objects flags"   let ld_r         | null ld_r_prog = Nothing         | otherwise      = Just (ld_r_prog, map Option $ words ld_r_args)
compiler/GHC/Stg/Lift/Analysis.hs view
@@ -326,7 +326,7 @@ rhsCard :: Id -> Card rhsCard bndr   | is_thunk  = oneifyCard n-  | otherwise = peelManyCalls (idArity bndr) cd+  | otherwise = fst (peelManyCalls (idArity bndr) cd)   where     is_thunk = idArity bndr == 0     -- Let's pray idDemandInfo is still OK after unarise...
compiler/GHC/Stg/Lint.hs view
@@ -46,10 +46,19 @@   t_1 :: TYPE r_1, ..., t_n :: TYPE r_n   s_1 :: TYPE p_1, ..., a_n :: TYPE p_n -Then we must check that each r_i is compatible with s_i. Compatibility-is weaker than on-the-nose equality: for example, IntRep and WordRep are-compatible. See Note [Bad unsafe coercion] in GHC.Core.Lint.+Before unarisation, we must check that each r_i is compatible with s_i.+Compatibility is weaker than on-the-nose equality: for example,+IntRep and WordRep are compatible. See Note [Bad unsafe coercion] in GHC.Core.Lint. +After unarisation, a single type might correspond to multiple arguments, e.g.++  (# Int# | Bool #) :: TYPE (SumRep '[ IntRep, LiftedRep ])++will result in two arguments: [Int# :: TYPE 'IntRep, Bool :: TYPE LiftedRep]+This means post unarise we potentially have to match up multiple arguments with+the reps of a single argument in the type's definition, because the type of the function+is *not* in unarised form.+ Wrinkle: it can sometimes happen that an argument type in the type of the function does not have a fixed runtime representation, i.e. there is an r_i such that runtimeRepPrimRep r_i crashes.@@ -122,7 +131,7 @@ import GHC.Utils.Misc import GHC.Core.Multiplicity (scaledThing) import GHC.Settings (Platform)-import GHC.Core.TyCon (primRepCompatible)+import GHC.Core.TyCon (primRepCompatible, primRepsCompatible) import GHC.Utils.Panic.Plain (panic)  lintStgTopBindings :: forall a . (OutputablePass a, BinderP a ~ Id)@@ -332,14 +341,18 @@ lintStgAppReps fun args = do   lf <- getLintFlags   let platform = lf_platform lf+       (fun_arg_tys, _res) = splitFunTys (idType fun)-      fun_arg_tys' = map (scaledThing ) fun_arg_tys :: [Type]+      fun_arg_tys' = map scaledThing fun_arg_tys :: [Type]++      -- Might be "wrongly" typed as polymorphic. See #21399+      -- In these cases typePrimRep_maybe will return Nothing+      -- and we abort kind checking.       fun_arg_tys_reps, actual_arg_reps :: [Maybe [PrimRep]]       fun_arg_tys_reps = map typePrimRep_maybe fun_arg_tys'       actual_arg_reps = map (typePrimRep_maybe . stgArgType) args        match_args :: [Maybe [PrimRep]] -> [Maybe [PrimRep]] -> LintM ()-      -- Might be wrongly typed as polymorphic. See #21399       match_args (Nothing:_) _   = return ()       match_args (_) (Nothing:_) = return ()       match_args (Just actual_rep:actual_reps_left) (Just expected_rep:expected_reps_left)@@ -353,21 +366,36 @@          -- Some reps are compatible *even* if they are not the same. E.g. IntRep and WordRep.         -- We check for that here with primRepCompatible-        | and $ zipWith (primRepCompatible platform) actual_rep expected_rep+        | primRepsCompatible platform actual_rep expected_rep         = match_args actual_reps_left expected_reps_left -        | otherwise = addErrL $ hang (text "Function type reps and function argument reps missmatched") 2 $+        -- We might distribute args from within one unboxed sum over multiple+        -- single rep args. This means we might need to match up things like:+        -- [Just [WordRep, LiftedRep]] with [Just [WordRep],Just [LiftedRep]]+        -- which happens here.+        -- See Note [Linting StgApp].+        | Just (actual,actuals) <- getOneRep actual_rep actual_reps_left+        , Just (expected,expecteds) <- getOneRep expected_rep expected_reps_left+        , primRepCompatible platform actual expected+        = match_args actuals expecteds++        | otherwise = addErrL $ hang (text "Function type reps and function argument reps mismatched") 2 $             (text "In application " <> ppr fun <+> ppr args $$-              text "argument rep:" <> ppr actual_rep $$-              text "expected rep:" <> ppr expected_rep $$+              text "argument rep:" <> ppr actual_arg_reps $$+              text "expected rep:" <> ppr fun_arg_tys_reps $$               -- text "expected reps:" <> ppr arg_ty_reps $$               text "unarised?:" <> ppr (lf_unarised lf))         where           isVoidRep [] = True           isVoidRep [VoidRep] = True           isVoidRep _ = False--          -- n_arg_ty_reps = length arg_ty_reps+          -- Try to strip one non-void arg rep from the current argument type returning+          -- the remaining list of arguments. We return Nothing for invalid input which+          -- will result in a lint failure in match_args.+          getOneRep :: [PrimRep] -> [Maybe [PrimRep]] -> Maybe (PrimRep, [Maybe [PrimRep]])+          getOneRep [] _rest = Nothing -- Void rep args are invalid at this point.+          getOneRep [rep] rest = Just (rep,rest) -- A single arg rep arg+          getOneRep (rep:reps) rest = Just (rep,Just reps:rest) -- Multi rep arg.        match_args _ _ = return () -- Functions are allowed to be over/under applied. 
compiler/GHC/Stg/Unarise.hs view
@@ -186,6 +186,129 @@ layout to use. Note that unlifted values can't be let-bound, so we don't need types in StgRhsCon. +Note [Casting slot arguments]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider this function which selects between Int32# and Int64# from a unboxed sum.++    foo ::  (# Int32# | Int64#  #) -> FD+    foo x = case x of+        (# x1 | #) -> F x1+        (# | x2 #) -> D x2++Naturally we would expect x1 to have a PrimRep of Int32Rep and x2 of DoubleRep.+However we used to generate this (bogus) code after Unarise giving rise to #22208:++    M.foo :: (# GHC.Prim.Int32# | GHC.Prim.Int64# #) -> M.FD+    [GblId, Arity=1, Unf=OtherCon []] =+        {} \r [sum_tag sum_field]+            case sum_tag of tag_gsc {+              __DEFAULT -> M.F [sum_field];+              2# -> M.D [sum_field];+            };++Where sum_field is used both as Int32# and Int64# depending on the branch+because they share the same SlotTy.+This usually works out since we put all int's in the same sort of register.+So even if the reps where wrong (x :: bits32) = (y :: bits64) would produce+correct code in the most cases.+However there are cases where this goes wrong, causing lint errors,in the case of #22208+compiler panics or in some cases incorrect results in the C backend.+For now our solution is to construct proper casts between the PrimRep of the slot and+the variables we want to store in, or read out of these slots.++This means when we have a sum (# Int32# | Int64# #) if we want to store a Int32+we convert it to a Int64 on construction of the tuple value, and convert it back+to a Int32 once when want to use the field. On most backends these coversions should+be no-ops at runtime so this seems reasonable.++Conversion for values coming out of a strict field happen in mapSumIdBinders. While+conversion during the construction of sums happen inside mkUbxSum.++------------- A full example of casting during sum construction ----------------++To compile a constructor application of a unboxed sum of type (# Int32# | Int64# )+in an expression like  `let sum = (# x | #)` we will call mkUbxSum to determine+which binders we have to replace sum with at use sites during unarise.+See also Note [Translating unboxed sums to unboxed tuples].++Int32# and Int64# in this case will share the same slot in the unboxed sum. This means+the sum after unarise will be represented by two binders. One for the tag and one for+the field. The later having Int64Rep.+However our input for the field is of Int32Rep. So in order to soundly construct+`(# x | #) :: (# Int32# | Int64# )` we must upcast `x` to Int64#.+To do this mkUbxSum will produce an expression with a hole for constructor application+to go into. That is the call to mkUbxSum and it's result will look something like:++  >>> mkUbxSum (#|#) [Int32#, Int64#] (x::Int32#) us (x')+  ([1#::Int#, x'::Int64#], \rhs -> case int32ToInt# x of x' -> rhs )++We will use the returned arguments to construct an application to an unboxed tuple:++  >>> mkTuple [tag::Int#, x'::Int64#]+  (# tag, x' #)++Which we will then use as the rhs to pass into the casting wrapper to+construct an expression that casts `x` to the right type before constructing the+tuple++  >>> (\rhs -> case int32ToInt# x of x' -> rhs ) (# tag, x' #)+  case int32ToInt# x of x' -> (# #) 1# x'++Which results in the this definition for `sum` after all is said and done:++  let sum = case int32ToInt# x of { x' -> (# #) 1# x' }++Not that the renaming is not optional. Cmm requires binders of different uniques+to have at least different types. See Note [CorePrep Overview]: 6. Clone all local Ids++------------- A full example of casting during sum matching --------------------++When matching on an unboxed sum constructor we start out with+something like this the pre-unarise:++    f :: (# Int32 | Int64# ) -> ...+    f sum = case sum of+        (# x |#) -> alt_rhs+        ...++We unarise the function arguments and get:++    f sum_tag sum_slot1 = case sum_tag of+        1# -> ???++Now we need to match up the original alternative binders with the sum slots passed+to the function. This is done by mapSumIdBinders which we we call for our+example alternative like this:++    >>> mapSumIdBinders [x] [sum_slot1] alt_rhs env+    (env', alt_rhs')++mapSumIdBinders first matches up the list of binders with the slots passed to+the function which is trivial in this case. Then we check if the slot and the+variable residing inside it agree on their Rep. If alternative binders and+the function arguments agree in their slot reps we we just extend the environment+with a mapping from `x` to `sum_slot1` and we return the rhs as is.++If the reps of the sum_slots do not agree with alternative binders they represent+then we need to wrap the whole RHS in nested cases which cast the sum_slot<n>+variables to the correct rep. Here `x` is of Int32Rep while `sum_slot1` will be+of Int64Rep. This means instead of retuning the original alt_rhs we will return:++  >>> mapSumIdBinders [x] [sum_slot1] alt_rhs env+  ( env'[x=x']+  , case int64ToInt32# (sum_slot1 :: Int64#) of+      (x' :: Int32#) -> alt_rhs+  )++We then run unarise on alt_rhs within that expression, which will replace the first occurence+of `x` with sum_slot_arg_1 giving us post-unarise:++    f sum_tag sum_slot1 =+      case sum_tag of+        1# -> case int64ToInt32# sum_slot1 of+          x' -> ... x' ...+        ...+ Note [UnariseEnv] ~~~~~~~~~~~~~~~~~~ At any variable occurrence 'v',@@ -258,8 +381,8 @@ import GHC.Types.Basic import GHC.Core import GHC.Core.DataCon-import GHC.Core.TyCon ( isVoidRep )-import GHC.Data.FastString (FastString, mkFastString)+import GHC.Core.TyCon+import GHC.Data.FastString (FastString, mkFastString, fsLit) import GHC.Types.Id import GHC.Types.Literal import GHC.Core.Make (aBSENT_SUM_FIELD_ERROR_ID)@@ -268,20 +391,25 @@ import GHC.Utils.Outputable import GHC.Utils.Panic import GHC.Utils.Panic.Plain-import GHC.Types.RepType import GHC.Stg.Syntax import GHC.Stg.Utils import GHC.Core.Type import GHC.Builtin.Types.Prim (intPrimTy) import GHC.Builtin.Types import GHC.Types.Unique.Supply+import GHC.Types.Unique import GHC.Utils.Misc import GHC.Types.Var.Env+import GHC.Types.RepType  import Data.Bifunctor (second) import Data.Maybe (mapMaybe) import qualified Data.IntMap as IM+import GHC.Builtin.PrimOps+import GHC.Builtin.PrimOps.Casts+import Data.List (mapAccumL) +-- import GHC.Utils.Trace --------------------------------------------------------------------------------  -- | A mapping from binders to the Ids they were expanded/renamed to.@@ -306,8 +434,10 @@ -- INVARIANT: OutStgArgs in the range only have NvUnaryTypes --            (i.e. no unboxed tuples, sums or voids) ---type UnariseEnv = VarEnv UnariseVal+newtype UnariseEnv = UnariseEnv  { ue_rho :: (VarEnv UnariseVal) } +initUnariseEnv :: VarEnv UnariseVal -> UnariseEnv+initUnariseEnv = UnariseEnv data UnariseVal   = MultiVal [OutStgArg] -- MultiVal to tuple. Can be empty list (void).   | UnaryVal OutStgArg   -- See NOTE [Renaming during unarisation].@@ -320,25 +450,27 @@ -- The id is mapped to one or more things. -- See Note [UnariseEnv] extendRho :: UnariseEnv -> Id -> UnariseVal -> UnariseEnv-extendRho rho x (MultiVal args)+extendRho env x (MultiVal args)   = assert (all (isNvUnaryType . stgArgType) args)-    extendVarEnv rho x (MultiVal args)-extendRho rho x (UnaryVal val)+    env { ue_rho = extendVarEnv (ue_rho env) x (MultiVal args) }+extendRho env x (UnaryVal val)   = assert (isNvUnaryType (stgArgType val))-    extendVarEnv rho x (UnaryVal val)+    env { ue_rho = extendVarEnv (ue_rho env) x (UnaryVal val) } -- Properly shadow things from an outer scope. -- See Note [UnariseEnv]  -- The id stands for itself so we don't record a mapping. -- See Note [UnariseEnv] extendRhoWithoutValue :: UnariseEnv -> Id -> UnariseEnv-extendRhoWithoutValue rho x = delVarEnv rho x+extendRhoWithoutValue env x = env { ue_rho = delVarEnv (ue_rho env) x } +lookupRho :: UnariseEnv -> Id -> Maybe UnariseVal+lookupRho env v = lookupVarEnv (ue_rho env) v  --------------------------------------------------------------------------------  unarise :: UniqSupply -> [StgTopBinding] -> [StgTopBinding]-unarise us binds = initUs_ us (mapM (unariseTopBinding emptyVarEnv) binds)+unarise us binds = initUs_ us (mapM (unariseTopBinding (initUnariseEnv emptyVarEnv)) binds)  unariseTopBinding :: UnariseEnv -> StgTopBinding -> UniqSM StgTopBinding unariseTopBinding rho (StgTopLifted bind)@@ -366,7 +498,7 @@ unariseExpr :: UnariseEnv -> StgExpr -> UniqSM StgExpr  unariseExpr rho e@(StgApp f [])-  = case lookupVarEnv rho f of+  = case lookupRho rho f of       Just (MultiVal args)  -- Including empty tuples         -> return (mkTuple args)       Just (UnaryVal (StgVarArg f'))@@ -379,7 +511,7 @@ unariseExpr rho e@(StgApp f args)   = return (StgApp f' (unariseFunArgs rho args))   where-    f' = case lookupVarEnv rho f of+    f' = case lookupRho rho f of            Just (UnaryVal (StgVarArg f')) -> f'            Nothing -> f            err -> pprPanic "unariseExpr - app2" (pprStgExpr panicStgPprOpts e $$ ppr err)@@ -390,12 +522,17 @@   = return (StgLit l)  unariseExpr rho (StgConApp dc n args ty_args)-  | Just args' <- unariseMulti_maybe rho dc args ty_args-  = return (mkTuple args')--  | otherwise-  , let args' = unariseConArgs rho args-  = return (StgConApp dc n args' (map stgArgType args'))+  | isUnboxedSumDataCon dc || isUnboxedTupleDataCon dc+  = do+      us <- getUniqueSupplyM+      case unariseUbxSumOrTupleArgs rho us dc args ty_args of+        (args', Just cast_wrapper)+          -> return $ cast_wrapper (mkTuple args')+        (args', Nothing)+          -> return $ (mkTuple args')+  | otherwise =+      let args' = unariseConArgs rho args in+      return $ (StgConApp dc n args' (map stgArgType args'))  unariseExpr rho (StgOpApp op args ty)   = return (StgOpApp op (unariseFunArgs rho args) ty)@@ -403,15 +540,19 @@ unariseExpr rho (StgCase scrut bndr alt_ty alts)   -- tuple/sum binders in the scrutinee can always be eliminated   | StgApp v [] <- scrut-  , Just (MultiVal xs) <- lookupVarEnv rho v+  , Just (MultiVal xs) <- lookupRho rho v   = elimCase rho xs bndr alt_ty alts    -- Handle strict lets for tuples and sums:   --   case (# a,b #) of r -> rhs   -- and analogously for sums   | StgConApp dc _n args ty_args <- scrut-  , Just args' <- unariseMulti_maybe rho dc args ty_args-  = elimCase rho args' bndr alt_ty alts+  , isUnboxedSumDataCon dc || isUnboxedTupleDataCon dc+  = do+    us <- getUniqueSupplyM+    case unariseUbxSumOrTupleArgs rho us dc args ty_args of+      (args',Just wrapper) -> wrapper <$> elimCase rho args' bndr alt_ty alts+      (args',Nothing) -> elimCase rho args' bndr alt_ty alts    -- See (3) of Note [Rubbish literals] in GHC.Types.Literal   | StgLit lit <- scrut@@ -436,17 +577,21 @@   = StgTick tick <$> unariseExpr rho e  -- Doesn't return void args.-unariseMulti_maybe :: UnariseEnv -> DataCon -> [InStgArg] -> [Type] -> Maybe [OutStgArg]-unariseMulti_maybe rho dc args ty_args+unariseUbxSumOrTupleArgs :: UnariseEnv -> UniqSupply -> DataCon -> [InStgArg] -> [Type]+                   -> ( [OutStgArg]           -- Arguments representing the unboxed sum+                      , Maybe (StgExpr -> StgExpr)) -- Transformation to apply to the arguments, to bring them+                                                    -- into the right Rep+unariseUbxSumOrTupleArgs rho us dc args ty_args   | isUnboxedTupleDataCon dc-  = Just (unariseConArgs rho args)+  = (unariseConArgs rho args, Nothing)    | isUnboxedSumDataCon dc   , let args1 = assert (isSingleton args) (unariseConArgs rho args)-  = Just (mkUbxSum dc ty_args args1)+  = let (args2, cast_wrapper) = mkUbxSum dc ty_args args1 us+    in (args2, Just cast_wrapper)    | otherwise-  = Nothing+  = panic "unariseUbxSumOrTupleArgs: Constructor not a unboxed sum or tuple"  -- Doesn't return void args. unariseRubbish_maybe :: Literal -> Maybe [OutStgArg]@@ -473,15 +618,19 @@                                                  , alt_bndrs = bndrs                                                  , alt_rhs   = rhs}]   = do let rho1 = extendRho rho bndr (MultiVal args)-           rho2+       (rho2, rhs') <- case () of+           _              | isUnboxedTupleBndr bndr-             = mapTupleIdBinders bndrs args rho1+             -> return (mapTupleIdBinders bndrs args rho1, rhs)              | otherwise-             = assert (isUnboxedSumBndr bndr) $-               if null bndrs then rho1-                             else mapSumIdBinders bndrs args rho1+             -> assert (isUnboxedSumBndr bndr) $+               case bndrs of+                -- Sum with a void-type binder?+                [] -> return (rho1, rhs)+                [alt_bndr] -> mapSumIdBinders alt_bndr args rhs rho1+                _ -> pprPanic "mapSumIdBinders" (ppr bndrs $$ ppr args) -       unariseExpr rho2 rhs+       unariseExpr rho2 rhs'  elimCase rho args bndr (MultiValAlt _) alts   | isUnboxedSumBndr bndr@@ -572,18 +721,23 @@ unariseSumAlt rho _ GenStgAlt{alt_con=DEFAULT,alt_bndrs=_,alt_rhs=e}   = GenStgAlt DEFAULT mempty <$> unariseExpr rho e -unariseSumAlt rho args GenStgAlt{ alt_con   = DataAlt sumCon+unariseSumAlt rho args alt@GenStgAlt{ alt_con   = DataAlt sumCon                                 , alt_bndrs = bs                                 , alt_rhs   = e                                 }-  = do let rho'     = mapSumIdBinders bs args rho-           lit_case = LitAlt (LitNumber LitNumInt (fromIntegral (dataConTag sumCon)))-       GenStgAlt lit_case mempty <$> unariseExpr rho' e +  = do (rho',e') <- case bs of+              [b] -> mapSumIdBinders b args e rho+              -- Sums must have one binder+              _ -> pprPanic "unariseSumAlt2" (ppr args $$ pprPanicAlt alt)+       let lit_case   = LitAlt (LitNumber LitNumInt (fromIntegral (dataConTag sumCon)))+       GenStgAlt lit_case mempty <$> unariseExpr rho' e'+ unariseSumAlt _ scrt alt-  = pprPanic "unariseSumAlt" (ppr scrt $$ pprPanicAlt alt)+  = pprPanic "unariseSumAlt3" (ppr scrt $$ pprPanicAlt alt)  --------------------------------------------------------------------------------+-- Mapping binders when matching und a unboxed sum/tuple  mapTupleIdBinders   :: [InId]       -- Un-processed binders of a tuple alternative.@@ -619,28 +773,91 @@       map_ids rho0 ids_unarised args0  mapSumIdBinders-  :: [InId]      -- Binder of a sum alternative (remember that sum patterns-                 -- only have one binder, so this list should be a singleton)+  :: InId        -- Binder (in the case alternative).   -> [OutStgArg] -- Arguments that form the sum (NOT including the tag).                  -- Can't have void args.-  -> UnariseEnv+  -> InStgExpr   -> UnariseEnv+  -> UniqSM (UnariseEnv, OutStgExpr) -mapSumIdBinders [id] args rho0-  = assert (not (any (isZeroBitTy . stgArgType) args)) $+mapSumIdBinders alt_bndr args rhs rho0+  = assert (not (any (isZeroBitTy . stgArgType) args)) $ do+    uss <- listSplitUniqSupply <$> getUniqueSupplyM     let+      fld_reps = typePrimRep (idType alt_bndr)++      -- Slots representing the whole sum       arg_slots = map primRepSlot $ concatMap (typePrimRep . stgArgType) args-      id_slots  = map primRepSlot $ typePrimRep (idType id)+      -- The slots representing the field of the sum we bind.+      id_slots  = map primRepSlot $ fld_reps       layout1   = layoutUbxSum arg_slots id_slots-    in-      if isMultiValBndr id-        then extendRho rho0 id (MultiVal [ args !! i | i <- layout1 ])-        else assert (layout1 `lengthIs` 1)-             extendRho rho0 id (UnaryVal (args !! head layout1)) -mapSumIdBinders ids sum_args _-  = pprPanic "mapSumIdBinders" (ppr ids $$ ppr sum_args)+      -- See Note [Casting slot arguments]+      -- Most of the code here is just to make sure our binders are of the+      -- right type.+      -- Select only the args which contain parts of the current field.+      id_arg_exprs   = [ args !! i | i <- layout1 ]+      id_vars   = [v | StgVarArg v <- id_arg_exprs]+      -- Output types for the field binders based on their rep+      id_tys    = map primRepToType fld_reps +      typed_id_arg_input = assert (equalLength id_vars id_tys) $+                           zip3 id_vars id_tys uss++      mkCastInput :: (Id,Type,UniqSupply) -> ([(PrimOp,Type,Unique)],Id,Id)+      mkCastInput (id,tar_type,bndr_us) =+        let (ops,types) = unzip $ getCasts (typePrimRep1 $ idType id) (typePrimRep1 tar_type)+            cst_opts = zip3 ops types $ uniqsFromSupply bndr_us+            out_id = case cst_opts of+              [] -> id+              _ ->  let (_,ty,uq) = last cst_opts+                    in mkCastVar uq ty+        in (cst_opts,id,out_id)++      cast_inputs = map mkCastInput typed_id_arg_input+      (rhs_with_casts,typed_ids) = mapAccumL cast_arg (\x->x) cast_inputs+        where+          cast_arg rhs_in (cast_ops,in_id,out_id) =+            let rhs_out = castArgRename cast_ops (StgVarArg in_id)+            in (rhs_in . rhs_out, out_id)++      typed_id_args = map StgVarArg typed_ids++      -- pprTrace "mapSumIdBinders"+      --           (text "id_tys" <+> ppr id_tys $$+      --           text "id_args" <+> ppr id_arg_exprs $$+      --           text "rhs" <+> ppr rhs $$+      --           text "rhs_with_casts" <+> ppr rhs_with_casts+      --           ) $+    if isMultiValBndr alt_bndr+      then return (extendRho rho0 alt_bndr (MultiVal typed_id_args), rhs_with_casts rhs)+      else assert (typed_id_args `lengthIs` 1) $+            return (extendRho rho0 alt_bndr (UnaryVal (head typed_id_args)), rhs_with_casts rhs)++-- Convert the argument to the given type, and wrap the conversion+-- around the given expression. Use the given Id as a name for the+-- converted value.+castArgRename :: [(PrimOp,Type,Unique)] -> StgArg -> StgExpr -> StgExpr+castArgRename ops in_arg rhs =+  case ops of+    [] -> rhs+    ((op,ty,uq):rest_ops) ->+      let out_id' = mkCastVar uq ty -- out_name `setIdUnique` uq `setIdType` ty+          sub_cast = castArgRename rest_ops (StgVarArg out_id')+      in mkCast in_arg op out_id' ty $ sub_cast rhs++-- Construct a case binder used when casting sums, of a given type and unique.+mkCastVar :: Unique -> Type -> Id+mkCastVar uq ty = mkSysLocal (fsLit "cst_sum") uq Many ty++mkCast :: StgArg -> PrimOp -> OutId -> Type -> StgExpr -> StgExpr+mkCast arg_in cast_op out_id out_ty in_rhs =+  let r2 = typePrimRep1 out_ty+      scrut = StgOpApp (StgPrimOp cast_op) [arg_in] out_ty+      alt = GenStgAlt { alt_con = DEFAULT, alt_bndrs = [], alt_rhs = in_rhs}+      alt_ty = PrimAlt r2+  in (StgCase scrut out_id alt_ty [alt])+ -- | Build a unboxed sum term from arguments of an alternative. -- -- Example, for (# x | #) :: (# (# #) | Int #) we call@@ -652,31 +869,72 @@ --   [ 1#, rubbish ] -- mkUbxSum-  :: DataCon      -- Sum data con+  :: HasDebugCallStack+  => DataCon      -- Sum data con   -> [Type]       -- Type arguments of the sum data con   -> [OutStgArg]  -- Actual arguments of the alternative.-  -> [OutStgArg]  -- Final tuple arguments-mkUbxSum dc ty_args args0+  -> UniqSupply+  -> ([OutStgArg] -- Final tuple arguments+     ,(StgExpr->StgExpr) -- We might need to cast the args first+     )+mkUbxSum dc ty_args args0 us   = let       (_ : sum_slots) = ubxSumRepType (map typePrimRep ty_args)-        -- drop tag slot-+      -- drop tag slot+      field_slots = (mapMaybe (typeSlotTy . stgArgType) args0)       tag = dataConTag dc+      layout'  = layoutUbxSum sum_slots field_slots -      layout'  = layoutUbxSum sum_slots (mapMaybe (typeSlotTy . stgArgType) args0)       tag_arg  = StgLitArg (LitNumber LitNumInt (fromIntegral tag))       arg_idxs = IM.fromList (zipEqual "mkUbxSum" layout' args0) -      mkTupArgs :: Int -> [SlotTy] -> IM.IntMap StgArg -> [StgArg]-      mkTupArgs _ [] _-        = []-      mkTupArgs arg_idx (slot : slots_left) arg_map-        | Just stg_arg <- IM.lookup arg_idx arg_map-        = stg_arg : mkTupArgs (arg_idx + 1) slots_left arg_map-        | otherwise-        = ubxSumRubbishArg slot : mkTupArgs (arg_idx + 1) slots_left arg_map+      ((_idx,_idx_map,_us,wrapper),slot_args)+        = assert (length arg_idxs <= length sum_slots ) $+          mapAccumL mkTupArg (0,arg_idxs,us,id) sum_slots++      mkTupArg  :: (Int, IM.IntMap StgArg,UniqSupply,StgExpr->StgExpr)+                -> SlotTy+                -> ((Int,IM.IntMap StgArg,UniqSupply,StgExpr->StgExpr), StgArg)+      mkTupArg (arg_idx, arg_map, us, wrapper) slot+         | Just stg_arg <- IM.lookup arg_idx arg_map+         =  case castArg us slot stg_arg of+              -- Slot and arg type missmatched, do a cast+              Just (casted_arg,us',wrapper') ->+                ( (arg_idx+1, arg_map, us', wrapper . wrapper')+                , casted_arg)+              -- Use the arg as-is+              Nothing ->+                ( (arg_idx+1, arg_map, us, wrapper)+                , stg_arg)+         -- Garbage slot, fill with rubbish+         | otherwise+         =  ( (arg_idx+1, arg_map, us, wrapper)+            , ubxSumRubbishArg slot)++      castArg :: UniqSupply -> SlotTy -> StgArg -> Maybe (StgArg,UniqSupply,StgExpr -> StgExpr)+      castArg us slot_ty arg+        -- Cast the argument to the type of the slot if required+        | slotPrimRep slot_ty /= typePrimRep1 (stgArgType arg)+        , out_ty <- primRepToType $ slotPrimRep slot_ty+        , (ops,types) <- unzip $ getCasts (typePrimRep1 $ stgArgType arg) $ typePrimRep1 out_ty+        , not . null $ ops+        = let (us1,us2) = splitUniqSupply us+              cast_uqs = uniqsFromSupply us1+              cast_opts = zip3 ops types cast_uqs+              (_op,out_ty,out_uq) = last cast_opts+              casts = castArgRename cast_opts arg :: StgExpr -> StgExpr+          in Just (StgVarArg (mkCastVar out_uq out_ty),us2,casts)+        -- No need for casting+        | otherwise = Nothing++      tup_args = tag_arg : slot_args     in-      tag_arg : mkTupArgs 0 sum_slots arg_idxs+      -- pprTrace "mkUbxSum" (+      --   text "ty_args (slots)" <+> ppr ty_args $$+      --   text "args0" <+> ppr args0 $$+      --   text "wrapper" <+>+      --       (ppr $ wrapper $ StgLit $ LitChar '_'))+      (tup_args, wrapper)   -- | Return a rubbish value for the given slot type.@@ -694,6 +952,8 @@ ubxSumRubbishArg Word64Slot = StgLitArg (LitNumber LitNumWord64 0) ubxSumRubbishArg FloatSlot  = StgLitArg (LitFloat 0) ubxSumRubbishArg DoubleSlot = StgLitArg (LitDouble 0)+ubxSumRubbishArg (VecSlot n e) = StgLitArg (LitRubbish vec_rep)+  where vec_rep = primRepToRuntimeRep (VecRep n e)  -------------------------------------------------------------------------------- @@ -787,7 +1047,7 @@ -- | MultiVal a function argument. Never returns an empty list. unariseFunArg :: UnariseEnv -> StgArg -> [StgArg] unariseFunArg rho (StgVarArg x) =-  case lookupVarEnv rho x of+  case lookupRho rho x of     Just (MultiVal [])  -> [voidArg]   -- NB: do not remove void args     Just (MultiVal as)  -> as     Just (UnaryVal arg) -> [arg]@@ -809,7 +1069,7 @@ -- | MultiVal a DataCon argument. Returns an empty list when argument is void. unariseConArg :: UnariseEnv -> InStgArg -> [OutStgArg] unariseConArg rho (StgVarArg x) =-  case lookupVarEnv rho x of+  case lookupRho rho x of     Just (UnaryVal arg) -> [arg]     Just (MultiVal as) -> as      -- 'as' can be empty     Nothing
compiler/GHC/StgToCmm/ExtCode.hs view
@@ -231,8 +231,12 @@ emitAssign :: CmmReg  -> CmmExpr -> CmmParse () emitAssign l r = code (F.emitAssign l r) -emitStore :: CmmExpr  -> CmmExpr -> CmmParse ()-emitStore l r = code (F.emitStore l r)+emitStore :: Maybe MemoryOrdering -> CmmExpr  -> CmmExpr -> CmmParse ()+emitStore (Just mem_ord) l r = do+  platform <- getPlatform+  let w = typeWidth $ cmmExprType platform r+  emit $ mkUnsafeCall (PrimTarget $ MO_AtomicWrite w mem_ord) [] [l,r]+emitStore Nothing l r = code (F.emitStore l r)  getCode :: CmmParse a -> CmmParse CmmAGraph getCode (EC ec) = EC $ \c e s -> do
compiler/GHC/StgToCmm/Prim.hs view
@@ -283,9 +283,10 @@     emitAssign (CmmLocal res) currentTSOExpr    ReadMutVarOp -> \[mutv] -> opIntoRegs $ \[res] ->-    emitAssign (CmmLocal res) (cmmLoadIndexW platform mutv (fixedHdrSizeW profile) (gcWord platform))+    emitPrimCall [res] (MO_AtomicRead (wordWidth platform) MemOrderAcquire)+        [ cmmOffsetW platform mutv (fixedHdrSizeW profile) ] -  WriteMutVarOp -> \[mutv, var] -> opIntoRegs $ \res@[] -> do+  WriteMutVarOp -> \[mutv, var] -> opIntoRegs $ \[] -> do     old_val <- CmmLocal <$> newTemp (cmmExprType platform var)     emitAssign old_val (cmmLoadIndexW platform mutv (fixedHdrSizeW profile) (gcWord platform)) @@ -294,8 +295,8 @@     -- Note that this also must come after we read the old value to ensure     -- that the read of old_val comes before another core's write to the     -- MutVar's value.-    emitPrimCall res MO_WriteBarrier []-    emitStore (cmmOffsetW platform mutv (fixedHdrSizeW profile)) var+    emitPrimCall [] (MO_AtomicWrite (wordWidth platform) MemOrderRelease)+        [ cmmOffsetW platform mutv (fixedHdrSizeW profile), var ]      platform <- getPlatform     mkdirtyMutVarCCall <- getCode $! emitCCall@@ -853,7 +854,7 @@ -- SIMD primops   (VecBroadcastOp vcat n w) -> \[e] -> opIntoRegs $ \[res] -> do     checkVecCompatibility cfg vcat n w-    doVecPackOp (vecElemInjectCast platform vcat w) ty zeros (replicate n e) res+    doVecPackOp ty zeros (replicate n e) res    where     zeros :: CmmExpr     zeros = CmmLit $ CmmVec (replicate n zero)@@ -871,7 +872,7 @@     checkVecCompatibility cfg vcat n w     when (es `lengthIsNot` n) $         panic "emitPrimOp: VecPackOp has wrong number of arguments"-    doVecPackOp (vecElemInjectCast platform vcat w) ty zeros es res+    doVecPackOp ty zeros es res    where     zeros :: CmmExpr     zeros = CmmLit $ CmmVec (replicate n zero)@@ -889,14 +890,14 @@     checkVecCompatibility cfg vcat n w     when (res `lengthIsNot` n) $         panic "emitPrimOp: VecUnpackOp has wrong number of results"-    doVecUnpackOp (vecElemProjectCast platform vcat w) ty arg res+    doVecUnpackOp ty arg res    where     ty :: CmmType     ty = vecVmmType vcat n w    (VecInsertOp vcat n w) -> \[v,e,i] -> opIntoRegs $ \[res] -> do     checkVecCompatibility cfg vcat n w-    doVecInsertOp (vecElemInjectCast platform vcat w) ty v e i res+    doVecInsertOp ty v e i res    where     ty :: CmmType     ty = vecVmmType vcat n w@@ -2247,32 +2248,8 @@ vecCmmCat WordVec  = cmmBits vecCmmCat FloatVec = cmmFloat -vecElemInjectCast :: Platform -> PrimOpVecCat -> Width -> Maybe MachOp-vecElemInjectCast _        FloatVec _   =  Nothing-vecElemInjectCast platform   IntVec   W8  =  Just (mo_WordTo8  platform)-vecElemInjectCast platform   IntVec   W16 =  Just (mo_WordTo16 platform)-vecElemInjectCast platform   IntVec   W32 =  Just (mo_WordTo32 platform)-vecElemInjectCast _        IntVec   W64 =  Nothing-vecElemInjectCast platform   WordVec  W8  =  Just (mo_WordTo8  platform)-vecElemInjectCast platform   WordVec  W16 =  Just (mo_WordTo16 platform)-vecElemInjectCast platform   WordVec  W32 =  Just (mo_WordTo32 platform)-vecElemInjectCast _        WordVec  W64 =  Nothing-vecElemInjectCast _        _        _   =  Nothing--vecElemProjectCast :: Platform -> PrimOpVecCat -> Width -> Maybe MachOp-vecElemProjectCast _        FloatVec _   =  Nothing-vecElemProjectCast platform   IntVec   W8  =  Just (mo_s_8ToWord  platform)-vecElemProjectCast platform   IntVec   W16 =  Just (mo_s_16ToWord platform)-vecElemProjectCast platform   IntVec   W32 =  Just (mo_s_32ToWord platform)-vecElemProjectCast _        IntVec   W64 =  Nothing-vecElemProjectCast platform   WordVec  W8  =  Just (mo_u_8ToWord  platform)-vecElemProjectCast platform   WordVec  W16 =  Just (mo_u_16ToWord platform)-vecElemProjectCast platform   WordVec  W32 =  Just (mo_u_32ToWord platform)-vecElemProjectCast _        WordVec  W64 =  Nothing-vecElemProjectCast _        _        _   =  Nothing----- NOTE [SIMD Design for the future]+-- Note [SIMD Design for the future]+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- Check to make sure that we can generate code for the specified vector type -- given the current set of dynamic flags. -- Currently these checks are specific to x86 and x86_64 architecture.@@ -2333,13 +2310,12 @@ ------------------------------------------------------------------------------ -- Helpers for translating vector packing and unpacking. -doVecPackOp :: Maybe MachOp  -- Cast from element to vector component-            -> CmmType       -- Type of vector+doVecPackOp :: CmmType       -- Type of vector             -> CmmExpr       -- Initial vector             -> [CmmExpr]     -- Elements             -> CmmFormal     -- Destination for result             -> FCode ()-doVecPackOp maybe_pre_write_cast ty z es res = do+doVecPackOp ty z es res = do     dst <- newTemp ty     emitAssign (CmmLocal dst) z     vecPack dst es 0@@ -2352,31 +2328,25 @@         dst <- newTemp ty         if isFloatType (vecElemType ty)           then emitAssign (CmmLocal dst) (CmmMachOp (MO_VF_Insert len wid)-                                                    [CmmReg (CmmLocal src), cast e, iLit])+                                                    [CmmReg (CmmLocal src), e, iLit])           else emitAssign (CmmLocal dst) (CmmMachOp (MO_V_Insert len wid)-                                                    [CmmReg (CmmLocal src), cast e, iLit])+                                                    [CmmReg (CmmLocal src), e, iLit])         vecPack dst es (i + 1)       where         -- vector indices are always 32-bits         iLit = CmmLit (CmmInt (toInteger i) W32) -    cast :: CmmExpr -> CmmExpr-    cast val = case maybe_pre_write_cast of-                 Nothing   -> val-                 Just cast -> CmmMachOp cast [val]-     len :: Length     len = vecLength ty      wid :: Width     wid = typeWidth (vecElemType ty) -doVecUnpackOp :: Maybe MachOp  -- Cast from vector component to element result-              -> CmmType       -- Type of vector+doVecUnpackOp :: CmmType       -- Type of vector               -> CmmExpr       -- Vector               -> [CmmFormal]   -- Element results               -> FCode ()-doVecUnpackOp maybe_post_read_cast ty e res =+doVecUnpackOp ty e res =     vecUnpack res 0   where     vecUnpack :: [CmmFormal] -> Int -> FCode ()@@ -2385,46 +2355,36 @@      vecUnpack (r : rs) i = do         if isFloatType (vecElemType ty)-          then emitAssign (CmmLocal r) (cast (CmmMachOp (MO_VF_Extract len wid)-                                             [e, iLit]))-          else emitAssign (CmmLocal r) (cast (CmmMachOp (MO_V_Extract len wid)-                                             [e, iLit]))+          then emitAssign (CmmLocal r) (CmmMachOp (MO_VF_Extract len wid)+                                             [e, iLit])+          else emitAssign (CmmLocal r) (CmmMachOp (MO_V_Extract len wid)+                                             [e, iLit])         vecUnpack rs (i + 1)       where         -- vector indices are always 32-bits         iLit = CmmLit (CmmInt (toInteger i) W32) -    cast :: CmmExpr -> CmmExpr-    cast val = case maybe_post_read_cast of-                 Nothing   -> val-                 Just cast -> CmmMachOp cast [val]-     len :: Length     len = vecLength ty      wid :: Width     wid = typeWidth (vecElemType ty) -doVecInsertOp :: Maybe MachOp  -- Cast from element to vector component-              -> CmmType       -- Vector type+doVecInsertOp :: CmmType       -- Vector type               -> CmmExpr       -- Source vector               -> CmmExpr       -- Element               -> CmmExpr       -- Index at which to insert element               -> CmmFormal     -- Destination for result               -> FCode ()-doVecInsertOp maybe_pre_write_cast ty src e idx res = do+doVecInsertOp ty src e idx res = do     platform <- getPlatform     -- vector indices are always 32-bits     let idx' :: CmmExpr         idx' = CmmMachOp (MO_SS_Conv (wordWidth platform) W32) [idx]     if isFloatType (vecElemType ty)-      then emitAssign (CmmLocal res) (CmmMachOp (MO_VF_Insert len wid) [src, cast e, idx'])-      else emitAssign (CmmLocal res) (CmmMachOp (MO_V_Insert len wid) [src, cast e, idx'])+      then emitAssign (CmmLocal res) (CmmMachOp (MO_VF_Insert len wid) [src, e, idx'])+      else emitAssign (CmmLocal res) (CmmMachOp (MO_V_Insert len wid) [src, e, idx'])   where-    cast :: CmmExpr -> CmmExpr-    cast val = case maybe_pre_write_cast of-                 Nothing   -> val-                 Just cast -> CmmMachOp cast [val]      len :: Length     len = vecLength ty@@ -3081,7 +3041,7 @@ doAtomicReadAddr res addr ty =     emitPrimCall         [ res ]-        (MO_AtomicRead (typeWidth ty))+        (MO_AtomicRead (typeWidth ty) MemOrderSeqCst)         [ addr ]  -- | Emit an atomic write to a byte array that acts as a memory barrier.@@ -3109,7 +3069,7 @@ doAtomicWriteAddr addr ty val =     emitPrimCall         [ {- no results -} ]-        (MO_AtomicWrite (typeWidth ty))+        (MO_AtomicWrite (typeWidth ty) MemOrderSeqCst)         [ addr, val ]  doCasByteArray
compiler/GHC/SysTools/Process.hs view
@@ -170,11 +170,7 @@     getResponseFile args = do       fp <- newTempName logger tmpfs (tmpDir dflags) TFL_CurrentModule "rsp"       withFile fp WriteMode $ \h -> do-#if defined(mingw32_HOST_OS)-          hSetEncoding h latin1-#else           hSetEncoding h utf8-#endif           hPutStr h $ unlines $ map escape args       return fp 
compiler/GHC/Tc/Instance/Typeable.hs view
@@ -172,7 +172,7 @@        } } }   where     needs_typeable_binds tc-      | tc `elem` [runtimeRepTyCon, levityTyCon, vecCountTyCon, vecElemTyCon]+      | tc `elem` ghcTypesTypeableTyCons       = False       | otherwise =           isAlgTyCon tc@@ -333,7 +333,14 @@                      -- Build TypeRepTodos for types in GHC.Prim                    ; todo2 <- todoForTyCons gHC_PRIM ghc_prim_module_id                                             ghcPrimTypeableTyCons-                   ; return ( gbl_env' , [todo1, todo2])+                   ; tcg_env <- getGblEnv+                   ; let mod_id = case tcg_tr_module tcg_env of  -- Should be set by now+                                   Just mod_id -> mod_id+                                   Nothing     -> pprPanic "tcMkTypeableBinds" empty++                   ; todo3 <- todoForTyCons gHC_TYPES mod_id ghcTypesTypeableTyCons++                   ; return ( gbl_env' , [todo1, todo2, todo3])                    }            else do gbl_env <- getGblEnv                    return (gbl_env, [])@@ -348,11 +355,17 @@ -- Note [Built-in syntax and the OrigNameCache] in "GHC.Iface.Env" for more. ghcPrimTypeableTyCons :: [TyCon] ghcPrimTypeableTyCons = concat-    [ [ runtimeRepTyCon, levityTyCon, vecCountTyCon, vecElemTyCon ]-    , map (tupleTyCon Unboxed) [0..mAX_TUPLE_SIZE]+    [ map (tupleTyCon Unboxed) [0..mAX_TUPLE_SIZE]     , map sumTyCon [2..mAX_SUM_SIZE]     , primTyCons     ]++-- | These are types which are defined in GHC.Types but are needed in order to+-- typecheck the other generated bindings, therefore to avoid ordering issues we+-- generate them up-front along with the bindings from GHC.Prim.+ghcTypesTypeableTyCons :: [TyCon]+ghcTypesTypeableTyCons = [ runtimeRepTyCon, levityTyCon+                         , vecCountTyCon, vecElemTyCon ]  data TypeableStuff     = Stuff { platform       :: Platform        -- ^ Target platform
compiler/GHC/Unit/Finder.hs view
@@ -136,13 +136,13 @@ -- that package is searched for the module.  findImportedModule :: HscEnv -> ModuleName -> PkgQual -> IO FindResult-findImportedModule hsc_env mod fs =+findImportedModule hsc_env mod pkg_qual =   let fc        = hsc_FC hsc_env       mhome_unit = hsc_home_unit_maybe hsc_env       dflags    = hsc_dflags hsc_env       fopts     = initFinderOpts dflags   in do-    findImportedModuleNoHsc fc fopts (hsc_unit_env hsc_env) mhome_unit mod fs+    findImportedModuleNoHsc fc fopts (hsc_unit_env hsc_env) mhome_unit mod pkg_qual  findImportedModuleNoHsc   :: FinderCache
ghc-lib.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.0 build-type: Simple name: ghc-lib-version: 9.4.3.20221104+version: 9.4.4.20221225 license: BSD3 license-file: LICENSE category: Development@@ -83,7 +83,7 @@         stm,         rts,         hpc == 0.6.*,-        ghc-lib-parser == 9.4.3.20221104+        ghc-lib-parser == 9.4.4.20221225     build-tool-depends: alex:alex >= 3.1, happy:happy >= 1.19.4     other-extensions:         BangPatterns@@ -477,6 +477,7 @@         Paths_ghc_lib         GHC         GHC.Builtin.Names.TH+        GHC.Builtin.PrimOps.Casts         GHC.Builtin.Types.Literals         GHC.Builtin.Utils         GHC.ByteCode.Asm
ghc-lib/stage0/compiler/build/primop-primop-info.hs-incl view
@@ -656,16 +656,16 @@ primOpInfo (VecBroadcastOp IntVec 32 W16) = mkGenPrimOp (fsLit "broadcastInt16X32#")  [] [int16PrimTy] (int16X32PrimTy) primOpInfo (VecBroadcastOp IntVec 16 W32) = mkGenPrimOp (fsLit "broadcastInt32X16#")  [] [int32PrimTy] (int32X16PrimTy) primOpInfo (VecBroadcastOp IntVec 8 W64) = mkGenPrimOp (fsLit "broadcastInt64X8#")  [] [int64PrimTy] (int64X8PrimTy)-primOpInfo (VecBroadcastOp WordVec 16 W8) = mkGenPrimOp (fsLit "broadcastWord8X16#")  [] [wordPrimTy] (word8X16PrimTy)-primOpInfo (VecBroadcastOp WordVec 8 W16) = mkGenPrimOp (fsLit "broadcastWord16X8#")  [] [wordPrimTy] (word16X8PrimTy)+primOpInfo (VecBroadcastOp WordVec 16 W8) = mkGenPrimOp (fsLit "broadcastWord8X16#")  [] [word8PrimTy] (word8X16PrimTy)+primOpInfo (VecBroadcastOp WordVec 8 W16) = mkGenPrimOp (fsLit "broadcastWord16X8#")  [] [word16PrimTy] (word16X8PrimTy) primOpInfo (VecBroadcastOp WordVec 4 W32) = mkGenPrimOp (fsLit "broadcastWord32X4#")  [] [word32PrimTy] (word32X4PrimTy) primOpInfo (VecBroadcastOp WordVec 2 W64) = mkGenPrimOp (fsLit "broadcastWord64X2#")  [] [word64PrimTy] (word64X2PrimTy)-primOpInfo (VecBroadcastOp WordVec 32 W8) = mkGenPrimOp (fsLit "broadcastWord8X32#")  [] [wordPrimTy] (word8X32PrimTy)-primOpInfo (VecBroadcastOp WordVec 16 W16) = mkGenPrimOp (fsLit "broadcastWord16X16#")  [] [wordPrimTy] (word16X16PrimTy)+primOpInfo (VecBroadcastOp WordVec 32 W8) = mkGenPrimOp (fsLit "broadcastWord8X32#")  [] [word8PrimTy] (word8X32PrimTy)+primOpInfo (VecBroadcastOp WordVec 16 W16) = mkGenPrimOp (fsLit "broadcastWord16X16#")  [] [word16PrimTy] (word16X16PrimTy) primOpInfo (VecBroadcastOp WordVec 8 W32) = mkGenPrimOp (fsLit "broadcastWord32X8#")  [] [word32PrimTy] (word32X8PrimTy) primOpInfo (VecBroadcastOp WordVec 4 W64) = mkGenPrimOp (fsLit "broadcastWord64X4#")  [] [word64PrimTy] (word64X4PrimTy)-primOpInfo (VecBroadcastOp WordVec 64 W8) = mkGenPrimOp (fsLit "broadcastWord8X64#")  [] [wordPrimTy] (word8X64PrimTy)-primOpInfo (VecBroadcastOp WordVec 32 W16) = mkGenPrimOp (fsLit "broadcastWord16X32#")  [] [wordPrimTy] (word16X32PrimTy)+primOpInfo (VecBroadcastOp WordVec 64 W8) = mkGenPrimOp (fsLit "broadcastWord8X64#")  [] [word8PrimTy] (word8X64PrimTy)+primOpInfo (VecBroadcastOp WordVec 32 W16) = mkGenPrimOp (fsLit "broadcastWord16X32#")  [] [word16PrimTy] (word16X32PrimTy) primOpInfo (VecBroadcastOp WordVec 16 W32) = mkGenPrimOp (fsLit "broadcastWord32X16#")  [] [word32PrimTy] (word32X16PrimTy) primOpInfo (VecBroadcastOp WordVec 8 W64) = mkGenPrimOp (fsLit "broadcastWord64X8#")  [] [word64PrimTy] (word64X8PrimTy) primOpInfo (VecBroadcastOp FloatVec 4 W32) = mkGenPrimOp (fsLit "broadcastFloatX4#")  [] [floatPrimTy] (floatX4PrimTy)@@ -686,16 +686,16 @@ primOpInfo (VecPackOp IntVec 32 W16) = mkGenPrimOp (fsLit "packInt16X32#")  [] [(mkTupleTy Unboxed [int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy])] (int16X32PrimTy) primOpInfo (VecPackOp IntVec 16 W32) = mkGenPrimOp (fsLit "packInt32X16#")  [] [(mkTupleTy Unboxed [int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy])] (int32X16PrimTy) primOpInfo (VecPackOp IntVec 8 W64) = mkGenPrimOp (fsLit "packInt64X8#")  [] [(mkTupleTy Unboxed [int64PrimTy, int64PrimTy, int64PrimTy, int64PrimTy, int64PrimTy, int64PrimTy, int64PrimTy, int64PrimTy])] (int64X8PrimTy)-primOpInfo (VecPackOp WordVec 16 W8) = mkGenPrimOp (fsLit "packWord8X16#")  [] [(mkTupleTy Unboxed [wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy])] (word8X16PrimTy)-primOpInfo (VecPackOp WordVec 8 W16) = mkGenPrimOp (fsLit "packWord16X8#")  [] [(mkTupleTy Unboxed [wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy])] (word16X8PrimTy)+primOpInfo (VecPackOp WordVec 16 W8) = mkGenPrimOp (fsLit "packWord8X16#")  [] [(mkTupleTy Unboxed [word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy])] (word8X16PrimTy)+primOpInfo (VecPackOp WordVec 8 W16) = mkGenPrimOp (fsLit "packWord16X8#")  [] [(mkTupleTy Unboxed [word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy])] (word16X8PrimTy) primOpInfo (VecPackOp WordVec 4 W32) = mkGenPrimOp (fsLit "packWord32X4#")  [] [(mkTupleTy Unboxed [word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy])] (word32X4PrimTy) primOpInfo (VecPackOp WordVec 2 W64) = mkGenPrimOp (fsLit "packWord64X2#")  [] [(mkTupleTy Unboxed [word64PrimTy, word64PrimTy])] (word64X2PrimTy)-primOpInfo (VecPackOp WordVec 32 W8) = mkGenPrimOp (fsLit "packWord8X32#")  [] [(mkTupleTy Unboxed [wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy])] (word8X32PrimTy)-primOpInfo (VecPackOp WordVec 16 W16) = mkGenPrimOp (fsLit "packWord16X16#")  [] [(mkTupleTy Unboxed [wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy])] (word16X16PrimTy)+primOpInfo (VecPackOp WordVec 32 W8) = mkGenPrimOp (fsLit "packWord8X32#")  [] [(mkTupleTy Unboxed [word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy])] (word8X32PrimTy)+primOpInfo (VecPackOp WordVec 16 W16) = mkGenPrimOp (fsLit "packWord16X16#")  [] [(mkTupleTy Unboxed [word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy])] (word16X16PrimTy) primOpInfo (VecPackOp WordVec 8 W32) = mkGenPrimOp (fsLit "packWord32X8#")  [] [(mkTupleTy Unboxed [word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy])] (word32X8PrimTy) primOpInfo (VecPackOp WordVec 4 W64) = mkGenPrimOp (fsLit "packWord64X4#")  [] [(mkTupleTy Unboxed [word64PrimTy, word64PrimTy, word64PrimTy, word64PrimTy])] (word64X4PrimTy)-primOpInfo (VecPackOp WordVec 64 W8) = mkGenPrimOp (fsLit "packWord8X64#")  [] [(mkTupleTy Unboxed [wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy])] (word8X64PrimTy)-primOpInfo (VecPackOp WordVec 32 W16) = mkGenPrimOp (fsLit "packWord16X32#")  [] [(mkTupleTy Unboxed [wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy])] (word16X32PrimTy)+primOpInfo (VecPackOp WordVec 64 W8) = mkGenPrimOp (fsLit "packWord8X64#")  [] [(mkTupleTy Unboxed [word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy])] (word8X64PrimTy)+primOpInfo (VecPackOp WordVec 32 W16) = mkGenPrimOp (fsLit "packWord16X32#")  [] [(mkTupleTy Unboxed [word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy])] (word16X32PrimTy) primOpInfo (VecPackOp WordVec 16 W32) = mkGenPrimOp (fsLit "packWord32X16#")  [] [(mkTupleTy Unboxed [word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy])] (word32X16PrimTy) primOpInfo (VecPackOp WordVec 8 W64) = mkGenPrimOp (fsLit "packWord64X8#")  [] [(mkTupleTy Unboxed [word64PrimTy, word64PrimTy, word64PrimTy, word64PrimTy, word64PrimTy, word64PrimTy, word64PrimTy, word64PrimTy])] (word64X8PrimTy) primOpInfo (VecPackOp FloatVec 4 W32) = mkGenPrimOp (fsLit "packFloatX4#")  [] [(mkTupleTy Unboxed [floatPrimTy, floatPrimTy, floatPrimTy, floatPrimTy])] (floatX4PrimTy)@@ -716,16 +716,16 @@ primOpInfo (VecUnpackOp IntVec 32 W16) = mkGenPrimOp (fsLit "unpackInt16X32#")  [] [int16X32PrimTy] ((mkTupleTy Unboxed [int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy, int16PrimTy])) primOpInfo (VecUnpackOp IntVec 16 W32) = mkGenPrimOp (fsLit "unpackInt32X16#")  [] [int32X16PrimTy] ((mkTupleTy Unboxed [int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy, int32PrimTy])) primOpInfo (VecUnpackOp IntVec 8 W64) = mkGenPrimOp (fsLit "unpackInt64X8#")  [] [int64X8PrimTy] ((mkTupleTy Unboxed [int64PrimTy, int64PrimTy, int64PrimTy, int64PrimTy, int64PrimTy, int64PrimTy, int64PrimTy, int64PrimTy]))-primOpInfo (VecUnpackOp WordVec 16 W8) = mkGenPrimOp (fsLit "unpackWord8X16#")  [] [word8X16PrimTy] ((mkTupleTy Unboxed [wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy]))-primOpInfo (VecUnpackOp WordVec 8 W16) = mkGenPrimOp (fsLit "unpackWord16X8#")  [] [word16X8PrimTy] ((mkTupleTy Unboxed [wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy]))+primOpInfo (VecUnpackOp WordVec 16 W8) = mkGenPrimOp (fsLit "unpackWord8X16#")  [] [word8X16PrimTy] ((mkTupleTy Unboxed [word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy]))+primOpInfo (VecUnpackOp WordVec 8 W16) = mkGenPrimOp (fsLit "unpackWord16X8#")  [] [word16X8PrimTy] ((mkTupleTy Unboxed [word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy])) primOpInfo (VecUnpackOp WordVec 4 W32) = mkGenPrimOp (fsLit "unpackWord32X4#")  [] [word32X4PrimTy] ((mkTupleTy Unboxed [word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy])) primOpInfo (VecUnpackOp WordVec 2 W64) = mkGenPrimOp (fsLit "unpackWord64X2#")  [] [word64X2PrimTy] ((mkTupleTy Unboxed [word64PrimTy, word64PrimTy]))-primOpInfo (VecUnpackOp WordVec 32 W8) = mkGenPrimOp (fsLit "unpackWord8X32#")  [] [word8X32PrimTy] ((mkTupleTy Unboxed [wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy]))-primOpInfo (VecUnpackOp WordVec 16 W16) = mkGenPrimOp (fsLit "unpackWord16X16#")  [] [word16X16PrimTy] ((mkTupleTy Unboxed [wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy]))+primOpInfo (VecUnpackOp WordVec 32 W8) = mkGenPrimOp (fsLit "unpackWord8X32#")  [] [word8X32PrimTy] ((mkTupleTy Unboxed [word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy]))+primOpInfo (VecUnpackOp WordVec 16 W16) = mkGenPrimOp (fsLit "unpackWord16X16#")  [] [word16X16PrimTy] ((mkTupleTy Unboxed [word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy])) primOpInfo (VecUnpackOp WordVec 8 W32) = mkGenPrimOp (fsLit "unpackWord32X8#")  [] [word32X8PrimTy] ((mkTupleTy Unboxed [word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy])) primOpInfo (VecUnpackOp WordVec 4 W64) = mkGenPrimOp (fsLit "unpackWord64X4#")  [] [word64X4PrimTy] ((mkTupleTy Unboxed [word64PrimTy, word64PrimTy, word64PrimTy, word64PrimTy]))-primOpInfo (VecUnpackOp WordVec 64 W8) = mkGenPrimOp (fsLit "unpackWord8X64#")  [] [word8X64PrimTy] ((mkTupleTy Unboxed [wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy]))-primOpInfo (VecUnpackOp WordVec 32 W16) = mkGenPrimOp (fsLit "unpackWord16X32#")  [] [word16X32PrimTy] ((mkTupleTy Unboxed [wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy, wordPrimTy]))+primOpInfo (VecUnpackOp WordVec 64 W8) = mkGenPrimOp (fsLit "unpackWord8X64#")  [] [word8X64PrimTy] ((mkTupleTy Unboxed [word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy, word8PrimTy]))+primOpInfo (VecUnpackOp WordVec 32 W16) = mkGenPrimOp (fsLit "unpackWord16X32#")  [] [word16X32PrimTy] ((mkTupleTy Unboxed [word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy, word16PrimTy])) primOpInfo (VecUnpackOp WordVec 16 W32) = mkGenPrimOp (fsLit "unpackWord32X16#")  [] [word32X16PrimTy] ((mkTupleTy Unboxed [word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy, word32PrimTy])) primOpInfo (VecUnpackOp WordVec 8 W64) = mkGenPrimOp (fsLit "unpackWord64X8#")  [] [word64X8PrimTy] ((mkTupleTy Unboxed [word64PrimTy, word64PrimTy, word64PrimTy, word64PrimTy, word64PrimTy, word64PrimTy, word64PrimTy, word64PrimTy])) primOpInfo (VecUnpackOp FloatVec 4 W32) = mkGenPrimOp (fsLit "unpackFloatX4#")  [] [floatX4PrimTy] ((mkTupleTy Unboxed [floatPrimTy, floatPrimTy, floatPrimTy, floatPrimTy]))@@ -746,16 +746,16 @@ primOpInfo (VecInsertOp IntVec 32 W16) = mkGenPrimOp (fsLit "insertInt16X32#")  [] [int16X32PrimTy, int16PrimTy, intPrimTy] (int16X32PrimTy) primOpInfo (VecInsertOp IntVec 16 W32) = mkGenPrimOp (fsLit "insertInt32X16#")  [] [int32X16PrimTy, int32PrimTy, intPrimTy] (int32X16PrimTy) primOpInfo (VecInsertOp IntVec 8 W64) = mkGenPrimOp (fsLit "insertInt64X8#")  [] [int64X8PrimTy, int64PrimTy, intPrimTy] (int64X8PrimTy)-primOpInfo (VecInsertOp WordVec 16 W8) = mkGenPrimOp (fsLit "insertWord8X16#")  [] [word8X16PrimTy, wordPrimTy, intPrimTy] (word8X16PrimTy)-primOpInfo (VecInsertOp WordVec 8 W16) = mkGenPrimOp (fsLit "insertWord16X8#")  [] [word16X8PrimTy, wordPrimTy, intPrimTy] (word16X8PrimTy)+primOpInfo (VecInsertOp WordVec 16 W8) = mkGenPrimOp (fsLit "insertWord8X16#")  [] [word8X16PrimTy, word8PrimTy, intPrimTy] (word8X16PrimTy)+primOpInfo (VecInsertOp WordVec 8 W16) = mkGenPrimOp (fsLit "insertWord16X8#")  [] [word16X8PrimTy, word16PrimTy, intPrimTy] (word16X8PrimTy) primOpInfo (VecInsertOp WordVec 4 W32) = mkGenPrimOp (fsLit "insertWord32X4#")  [] [word32X4PrimTy, word32PrimTy, intPrimTy] (word32X4PrimTy) primOpInfo (VecInsertOp WordVec 2 W64) = mkGenPrimOp (fsLit "insertWord64X2#")  [] [word64X2PrimTy, word64PrimTy, intPrimTy] (word64X2PrimTy)-primOpInfo (VecInsertOp WordVec 32 W8) = mkGenPrimOp (fsLit "insertWord8X32#")  [] [word8X32PrimTy, wordPrimTy, intPrimTy] (word8X32PrimTy)-primOpInfo (VecInsertOp WordVec 16 W16) = mkGenPrimOp (fsLit "insertWord16X16#")  [] [word16X16PrimTy, wordPrimTy, intPrimTy] (word16X16PrimTy)+primOpInfo (VecInsertOp WordVec 32 W8) = mkGenPrimOp (fsLit "insertWord8X32#")  [] [word8X32PrimTy, word8PrimTy, intPrimTy] (word8X32PrimTy)+primOpInfo (VecInsertOp WordVec 16 W16) = mkGenPrimOp (fsLit "insertWord16X16#")  [] [word16X16PrimTy, word16PrimTy, intPrimTy] (word16X16PrimTy) primOpInfo (VecInsertOp WordVec 8 W32) = mkGenPrimOp (fsLit "insertWord32X8#")  [] [word32X8PrimTy, word32PrimTy, intPrimTy] (word32X8PrimTy) primOpInfo (VecInsertOp WordVec 4 W64) = mkGenPrimOp (fsLit "insertWord64X4#")  [] [word64X4PrimTy, word64PrimTy, intPrimTy] (word64X4PrimTy)-primOpInfo (VecInsertOp WordVec 64 W8) = mkGenPrimOp (fsLit "insertWord8X64#")  [] [word8X64PrimTy, wordPrimTy, intPrimTy] (word8X64PrimTy)-primOpInfo (VecInsertOp WordVec 32 W16) = mkGenPrimOp (fsLit "insertWord16X32#")  [] [word16X32PrimTy, wordPrimTy, intPrimTy] (word16X32PrimTy)+primOpInfo (VecInsertOp WordVec 64 W8) = mkGenPrimOp (fsLit "insertWord8X64#")  [] [word8X64PrimTy, word8PrimTy, intPrimTy] (word8X64PrimTy)+primOpInfo (VecInsertOp WordVec 32 W16) = mkGenPrimOp (fsLit "insertWord16X32#")  [] [word16X32PrimTy, word16PrimTy, intPrimTy] (word16X32PrimTy) primOpInfo (VecInsertOp WordVec 16 W32) = mkGenPrimOp (fsLit "insertWord32X16#")  [] [word32X16PrimTy, word32PrimTy, intPrimTy] (word32X16PrimTy) primOpInfo (VecInsertOp WordVec 8 W64) = mkGenPrimOp (fsLit "insertWord64X8#")  [] [word64X8PrimTy, word64PrimTy, intPrimTy] (word64X8PrimTy) primOpInfo (VecInsertOp FloatVec 4 W32) = mkGenPrimOp (fsLit "insertFloatX4#")  [] [floatX4PrimTy, floatPrimTy, intPrimTy] (floatX4PrimTy)