[Git][ghc/ghc][wip/ncg-simd] 3 commits: update docs & genprimopcode

sheaf (@sheaf) gitlab at gitlab.haskell.org
Wed Jun 26 10:23:18 UTC 2024



sheaf pushed to branch wip/ncg-simd at Glasgow Haskell Compiler / GHC


Commits:
e13380c2 by sheaf at 2024-06-26T12:13:13+02:00
update docs & genprimopcode

- - - - -
3583556a by sheaf at 2024-06-26T12:13:24+02:00
Revert "fixup Reg.Liveness.equalBlockMaps"

This reverts commit bdfd16720337a004f1ea37737b5e6d69aef7a7a5.

- - - - -
dc286e78 by sheaf at 2024-06-26T12:14:23+02:00
Empty commit allowing metric increases

-------------------------
Metric Increase:
    T12707
    T13035
    T13379
    T3294
    T4801
    T5321FD
    T5321Fun
    T783
-------------------------

- - - - -


6 changed files:

- compiler/GHC/Builtin/primops.txt.pp
- compiler/GHC/CmmToAsm/PPC/Instr.hs
- compiler/GHC/CmmToAsm/Reg/Liveness.hs
- compiler/GHC/CmmToAsm/X86/Instr.hs
- docs/users_guide/9.12.1-notes.rst
- utils/genprimopcode/Main.hs


Changes:

=====================================
compiler/GHC/Builtin/primops.txt.pp
=====================================
@@ -145,7 +145,7 @@ defaults
    cheap            = { primOpOkForSpeculation _thisOp }
    strictness       = { \ arity -> mkClosedDmdSig (replicate arity topDmd) topDiv }
    fixity           = Nothing
-   llvm_only        = False
+   simd             = False
    vector           = []
    deprecated_msg   = {}      -- A non-empty message indicates deprecation
 
@@ -4022,86 +4022,86 @@ section "SIMD Vectors"
   ,<Word8,Word8#,64>,<Word16,Word16#,32>,<Word32,Word32#,16>,<Word64,Word64#,8>]
 
 primtype VECTOR
-   with llvm_only = True
+   with simd = True
         vector = ALL_VECTOR_TYPES
 
 primop VecBroadcastOp "broadcast#" GenPrimOp
    SCALAR -> VECTOR
    { Broadcast a scalar to all elements of a vector. }
-   with llvm_only = True
+   with simd = True
         vector = ALL_VECTOR_TYPES
 
 primop VecPackOp "pack#" GenPrimOp
    VECTUPLE -> VECTOR
    { Pack the elements of an unboxed tuple into a vector. }
-   with llvm_only = True
+   with simd = True
         vector = ALL_VECTOR_TYPES
 
 primop VecUnpackOp "unpack#" GenPrimOp
    VECTOR -> VECTUPLE
    { Unpack the elements of a vector into an unboxed tuple. #}
-   with llvm_only = True
+   with simd = True
         vector = ALL_VECTOR_TYPES
 
 primop VecInsertOp "insert#" GenPrimOp
    VECTOR -> SCALAR -> Int# -> VECTOR
    { Insert a scalar at the given position in a vector. }
    with effect = CanFail
-        llvm_only = True
+        simd = True
         vector = ALL_VECTOR_TYPES
 
 primop VecAddOp "plus#" GenPrimOp
    VECTOR -> VECTOR -> VECTOR
    { Add two vectors element-wise. }
    with commutable = True
-        llvm_only = True
+        simd = True
         vector = ALL_VECTOR_TYPES
 
 primop VecSubOp "minus#" GenPrimOp
    VECTOR -> VECTOR -> VECTOR
    { Subtract two vectors element-wise. }
-   with llvm_only = True
+   with simd = True
         vector = ALL_VECTOR_TYPES
 
 primop VecMulOp "times#" GenPrimOp
    VECTOR -> VECTOR -> VECTOR
    { Multiply two vectors element-wise. }
    with commutable = True
-        llvm_only = True
+        simd = True
         vector = ALL_VECTOR_TYPES
 
 primop VecDivOp "divide#" GenPrimOp
    VECTOR -> VECTOR -> VECTOR
    { Divide two vectors element-wise. }
    with effect = CanFail
-        llvm_only = True
+        simd = True
         vector = FLOAT_VECTOR_TYPES
 
 primop VecQuotOp "quot#" GenPrimOp
    VECTOR -> VECTOR -> VECTOR
    { Rounds towards zero element-wise. }
    with effect = CanFail
-        llvm_only = True
+        simd = True
         vector = INT_VECTOR_TYPES
 
 primop VecRemOp "rem#" GenPrimOp
    VECTOR -> VECTOR -> VECTOR
    { Satisfies @('quot#' x y) 'times#' y 'plus#' ('rem#' x y) == x at . }
    with effect = CanFail
-        llvm_only = True
+        simd = True
         vector = INT_VECTOR_TYPES
 
 primop VecNegOp "negate#" GenPrimOp
    VECTOR -> VECTOR
    { Negate element-wise. }
-   with llvm_only = True
+   with simd = True
         vector = SIGNED_VECTOR_TYPES
 
 primop VecIndexByteArrayOp "indexArray#" GenPrimOp
    ByteArray# -> Int# -> VECTOR
    { Read a vector from specified index of immutable array. }
    with effect = CanFail
-        llvm_only = True
+        simd = True
         vector = ALL_VECTOR_TYPES
 
 primop VecReadByteArrayOp "readArray#" GenPrimOp
@@ -4109,7 +4109,7 @@ primop VecReadByteArrayOp "readArray#" GenPrimOp
    { Read a vector from specified index of mutable array. }
    with effect = ReadWriteEffect
         can_fail_warning = YesWarnCanFail
-        llvm_only = True
+        simd = True
         vector = ALL_VECTOR_TYPES
 
 primop VecWriteByteArrayOp "writeArray#" GenPrimOp
@@ -4117,14 +4117,14 @@ primop VecWriteByteArrayOp "writeArray#" GenPrimOp
    { Write a vector to specified index of mutable array. }
    with effect = ReadWriteEffect
         can_fail_warning = YesWarnCanFail
-        llvm_only = True
+        simd = True
         vector = ALL_VECTOR_TYPES
 
 primop VecIndexOffAddrOp "indexOffAddr#" GenPrimOp
    Addr# -> Int# -> VECTOR
    { Reads vector; offset in bytes. }
    with effect = CanFail
-        llvm_only = True
+        simd = True
         vector = ALL_VECTOR_TYPES
 
 primop VecReadOffAddrOp "readOffAddr#" GenPrimOp
@@ -4132,7 +4132,7 @@ primop VecReadOffAddrOp "readOffAddr#" GenPrimOp
    { Reads vector; offset in bytes. }
    with effect = ReadWriteEffect
         can_fail_warning = YesWarnCanFail
-        llvm_only = True
+        simd = True
         vector = ALL_VECTOR_TYPES
 
 primop VecWriteOffAddrOp "writeOffAddr#" GenPrimOp
@@ -4140,7 +4140,7 @@ primop VecWriteOffAddrOp "writeOffAddr#" GenPrimOp
    { Write vector; offset in bytes. }
    with effect = ReadWriteEffect
         can_fail_warning = YesWarnCanFail
-        llvm_only = True
+        simd = True
         vector = ALL_VECTOR_TYPES
 
 
@@ -4148,7 +4148,7 @@ primop VecIndexScalarByteArrayOp "indexArrayAs#" GenPrimOp
    ByteArray# -> Int# -> VECTOR
    { Read a vector from specified index of immutable array of scalars; offset is in scalar elements. }
    with effect = CanFail
-        llvm_only = True
+        simd = True
         vector = ALL_VECTOR_TYPES
 
 primop VecReadScalarByteArrayOp "readArrayAs#" GenPrimOp
@@ -4156,7 +4156,7 @@ primop VecReadScalarByteArrayOp "readArrayAs#" GenPrimOp
    { Read a vector from specified index of mutable array of scalars; offset is in scalar elements. }
    with effect = ReadWriteEffect
         can_fail_warning = YesWarnCanFail
-        llvm_only = True
+        simd = True
         vector = ALL_VECTOR_TYPES
 
 primop VecWriteScalarByteArrayOp "writeArrayAs#" GenPrimOp
@@ -4164,14 +4164,14 @@ primop VecWriteScalarByteArrayOp "writeArrayAs#" GenPrimOp
    { Write a vector to specified index of mutable array of scalars; offset is in scalar elements. }
    with effect = ReadWriteEffect
         can_fail_warning = YesWarnCanFail
-        llvm_only = True
+        simd = True
         vector = ALL_VECTOR_TYPES
 
 primop VecIndexScalarOffAddrOp "indexOffAddrAs#" GenPrimOp
    Addr# -> Int# -> VECTOR
    { Reads vector; offset in scalar elements. }
    with effect = CanFail
-        llvm_only = True
+        simd = True
         vector = ALL_VECTOR_TYPES
 
 primop VecReadScalarOffAddrOp "readOffAddrAs#" GenPrimOp
@@ -4179,7 +4179,7 @@ primop VecReadScalarOffAddrOp "readOffAddrAs#" GenPrimOp
    { Reads vector; offset in scalar elements. }
    with effect = ReadWriteEffect
         can_fail_warning = YesWarnCanFail
-        llvm_only = True
+        simd = True
         vector = ALL_VECTOR_TYPES
 
 primop VecWriteScalarOffAddrOp "writeOffAddrAs#" GenPrimOp
@@ -4187,39 +4187,39 @@ primop VecWriteScalarOffAddrOp "writeOffAddrAs#" GenPrimOp
    { Write vector; offset in scalar elements. }
    with effect = ReadWriteEffect
         can_fail_warning = YesWarnCanFail
-        llvm_only = True
+        simd = True
         vector = ALL_VECTOR_TYPES
 
 primop   VecFMAdd   "fmadd#" GenPrimOp
    VECTOR -> VECTOR -> VECTOR -> VECTOR
    {Fused multiply-add operation @x*y+z at . See "GHC.Prim#fma".}
    with
-      llvm_only = True
+      simd = True
       vector = FLOAT_VECTOR_TYPES
 primop   VecFMSub   "fmsub#" GenPrimOp
    VECTOR -> VECTOR -> VECTOR -> VECTOR
    {Fused multiply-subtract operation @x*y-z at . See "GHC.Prim#fma".}
    with
-      llvm_only = True
+      simd = True
       vector = FLOAT_VECTOR_TYPES
 primop   VecFNMAdd   "fnmadd#" GenPrimOp
    VECTOR -> VECTOR -> VECTOR -> VECTOR
    {Fused negate-multiply-add operation @-x*y+z at . See "GHC.Prim#fma".}
    with
-      llvm_only = True
+      simd = True
       vector = FLOAT_VECTOR_TYPES
 primop   VecFNMSub   "fnmsub#" GenPrimOp
    VECTOR -> VECTOR -> VECTOR -> VECTOR
    {Fused negate-multiply-subtract operation @-x*y-z at . See "GHC.Prim#fma".}
    with
-      llvm_only = True
+      simd = True
       vector = FLOAT_VECTOR_TYPES
 
 primop VecShuffleOp "shuffle#" GenPrimOp
   VECTOR -> VECTOR -> INTVECTUPLE -> VECTOR
-  { Shuffle elements of the concatenation of the input two vectors
+  {Shuffle elements of the concatenation of the input two vectors
   into the result vector.}
-   with llvm_only = True
+   with simd = True
         vector = ALL_VECTOR_TYPES
 
 ------------------------------------------------------------------------


=====================================
compiler/GHC/CmmToAsm/PPC/Instr.hs
=====================================
@@ -394,7 +394,7 @@ regUsageOfInstr platform instr
     usage (src, dst) = RU (map mkFmt $ filter (interesting platform) src)
                           (map mkFmt $ filter (interesting platform) dst)
       -- SIMD NCG TODO: the format here is used for register spilling/unspilling.
-      -- As the AArch64 NCG does not currently support SIMD registers,
+      -- As the PowerPC NCG does not currently support SIMD registers,
       -- this simple logic is OK.
     mkFmt r = RegFormat r fmt
       where fmt = case targetClassOfReg platform r of


=====================================
compiler/GHC/CmmToAsm/Reg/Liveness.hs
=====================================
@@ -927,15 +927,10 @@ livenessSCCs platform blockmap done
 
                 -- probably the least efficient way to compare two
                 -- BlockMaps for equality.
-            equalBlockMaps
-                :: BlockMap (UniqSet RegFormat)
-                -> BlockMap (UniqSet RegFormat)
-                -> Bool
             equalBlockMaps a b
                 = a' == b'
-              where a' = map f $ mapToList a
-                    b' = map f $ mapToList b
-                    f (key,elt) = (key, map regFormatReg $ nonDetEltsUniqSet elt)
+              where a' = mapToList a
+                    b' = mapToList b
                     -- See Note [Unique Determinism and code generation]
 
 


=====================================
compiler/GHC/CmmToAsm/X86/Instr.hs
=====================================
@@ -206,7 +206,7 @@ data Instr
         --
         -- When used at a vector format, only moves the lower 64 bits of data;
         -- the rest of the data in the destination may either be zeroed or
-        -- preserved, depending on the specific format.
+        -- preserved, depending on the specific format and operands.
         | MOV Format Operand Operand
              -- N.B. Due to AT&T assembler quirks, when used with 'II64'
              -- 'Format' immediate source and memory target operand, the source


=====================================
docs/users_guide/9.12.1-notes.rst
=====================================
@@ -62,6 +62,12 @@ Compiler
 
 - :ghc-flag:`-Wderiving-typeable` has been added to :ghc-flag:`-Wall`.
 
+- SIMD support has been added to the X86 native code generator.
+  For the time being, only 128 bit wide vectors are supported, with most
+  floating-point operations implemented, together with a few integer vector
+  operations. Other operations still require the LLVM backend. Contributors
+  welcome!
+
 - i386 Windows support is now completely removed amid massive cleanup
   of legacy code to pave way for Arm64 Windows support (`#24883
   <https://gitlab.haskell.org/ghc/ghc/-/issues/24883>`_). Rest
@@ -98,6 +104,20 @@ Runtime system
 ``ghc-prim`` library
 ~~~~~~~~~~~~~~~~~~~~
 
+- New fused multiply-add instructions for vectors of floating-point values,
+  such as ``fmaddFloatX4# :: FloatX4# -> FloatX4# -> FloatX4# -> FloatX4#`` and
+  ``fnmsubDoubleX2# :: DoubleX2# -> DoubleX2# -> DoubleX2# -> DoubleX2#``.
+  These follow the same semantics as ``fmadd``/``fmsub``/``fnmadd``/``fnmsub``,
+  operating in parallel on vectors of floating-point values.
+
+- New vector shuffle instructions, such as ``shuffleFloatX4# :: FloatX4# -> FloatX4# -> (# Int#, Int#, Int#, Int# #) -> FloatX4#``.
+  These instructions take two input vectors and a collection of indices (which must
+  be compile-time literal integers), and constructs a result vector by extracting
+  out the values at those indices. For instance, ``shuffleFloatX4#`` on input vectors with
+  components ``(# 0.1#, 11.1#, 22.1#, 33.1# #)`` and ``(# 44.1#, 55.1#, 66.1#, 77.1# #)``,
+  and indices ``(# 4#, 3#, 6#, 1# #)``, will return a vector with components
+  ``(# 44.1#, 33.1#, 66.1#, 11.1# #)``.
+
 ``ghc`` library
 ~~~~~~~~~~~~~~~
 


=====================================
utils/genprimopcode/Main.hs
=====================================
@@ -343,15 +343,10 @@ gen_hs_source (Info defaults entries) =
                  Section { } -> error "Section is not an entity"
              ]
 
-           extra options = case on_llvm_only options ++ can_fail options of
-             [m1,m2] -> "\n\n__/Warning:/__ this " ++ m1 ++ " and " ++ m2 ++ "."
+           extra options = case can_fail options of
              [m] -> "\n\n__/Warning:/__ this " ++ m ++ "."
              _ -> ""
 
-           on_llvm_only options
-             = [ "is only available on LLVM"
-               | Just (OptionTrue _) <- [lookup_attrib "llvm_only" options] ]
-
            can_fail options
              = [ "can fail with an unchecked exception"
                | Just (OptionEffect eff) <- [lookup_attrib "effect" options]
@@ -473,37 +468,50 @@ gen_wrappers (Info _ entries)
      ++ "import qualified GHC.Prim\n"
      ++ "import GHC.Tuple ()\n"
      ++ "import GHC.Prim (" ++ types ++ ")\n"
-     ++ unlines (concatMap f specs)
+     ++ unlines (concatMap mkWrapper wrappers)
      where
-        specs = filter (not.dodgy) $
-                filter (not.is_llvm_only) $
-                filter is_primop entries
-        tycons = foldr union [] $ map (tyconsIn . ty) specs
+        wrappers = filter wantWrapper entries
+        tycons = foldr union [] $ map (tyconsIn . ty) wrappers
         tycons' = filter (`notElem` [TyCon "()", TyCon "Bool"]) tycons
         types = concat $ intersperse ", " $ map show tycons'
-        f spec = let args = map (\n -> "a" ++ show n) [1 .. arity (ty spec)]
-                     src_name = wrap (name spec)
-                     lhs = src_name ++ " " ++ unwords args
-                     rhs = wrapQual (name spec) ++ " " ++ unwords args
-                 in ["{-# NOINLINE " ++ src_name ++ " #-}",
-                     src_name ++ " :: " ++ pprTy (ty spec),
-                     lhs ++ " = " ++ rhs]
+        mkWrapper spec =
+          let args = map (\n -> "a" ++ show n) [1 .. arity (ty spec)]
+              src_name = wrap (name spec)
+              lhs = src_name ++ " " ++ unwords args
+              rhs = wrapQual (name spec) ++ " " ++ unwords args
+          in ["{-# NOINLINE " ++ src_name ++ " #-}",
+              src_name ++ " :: " ++ pprTy (ty spec),
+              lhs ++ " = " ++ rhs]
         wrap nm | isLower (head nm) = nm
                 | otherwise = "(" ++ nm ++ ")"
         wrapQual nm | isLower (head nm) = "GHC.Prim." ++ nm
                     | otherwise         = "(GHC.Prim." ++ nm ++ ")"
 
-        dodgy spec
-           = name spec `elem`
-             [-- tagToEnum# is really magical, and can't have
+        wantWrapper :: Entry -> Bool
+        wantWrapper entry =
+          and
+            [ not $ name entry `elem` magicalPrimops
+            , is_primop entry
+                -- NB: is_primop rules out vector primops; not sure why this is necessary.
+            , not $ is_simd entry
+                -- Don't produce wrappers for SIMD primops.
+                --
+                -- SIMD NCG TODO: this was the logic in place when SIMD primops
+                -- were LLVM only; but now that this is no longer the case I
+                -- suppose this choice can be revisited?
+            ]
+
+        magicalPrimops :: [String]
+        magicalPrimops =
+          [ "tagToEnum#"
+              -- tagToEnum# is really magical, and can't have
               -- a wrapper since its implementation depends on
               -- the type of its result
-              "tagToEnum#"
-             ]
+          ]
 
-        is_llvm_only :: Entry -> Bool
-        is_llvm_only entry =
-            case lookup_attrib "llvm_only" (opts entry) of
+        is_simd :: Entry -> Bool
+        is_simd entry =
+            case lookup_attrib "simd" (opts entry) of
               Just (OptionTrue _) -> True
               _                   -> False
 



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/125fb19cec33bdd5bb0de9117222b6dbac665830...dc286e78d53b857cd2ac6f8b27103ffd85d2e3e4

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/125fb19cec33bdd5bb0de9117222b6dbac665830...dc286e78d53b857cd2ac6f8b27103ffd85d2e3e4
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20240626/1e9b2da6/attachment-0001.html>


More information about the ghc-commits mailing list