Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC

Commits:

19 changed files:

Changes:

  • compiler/GHC/Cmm/CallConv.hs
    ... ... @@ -203,11 +203,7 @@ realDoubleRegs platform = map DoubleReg $ regList (pc_MAX_Real_Double_REG (pl
    203 203
     realLongRegs    platform = map LongReg    $ regList (pc_MAX_Real_Long_REG    (platformConstants platform))
    
    204 204
     
    
    205 205
     realXmmRegNos :: Platform -> [Int]
    
    206
    -realXmmRegNos platform
    
    207
    -    | isSse2Enabled platform || platformArch platform == ArchAArch64
    
    208
    -    = regList (pc_MAX_Real_XMM_REG (platformConstants platform))
    
    209
    -    | otherwise
    
    210
    -    = []
    
    206
    +realXmmRegNos platform = regList (pc_MAX_Real_XMM_REG (platformConstants platform))
    
    211 207
     
    
    212 208
     regList :: Int -> [Int]
    
    213 209
     regList n = [1 .. n]
    

  • compiler/GHC/CmmToAsm/Config.hs
    1 1
     -- | Native code generator configuration
    
    2 2
     module GHC.CmmToAsm.Config
    
    3 3
        ( NCGConfig(..)
    
    4
    +   , ncgX86Features
    
    4 5
        , ncgWordWidth
    
    5 6
        , ncgSpillPreallocSize
    
    6 7
        , platformWordWidth
    
    ... ... @@ -9,10 +10,12 @@ where
    9 10
     
    
    10 11
     import GHC.Prelude
    
    11 12
     import GHC.Platform
    
    13
    +import GHC.Platform.CpuFeatures
    
    12 14
     import GHC.Cmm.Type (Width(..))
    
    13 15
     import GHC.CmmToAsm.CFG.Weight
    
    14 16
     import GHC.Unit.Module (Module)
    
    15 17
     import GHC.Utils.Outputable
    
    18
    +import GHC.Utils.Panic
    
    16 19
     
    
    17 20
     -- | Native code generator configuration
    
    18 21
     data NCGConfig = NCGConfig
    
    ... ... @@ -29,12 +32,7 @@ data NCGConfig = NCGConfig
    29 32
        , ncgRegsGraph             :: !Bool
    
    30 33
        , ncgAsmLinting            :: !Bool            -- ^ Perform ASM linting pass
    
    31 34
        , ncgDoConstantFolding     :: !Bool            -- ^ Perform CMM constant folding
    
    32
    -   , ncgSseAvxVersion         :: Maybe SseAvxVersion -- ^ (x86) SSE and AVX instructions
    
    33
    -   , ncgAvx512fEnabled        :: !Bool
    
    34
    -   , ncgAvx512vlEnabled       :: !Bool
    
    35
    -   , ncgAvx512bwEnabled       :: !Bool
    
    36
    -   , ncgAvx512dqEnabled       :: !Bool
    
    37
    -   , ncgBmiVersion            :: Maybe BmiVersion -- ^ (x86) BMI instructions
    
    35
    +   , ncgCpuFeatures           :: !CpuFeatures     -- ^ Enabled CPU features
    
    38 36
        , ncgDumpRegAllocStages    :: !Bool
    
    39 37
        , ncgDumpAsmStats          :: !Bool
    
    40 38
        , ncgDumpAsmConflicts      :: !Bool
    
    ... ... @@ -54,6 +52,13 @@ data NCGConfig = NCGConfig
    54 52
        , ncgLa664Enabled          :: !Bool            -- ^ la664 is equal to isav1.1
    
    55 53
        }
    
    56 54
     
    
    55
    +-- | X86 only: enabled x86 CPU features.
    
    56
    +ncgX86Features :: NCGConfig -> X86Features
    
    57
    +ncgX86Features config =
    
    58
    +  case ncgCpuFeatures config of
    
    59
    +    X86CpuFeatures feats -> feats
    
    60
    +    _ -> panic "ncgX86Features: not an x86 target"
    
    61
    +
    
    57 62
     -- | Return Word size
    
    58 63
     ncgWordWidth :: NCGConfig -> Width
    
    59 64
     ncgWordWidth config = platformWordWidth (ncgPlatform config)
    

  • compiler/GHC/CmmToAsm/X86/CodeGen.hs
    ... ... @@ -56,6 +56,7 @@ import GHC.CmmToAsm.Config
    56 56
     import GHC.Platform.Reg
    
    57 57
     import GHC.CmmToAsm.Reg.Target (targetClassOfReg)
    
    58 58
     import GHC.Platform
    
    59
    +import GHC.Platform.CpuFeatures
    
    59 60
     import GHC.Platform.Reg.Class.Unified (RegClass(..))
    
    60 61
     
    
    61 62
     -- Our intermediate code:
    
    ... ... @@ -99,43 +100,7 @@ import Data.Word
    99 100
     
    
    100 101
     import qualified Data.Map as Map
    
    101 102
     
    
    102
    -is32BitPlatform :: NatM Bool
    
    103
    -is32BitPlatform = do
    
    104
    -    platform <- getPlatform
    
    105
    -    return $ target32Bit platform
    
    106
    -
    
    107
    --- These flags may be implied by other flags like -mfma or -mavx512f.
    
    108
    --- See Note [Implications between X86 CPU feature flags] for details.
    
    109
    -ssse3Enabled :: NatM Bool
    
    110
    -ssse3Enabled = do
    
    111
    -  config <- getConfig
    
    112
    -  return (ncgSseAvxVersion config >= Just SSSE3)
    
    113
    -
    
    114
    -sse4_1Enabled :: NatM Bool
    
    115
    -sse4_1Enabled = do
    
    116
    -  config <- getConfig
    
    117
    -  return (ncgSseAvxVersion config >= Just SSE4)
    
    118
    -
    
    119
    -sse4_2Enabled :: NatM Bool
    
    120
    -sse4_2Enabled = do
    
    121
    -  config <- getConfig
    
    122
    -  return (ncgSseAvxVersion config >= Just SSE42)
    
    123
    -
    
    124
    -avxEnabled :: NatM Bool
    
    125
    -avxEnabled = do
    
    126
    -  config <- getConfig
    
    127
    -  return (ncgSseAvxVersion config >= Just AVX1)
    
    128
    -
    
    129
    -avx2Enabled :: NatM Bool
    
    130
    -avx2Enabled = do
    
    131
    -  config <- getConfig
    
    132
    -  return (ncgSseAvxVersion config >= Just AVX2)
    
    133
    -
    
    134
    -avx512vlEnabled :: NatM Bool
    
    135
    -avx512vlEnabled = ncgAvx512vlEnabled <$> getConfig
    
    136
    -
    
    137
    -avx512dqEnabled :: NatM Bool
    
    138
    -avx512dqEnabled = ncgAvx512dqEnabled <$> getConfig
    
    103
    +--------------------------------------------------------------------------------
    
    139 104
     
    
    140 105
     cmmTopCodeGen
    
    141 106
             :: RawCmmDecl
    
    ... ... @@ -426,7 +391,9 @@ swizzleRegisterRep (Any _ codefn) format = Any format codefn
    426 391
     
    
    427 392
     getLocalRegReg :: LocalReg -> Reg
    
    428 393
     getLocalRegReg (LocalReg u ty)
    
    429
    -  = -- by assuming SSE2, Int, Word, Float, Double and vectors all can be register allocated
    
    394
    +  = -- Int, Word, Float, Double and vectors can all be register allocated, as the
    
    395
    +    -- baseline instruction set includes SSE2: see 'x86BaselineSseAvx' in
    
    396
    +    -- GHC.Platform.CpuFeatures.
    
    430 397
         RegVirtual (mkVirtualReg u (cmmTypeFormat ty))
    
    431 398
     
    
    432 399
     -- | Grab the Reg for a CmmReg
    
    ... ... @@ -495,6 +462,20 @@ is32BitInteger i = i64 <= 0x7fffffff && i64 >= -0x80000000
    495 462
       where i64 = fromIntegral i :: Int64
    
    496 463
     
    
    497 464
     
    
    465
    +-- -----------------------------------------------------------------------------
    
    466
    +-- NCG configuration options (e.g. enabled X86 CPU features)
    
    467
    +
    
    468
    +is32BitPlatform :: NatM Bool
    
    469
    +is32BitPlatform = do
    
    470
    +    platform <- getPlatform
    
    471
    +    return $ target32Bit platform
    
    472
    +
    
    473
    +-- | Whether an x86 instruction set is enabled, e.g. @x86Feature x86AvxEnabled@.
    
    474
    +--
    
    475
    +-- See Note [CPU features] for the implication structure of X86 features.
    
    476
    +x86Feature :: (X86Features -> res) -> NatM res
    
    477
    +x86Feature f = f . ncgX86Features <$> getConfig
    
    478
    +
    
    498 479
     -- -----------------------------------------------------------------------------
    
    499 480
     -- General things for putting together code sequences
    
    500 481
     
    
    ... ... @@ -976,11 +957,11 @@ getRegister' _ _ (CmmMachOp mop []) =
    976 957
       pprPanic "getRegister(x86): nullary MachOp" (text $ show mop)
    
    977 958
     
    
    978 959
     getRegister' platform is32Bit (CmmMachOp mop [x]) = do -- unary MachOps
    
    979
    -    sse42   <- sse4_2Enabled
    
    980
    -    ssse3    <- ssse3Enabled
    
    981
    -    avx     <- avxEnabled
    
    982
    -    avx2    <- avx2Enabled
    
    983
    -    avx512vl <- avx512vlEnabled
    
    960
    +    sse42    <- x86Feature x86Sse4_2Enabled
    
    961
    +    ssse3    <- x86Feature x86Ssse3Enabled
    
    962
    +    avx      <- x86Feature x86AvxEnabled
    
    963
    +    avx2     <- x86Feature x86Avx2Enabled
    
    964
    +    avx512vl <- x86Feature x86Avx512VLEnabled
    
    984 965
         case mop of
    
    985 966
           MO_F_Neg w  -> sse2NegCode w x
    
    986 967
     
    
    ... ... @@ -1459,11 +1440,11 @@ getRegister' platform is32Bit (CmmMachOp (MO_Xor w) [x, y])
    1459 1440
       = genBitTestCode (intFormat w) BTC opnd ix
    
    1460 1441
     
    
    1461 1442
     getRegister' platform is32Bit (CmmMachOp mop [x, y]) = do -- dyadic MachOps
    
    1462
    -  sse4_1 <- sse4_1Enabled
    
    1463
    -  sse4_2 <- sse4_2Enabled
    
    1464
    -  avx <- avxEnabled
    
    1465
    -  avx512vl <- avx512vlEnabled
    
    1466
    -  avx512dq <- avx512dqEnabled
    
    1443
    +  sse4_1 <- x86Feature x86Sse4_1Enabled
    
    1444
    +  sse4_2 <- x86Feature x86Sse4_2Enabled
    
    1445
    +  avx <- x86Feature x86AvxEnabled
    
    1446
    +  avx512vl <- x86Feature x86Avx512VLEnabled
    
    1447
    +  avx512dq <- x86Feature x86Avx512DQEnabled
    
    1467 1448
       case mop of
    
    1468 1449
           MO_F_Eq _ -> condFltReg is32Bit EQQ x y
    
    1469 1450
           MO_F_Ne _ -> condFltReg is32Bit NE  x y
    
    ... ... @@ -2607,7 +2588,7 @@ getRegister' platform is32Bit (CmmMachOp mop [x, y]) = do -- dyadic MachOps
    2607 2588
     
    
    2608 2589
             -- PALIGNR (SSSE3) or PSLLDQ + PSRLDQ: is == [i,i+1,...,n-2,n-1;n,n+1,...,n+i-1]
    
    2609 2590
             | (js, ks) <- span (< n) is, and (zipWith (==) (reverse js) [n-1,n-2..]), and (zipWith (==) ks [n..]) -> Just $ do
    
    2610
    -          ssse3 <- ssse3Enabled
    
    2591
    +          ssse3 <- x86Feature x86Ssse3Enabled
    
    2611 2592
               let amountInBytes = widthInBytes * length ks
    
    2612 2593
               if ssse3
    
    2613 2594
                 then vector_op_sse (`PALIGNR` (ImmInt amountInBytes)) fmt v2 v1
    
    ... ... @@ -2624,7 +2605,7 @@ getRegister' platform is32Bit (CmmMachOp mop [x, y]) = do -- dyadic MachOps
    2624 2605
     
    
    2625 2606
             -- PALIGNR (SSSE3) or PSLLDQ + PSRLDQ: is == [n+i,n+i+1,...,2n-2,2n-1;0,1,...,i-1]
    
    2626 2607
             | (js, ks) <- span (>= n) is, and (zipWith (==) (reverse js) [2*n-1,2*n-2..]), and (zipWith (==) ks [0..]) -> Just $ do
    
    2627
    -          ssse3 <- ssse3Enabled
    
    2608
    +          ssse3 <- x86Feature x86Ssse3Enabled
    
    2628 2609
               let amountInBytes = widthInBytes * length ks
    
    2629 2610
               if ssse3
    
    2630 2611
                 then vector_op_sse (`PALIGNR` (ImmInt amountInBytes)) fmt v1 v2
    
    ... ... @@ -2663,7 +2644,7 @@ getRegister' platform is32Bit (CmmMachOp mop [x, y]) = do -- dyadic MachOps
    2663 2644
         vector_shuffle_int8x16 sse4_1 v1 v2 is
    
    2664 2645
           | Just commonCase <- vector_shuffle_int128_common sse4_1 fmt v1 v2 is = commonCase
    
    2665 2646
           | otherwise = do
    
    2666
    -        ssse3 <- ssse3Enabled
    
    2647
    +        ssse3 <- x86Feature x86Ssse3Enabled
    
    2667 2648
             let fmtInt16X8 = VecFormat 8 FmtInt16
    
    2668 2649
                 v1IsZero = isZeroVecLit v1
    
    2669 2650
                 v2IsZero = isZeroVecLit v2
    
    ... ... @@ -3021,8 +3002,8 @@ getRegister' platform is32Bit (CmmMachOp mop [x, y]) = do -- dyadic MachOps
    3021 3002
     
    
    3022 3003
     
    
    3023 3004
     getRegister' platform _is32Bit (CmmMachOp mop [x, y, z]) = do -- ternary MachOps
    
    3024
    -  avx    <- avxEnabled
    
    3025
    -  sse4_1 <- sse4_1Enabled
    
    3005
    +  avx    <- x86Feature x86AvxEnabled
    
    3006
    +  sse4_1 <- x86Feature x86Sse4_1Enabled
    
    3026 3007
       case mop of
    
    3027 3008
           -- Floating point fused multiply-add operations @ ± x*y ± z@
    
    3028 3009
           MO_FMA var l w
    
    ... ... @@ -3325,7 +3306,7 @@ getRegister' platform is32Bit (CmmLit lit)
    3325 3306
         is_label _                    = False
    
    3326 3307
     
    
    3327 3308
     getRegister' platform is32Bit (CmmLit lit) = do
    
    3328
    -  avx <- avxEnabled
    
    3309
    +  avx <- x86Feature x86AvxEnabled
    
    3329 3310
     
    
    3330 3311
       -- NB: it is important that the code produced here (to load a literal into
    
    3331 3312
       -- a register) doesn't clobber any registers other than the destination
    
    ... ... @@ -4764,7 +4745,8 @@ genCCall32 addr _conv dest_regs args = do
    4764 4745
                   | isVecType ty
    
    4765 4746
                   = unitOL (mkRegRegMoveInstr config (cmmTypeFormat ty) xmm0 r_dest)
    
    4766 4747
                   | isFloatType ty =
    
    4767
    -                  -- we assume SSE2
    
    4748
    +                  -- SSE2 is in the baseline instruction set: see 'x86BaselineSseAvx'
    
    4749
    +                  -- in GHC.Platform.CpuFeatures.
    
    4768 4750
                       let tmp_amode = AddrBaseIndex (EABaseReg esp)
    
    4769 4751
                                                            EAIndexNone
    
    4770 4752
                                                            (ImmInt 0)
    
    ... ... @@ -6418,7 +6400,7 @@ genCtzGeneric width dst src = do
    6418 6400
       config <- getConfig
    
    6419 6401
       let bw = widthInBits width
    
    6420 6402
       let dst_r = getLocalRegReg dst
    
    6421
    -  if ncgBmiVersion config >= Just BMI2
    
    6403
    +  if x86Bmi2Enabled (ncgX86Features config)
    
    6422 6404
       then do
    
    6423 6405
           src_r <- getNewRegNat (intFormat width)
    
    6424 6406
           let instrs = appOL (code_src src_r) $ case width of
    
    ... ... @@ -6735,7 +6717,7 @@ genPopCnt bid width dst src = do
    6735 6717
         platform = ncgPlatform config
    
    6736 6718
         format = intFormat width
    
    6737 6719
     
    
    6738
    -  sse4_2Enabled >>= \case
    
    6720
    +  x86Feature x86Sse4_2Enabled >>= \case
    
    6739 6721
     
    
    6740 6722
         True -> do
    
    6741 6723
           code_src <- getAnyReg src
    
    ... ... @@ -6771,7 +6753,7 @@ genPdep bid width dst src mask = do
    6771 6753
         platform = ncgPlatform config
    
    6772 6754
         format = intFormat width
    
    6773 6755
     
    
    6774
    -  if ncgBmiVersion config >= Just BMI2
    
    6756
    +  if x86Bmi2Enabled (ncgX86Features config)
    
    6775 6757
         then do
    
    6776 6758
           code_src  <- getAnyReg src
    
    6777 6759
           code_mask <- getAnyReg mask
    
    ... ... @@ -6798,7 +6780,7 @@ genPdep bid width dst src mask = do
    6798 6780
     genPext :: BlockId -> Width -> LocalReg -> CmmExpr -> CmmExpr -> NatM InstrBlock
    
    6799 6781
     genPext bid width dst src mask = do
    
    6800 6782
       config <- getConfig
    
    6801
    -  if ncgBmiVersion config >= Just BMI2
    
    6783
    +  if x86Bmi2Enabled (ncgX86Features config)
    
    6802 6784
         then do
    
    6803 6785
           let format   = intFormat width
    
    6804 6786
           let dst_r    = getLocalRegReg dst
    
    ... ... @@ -6835,7 +6817,7 @@ genClz bid width dst src = do
    6835 6817
         else do
    
    6836 6818
           code_src <- getAnyReg src
    
    6837 6819
           let dst_r = getLocalRegReg dst
    
    6838
    -      if ncgBmiVersion config >= Just BMI2
    
    6820
    +      if x86Bmi2Enabled (ncgX86Features config)
    
    6839 6821
             then do
    
    6840 6822
               src_r <- getNewRegNat (intFormat width)
    
    6841 6823
               return $ appOL (code_src src_r) $ case width of
    

  • compiler/GHC/CmmToAsm/X86/Instr.hs
    ... ... @@ -65,6 +65,7 @@ import GHC.Utils.Constants ( debugIsOn )
    65 65
     import GHC.Utils.Outputable
    
    66 66
     import GHC.Utils.Panic
    
    67 67
     import GHC.Platform
    
    68
    +import GHC.Platform.CpuFeatures
    
    68 69
     
    
    69 70
     import GHC.Cmm.CLabel
    
    70 71
     import GHC.Types.Unique.Set
    
    ... ... @@ -1182,9 +1183,10 @@ movInstr config fmt =
    1182 1183
           = f
    
    1183 1184
     
    
    1184 1185
         plat    = ncgPlatform config
    
    1185
    -    avx     = ncgSseAvxVersion config >= Just AVX1
    
    1186
    -    avx2    = ncgSseAvxVersion config >= Just AVX2
    
    1187
    -    avx512f = ncgAvx512fEnabled config
    
    1186
    +    feats   = ncgX86Features config
    
    1187
    +    avx     = x86AvxEnabled feats
    
    1188
    +    avx2    = x86Avx2Enabled feats
    
    1189
    +    avx512f = x86Avx512FEnabled feats
    
    1188 1190
         avx_move sFmt =
    
    1189 1191
           if isFloatScalarFormat sFmt
    
    1190 1192
           then assertCompatibleRegs $
    

  • compiler/GHC/CmmToLlvm/CodeGen.hs
    ... ... @@ -260,12 +260,12 @@ discussion about portable pdep/pext intrinsics.
    260 260
     -}
    
    261 261
     genCall (PrimTarget op@(MO_Pdep w)) [dst] args = do
    
    262 262
         cfg <- getConfig
    
    263
    -    if  llvmCgBmiVersion cfg >= Just BMI2
    
    263
    +    if  llvmCgBmi2Enabled cfg
    
    264 264
             then genCallMinimumTruncationCast W32 w op dst args
    
    265 265
             else genCallSimpleCast w op dst args
    
    266 266
     genCall (PrimTarget op@(MO_Pext w)) [dst] args = do
    
    267 267
         cfg <- getConfig
    
    268
    -    if  llvmCgBmiVersion cfg >= Just BMI2
    
    268
    +    if  llvmCgBmi2Enabled cfg
    
    269 269
             then genCallMinimumTruncationCast W32 w op dst args
    
    270 270
             else genCallSimpleCast w op dst args
    
    271 271
     
    
    ... ... @@ -852,7 +852,7 @@ cmmPrimOpFunctions :: CallishMachOp -> LlvmM LMString
    852 852
     cmmPrimOpFunctions mop = do
    
    853 853
       cfg      <- getConfig
    
    854 854
       platform <- getPlatform
    
    855
    -  let !isBmi2Enabled = llvmCgBmiVersion cfg >= Just BMI2
    
    855
    +  let !isBmi2Enabled = llvmCgBmi2Enabled cfg
    
    856 856
           !is32bit       = platformWordSize platform == PW4
    
    857 857
           unsupported = panic ("cmmPrimOpFunctions: " ++ show mop
    
    858 858
                             ++ " not supported here")
    

  • compiler/GHC/CmmToLlvm/Config.hs
    1 1
     -- | Llvm code generator configuration
    
    2 2
     module GHC.CmmToLlvm.Config
    
    3 3
       ( LlvmCgConfig(..)
    
    4
    +  , llvmCgBmi2Enabled
    
    4 5
       , LlvmConfig(..)
    
    5 6
       , LlvmTarget(..)
    
    6 7
       , initLlvmConfig
    
    ... ... @@ -9,6 +10,7 @@ where
    9 10
     
    
    10 11
     import GHC.Prelude
    
    11 12
     import GHC.Platform
    
    13
    +import GHC.Platform.CpuFeatures
    
    12 14
     
    
    13 15
     import GHC.Utils.Outputable
    
    14 16
     import GHC.Settings.Utils
    
    ... ... @@ -22,7 +24,7 @@ data LlvmCgConfig = LlvmCgConfig
    22 24
       , llvmCgContext           :: !SDocContext  -- ^ Context for LLVM code generation
    
    23 25
       , llvmCgFillUndefWithGarbage :: !Bool      -- ^ Fill undefined literals with garbage values
    
    24 26
       , llvmCgSplitSection      :: !Bool         -- ^ Split sections
    
    25
    -  , llvmCgBmiVersion        :: Maybe BmiVersion  -- ^ (x86) BMI instructions
    
    27
    +  , llvmCgCpuFeatures       :: !CpuFeatures  -- ^ Enabled CPU features
    
    26 28
       , llvmCgLlvmVersion       :: Maybe LlvmVersion -- ^ version of Llvm we're using
    
    27 29
       , llvmCgDoWarn            :: !Bool         -- ^ True ==> warn unsupported Llvm version
    
    28 30
       , llvmCgLlvmTarget        :: !String       -- ^ target triple passed to LLVM
    
    ... ... @@ -30,6 +32,13 @@ data LlvmCgConfig = LlvmCgConfig
    30 32
                                                  -- see Note [LLVM configuration]
    
    31 33
       }
    
    32 34
     
    
    35
    +-- | Whether BMI2 instructions are enabled (x86 only).
    
    36
    +llvmCgBmi2Enabled :: LlvmCgConfig -> Bool
    
    37
    +llvmCgBmi2Enabled cfg =
    
    38
    +  case llvmCgCpuFeatures cfg of
    
    39
    +    X86CpuFeatures feats -> x86Bmi2Enabled feats
    
    40
    +    _                    -> False
    
    41
    +
    
    33 42
     data LlvmTarget = LlvmTarget
    
    34 43
       { lDataLayout :: String
    
    35 44
       , lCPU        :: String
    

  • compiler/GHC/Driver/Config/CmmToAsm.hs
    ... ... @@ -39,37 +39,8 @@ initNCGConfig dflags this_mod = NCGConfig
    39 39
        , ncgDumpRegAllocStages    = dopt Opt_D_dump_asm_regalloc_stages dflags
    
    40 40
        , ncgDumpAsmStats          = dopt Opt_D_dump_asm_stats dflags
    
    41 41
        , ncgDumpAsmConflicts      = dopt Opt_D_dump_asm_conflicts dflags
    
    42
    -   , ncgBmiVersion            = case platformArch (targetPlatform dflags) of
    
    43
    -                                 ArchX86_64 -> bmiVersion dflags
    
    44
    -                                 ArchX86    -> bmiVersion dflags
    
    45
    -                                 _          -> Nothing
    
    46
    -
    
    47
    -     -- We assume  SSE1 and SSE2 operations are available on both
    
    48
    -     -- x86 and x86_64. Historically we didn't default to SSE2 and
    
    49
    -     -- SSE1 on x86, which results in defacto nondeterminism for how
    
    50
    -     -- rounding behaves in the associated x87 floating point instructions
    
    51
    -     -- because variations in the spill/fpu stack placement of arguments for
    
    52
    -     -- operations would change the precision and final result of what
    
    53
    -     -- would otherwise be the same expressions with respect to single or
    
    54
    -     -- double precision IEEE floating point computations.
    
    55
    -
    
    56
    -     -- ncgSseAvxVersion is set to the actual SSE/AVX version.
    
    57
    -     -- For example, -mfma does not set DynFlags's sseAvxVersion, but makes ncgSseAvxVersion >= AVX1.
    
    58
    -     -- See also Note [Implications between X86 CPU feature flags]
    
    59
    -   , ncgSseAvxVersion =
    
    60
    -      let v | isAvx2Enabled dflags = Just AVX2 -- -mavx512f does not set sseAvxVersion, but makes isAvx2Enabled true
    
    61
    -            | isAvxEnabled dflags  = Just AVX1 -- -mfma does not set sseAvxVersion, but makes isAvxEnabled true
    
    62
    -            | otherwise            = max (Just SSE2) (sseAvxVersion dflags)
    
    63
    -      in case platformArch (targetPlatform dflags) of
    
    64
    -            ArchX86_64 -> v
    
    65
    -            ArchX86    -> v
    
    66
    -            _          -> Nothing
    
    67
    -   , ncgAvx512fEnabled = isAvx512fEnabled dflags
    
    68
    -   , ncgAvx512vlEnabled = isAvx512vlEnabled dflags
    
    69
    -   , ncgAvx512bwEnabled = isAvx512bwEnabled dflags
    
    70
    -   , ncgAvx512dqEnabled = isAvx512dqEnabled dflags
    
    71
    -
    
    72
    -   , ncgLa664Enabled = isLa664Enabled dflags
    
    42
    +   , ncgCpuFeatures           = targetCpuFeatures dflags
    
    43
    +   , ncgLa664Enabled          = isLa664Enabled dflags
    
    73 44
     
    
    74 45
        , ncgDwarfEnabled        = osElfTarget (platformOS (targetPlatform dflags)) && debugLevel dflags > 0 && platformArch (targetPlatform dflags) /= ArchAArch64
    
    75 46
        , ncgDwarfUnwindings     = osElfTarget (platformOS (targetPlatform dflags)) && debugLevel dflags > 0
    

  • compiler/GHC/Driver/Config/CmmToLlvm.hs
    ... ... @@ -23,10 +23,7 @@ initLlvmCgConfig logger config_cache dflags = do
    23 23
         , llvmCgContext              = initSDocContext dflags PprCode
    
    24 24
         , llvmCgFillUndefWithGarbage = gopt Opt_LlvmFillUndefWithGarbage dflags
    
    25 25
         , llvmCgSplitSection         = gopt Opt_SplitSections dflags
    
    26
    -    , llvmCgBmiVersion           = case platformArch (targetPlatform dflags) of
    
    27
    -                                      ArchX86_64 -> bmiVersion dflags
    
    28
    -                                      ArchX86    -> bmiVersion dflags
    
    29
    -                                      _          -> Nothing
    
    26
    +    , llvmCgCpuFeatures          = targetCpuFeatures dflags
    
    30 27
         , llvmCgLlvmVersion          = version
    
    31 28
         , llvmCgDoWarn               = wopt Opt_WarnUnsupportedLlvmVersion dflags
    
    32 29
         , llvmCgLlvmTarget           = platformMisc_llvmTarget $! platformMisc dflags
    

  • compiler/GHC/Driver/Config/StgToCmm.hs
    ... ... @@ -12,6 +12,7 @@ import GHC.Cmm.MachOp ( FMASign(..))
    12 12
     import GHC.Driver.Backend
    
    13 13
     import GHC.Driver.Session
    
    14 14
     import GHC.Platform
    
    15
    +import GHC.Platform.CpuFeatures
    
    15 16
     import GHC.Platform.Profile
    
    16 17
     import GHC.Platform.Regs
    
    17 18
     import GHC.Utils.Error
    
    ... ... @@ -63,7 +64,7 @@ initStgToCmmConfig dflags mod = StgToCmmConfig
    63 64
       , stgToCmmAllowExtendedAddSubInstrs = (ncg && (x86ish || ppc)) || llvm
    
    64 65
       , stgToCmmAllowFMAInstr =
    
    65 66
           if
    
    66
    -        | not (isFmaEnabled dflags)
    
    67
    +        | not (cpuFmaEnabled cpu_feats)
    
    67 68
             || not (ncg || llvm)
    
    68 69
             -- If we're not using the native code generator or LLVM,
    
    69 70
             -- fall back to the generic implementation.
    
    ... ... @@ -81,12 +82,10 @@ initStgToCmmConfig dflags mod = StgToCmmConfig
    81 82
     
    
    82 83
       , stgToCmmAllowIntMul2Instr         = (ncg && (x86ish || aarch64)) || llvm
    
    83 84
       , stgToCmmAllowWordMul2Instr        = (ncg && (x86ish || ppc || aarch64)) || llvm
    
    84
    -  , stgToCmmAllowIntWord64X2MinMax    = (ncg && ((x86ish && isSse4_2Enabled dflags) || aarch64)) || llvm
    
    85
    +  , stgToCmmAllowIntWord64X2MinMax    = (ncg && (sse4_2 || aarch64)) || llvm
    
    85 86
       -- SIMD flags
    
    86 87
       , stgToCmmVecInstrsErr  = vec_err
    
    87
    -  , stgToCmmAvx           = isAvxEnabled                   dflags
    
    88
    -  , stgToCmmAvx2          = isAvx2Enabled                  dflags
    
    89
    -  , stgToCmmAvx512f       = isAvx512fEnabled               dflags
    
    88
    +  , stgToCmmCpuFeatures   = cpu_feats
    
    90 89
       , stgToCmmUseStdApThunk = not $ gopt Opt_Ticky_AP dflags
    
    91 90
       -- See Note [Saving foreign call target to local]
    
    92 91
       , stgToCmmSaveFCallTargetToLocal = any (callerSaves platform) $ activeStgRegs platform
    
    ... ... @@ -111,6 +110,10 @@ initStgToCmmConfig dflags mod = StgToCmmConfig
    111 110
                           ArchPPC      -> True
    
    112 111
                           ArchPPC_64 _ -> True
    
    113 112
                           _            -> False
    
    113
    +          cpu_feats = targetCpuFeatures dflags
    
    114
    +          sse4_2 = case cpu_feats of
    
    115
    +                     X86CpuFeatures feats -> x86Sse4_2Enabled feats
    
    116
    +                     _                    -> False
    
    114 117
               vec_err = case backendSimdValidity (backend dflags) of
    
    115 118
                           IsValid -> Nothing
    
    116 119
                           NotValid msg -> Just msg

  • compiler/GHC/Driver/DynFlags.hs
    ... ... @@ -78,23 +78,7 @@ module GHC.Driver.DynFlags (
    78 78
             initPromotionTickContext,
    
    79 79
     
    
    80 80
             -- * Platform features
    
    81
    -        isSse3Enabled,
    
    82
    -        isSsse3Enabled,
    
    83
    -        isSse4_1Enabled,
    
    84
    -        isSse4_2Enabled,
    
    85
    -        isAvxEnabled,
    
    86
    -        isAvx2Enabled,
    
    87
    -        isAvx512bwEnabled,
    
    88
    -        isAvx512cdEnabled,
    
    89
    -        isAvx512dqEnabled,
    
    90
    -        isAvx512erEnabled,
    
    91
    -        isAvx512fEnabled,
    
    92
    -        isAvx512pfEnabled,
    
    93
    -        isAvx512vlEnabled,
    
    94
    -        isFmaEnabled,
    
    95
    -        isGfniEnabled,
    
    96
    -        isBmiEnabled,
    
    97
    -        isBmi2Enabled,
    
    81
    +        targetCpuFeatures,
    
    98 82
             -- For LoongArch platform
    
    99 83
             isLa664Enabled
    
    100 84
     ) where
    
    ... ... @@ -102,6 +86,7 @@ module GHC.Driver.DynFlags (
    102 86
     import GHC.Prelude
    
    103 87
     
    
    104 88
     import GHC.Platform
    
    89
    +import GHC.Platform.CpuFeatures
    
    105 90
     import GHC.Platform.Ways
    
    106 91
     import GHC.Platform.Profile
    
    107 92
     
    
    ... ... @@ -460,18 +445,9 @@ data DynFlags = DynFlags {
    460 445
     
    
    461 446
       interactivePrint      :: Maybe String,
    
    462 447
     
    
    463
    -  -- | Machine dependent flags (-m\<blah> stuff)
    
    464
    -  sseAvxVersion         :: Maybe SseAvxVersion,
    
    465
    -  bmiVersion            :: Maybe BmiVersion,
    
    466
    -  avx512bw              :: Bool, -- ^ Enable AVX-512BW Instructions.
    
    467
    -  avx512cd              :: Bool, -- ^ Enable AVX-512 Conflict Detection Instructions.
    
    468
    -  avx512dq              :: Bool, -- ^ Enable AVX-512DQ Instructions.
    
    469
    -  avx512er              :: Bool, -- ^ Enable AVX-512 Exponential and Reciprocal Instructions.
    
    470
    -  avx512f               :: Bool, -- ^ Enable AVX-512 instructions.
    
    471
    -  avx512pf              :: Bool, -- ^ Enable AVX-512 PreFetch Instructions.
    
    472
    -  avx512vl              :: Bool, -- ^ Enable AVX-512VL Instructions.
    
    473
    -  fma                   :: Bool, -- ^ Enable FMA instructions.
    
    474
    -  gfni                  :: Bool, -- ^ Enable GFNI Instructions.
    
    448
    +  -- Machine dependent flags (-m\<blah> stuff)
    
    449
    +  cpuFeatures           :: EnumSet CpuFeature, -- ^ The @-m\<feature\>@ flags that were passed.
    
    450
    +                                               -- See Note [CPU features] in GHC.Platform.CpuFeatures.
    
    475 451
       la664                 :: Bool, -- ^ Enable LA664 instructions
    
    476 452
     
    
    477 453
       -- Constants used to control the amount of optimization done.
    
    ... ... @@ -751,18 +727,7 @@ defaultDynFlags mySettings =
    751 727
             profAuto = NoProfAuto,
    
    752 728
             callerCcFilters = [],
    
    753 729
             interactivePrint = Nothing,
    
    754
    -        sseAvxVersion = Nothing,
    
    755
    -        bmiVersion = Nothing,
    
    756
    -        avx512bw = False,
    
    757
    -        avx512cd = False,
    
    758
    -        avx512dq = False,
    
    759
    -        avx512er = False,
    
    760
    -        avx512f = False,
    
    761
    -        avx512pf = False,
    
    762
    -        avx512vl = False,
    
    763
    -        -- Use FMA by default on AArch64
    
    764
    -        fma = (platformArch . sTargetPlatform $ mySettings) == ArchAArch64,
    
    765
    -        gfni = False,
    
    730
    +        cpuFeatures = EnumSet.empty,
    
    766 731
             -- For LoongArch, la464 is used by default.
    
    767 732
             la664 = False,
    
    768 733
     
    
    ... ... @@ -1621,111 +1586,16 @@ initPromotionTickContext dflags =
    1621 1586
       }
    
    1622 1587
     
    
    1623 1588
     -- -----------------------------------------------------------------------------
    
    1624
    --- SSE, AVX, FMA
    
    1589
    +-- CPU features
    
    1625 1590
     
    
    1626
    -isSse3Enabled :: DynFlags -> Bool
    
    1627
    -isSse3Enabled dflags = sseAvxVersion dflags >= Just SSE3 || isAvxEnabled dflags
    
    1628
    -
    
    1629
    -isSsse3Enabled :: DynFlags -> Bool
    
    1630
    -isSsse3Enabled dflags = sseAvxVersion dflags >= Just SSSE3 || isAvxEnabled dflags
    
    1631
    -
    
    1632
    -isSse4_1Enabled :: DynFlags -> Bool
    
    1633
    -isSse4_1Enabled dflags = sseAvxVersion dflags >= Just SSE4 || isAvxEnabled dflags
    
    1634
    -
    
    1635
    -isSse4_2Enabled :: DynFlags -> Bool
    
    1636
    -isSse4_2Enabled dflags = sseAvxVersion dflags >= Just SSE42 || isAvxEnabled dflags
    
    1637
    -
    
    1638
    -isAvxEnabled :: DynFlags -> Bool
    
    1639
    -isAvxEnabled dflags = sseAvxVersion dflags >= Just AVX1 || (isX86 && fma dflags) || isAvx512fEnabled dflags
    
    1640
    -  where
    
    1641
    -    -- -mfma can be used on multiple platforms, but -mavx is x86-only
    
    1642
    -    isX86 = case platformArch (targetPlatform dflags) of
    
    1643
    -      ArchX86_64 -> True
    
    1644
    -      ArchX86    -> True
    
    1645
    -      _          -> False
    
    1646
    -
    
    1647
    -isAvx2Enabled :: DynFlags -> Bool
    
    1648
    -isAvx2Enabled dflags = sseAvxVersion dflags >= Just AVX2 || isAvx512fEnabled dflags
    
    1649
    -
    
    1650
    -isAvx512bwEnabled :: DynFlags -> Bool
    
    1651
    -isAvx512bwEnabled dflags = avx512bw dflags
    
    1652
    -
    
    1653
    -isAvx512cdEnabled :: DynFlags -> Bool
    
    1654
    -isAvx512cdEnabled dflags = avx512cd dflags
    
    1655
    -
    
    1656
    -isAvx512dqEnabled :: DynFlags -> Bool
    
    1657
    -isAvx512dqEnabled dflags = avx512dq dflags
    
    1658
    -
    
    1659
    -isAvx512erEnabled :: DynFlags -> Bool
    
    1660
    -isAvx512erEnabled dflags = avx512er dflags
    
    1661
    -
    
    1662
    -isAvx512fEnabled :: DynFlags -> Bool
    
    1663
    -isAvx512fEnabled dflags = avx512f dflags || avx512bw dflags || avx512cd dflags || avx512dq dflags || avx512er dflags || avx512pf dflags || avx512vl dflags
    
    1664
    -
    
    1665
    -isAvx512pfEnabled :: DynFlags -> Bool
    
    1666
    -isAvx512pfEnabled dflags = avx512pf dflags
    
    1667
    -
    
    1668
    -isAvx512vlEnabled :: DynFlags -> Bool
    
    1669
    -isAvx512vlEnabled dflags = avx512vl dflags
    
    1670
    -
    
    1671
    -isFmaEnabled :: DynFlags -> Bool
    
    1672
    -isFmaEnabled dflags = fma dflags || (isX86 && isAvx512fEnabled dflags)
    
    1673
    -  where
    
    1674
    -    -- -mfma is used on multiple platforms, but -mavx512f is x86-only
    
    1675
    -    isX86 = case platformArch (targetPlatform dflags) of
    
    1676
    -      ArchX86_64 -> True
    
    1677
    -      ArchX86    -> True
    
    1678
    -      _          -> False
    
    1679
    -
    
    1680
    -isGfniEnabled :: DynFlags -> Bool
    
    1681
    -isGfniEnabled dflags = gfni dflags
    
    1682
    -
    
    1683
    -{- Note [Implications between X86 CPU feature flags]
    
    1684
    -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    1685
    -Many X86 CPU feature flags (such as -mavx, -mfma or -msse4) imply other
    
    1686
    -feature flags. In particular, there are straightforward linear implication
    
    1687
    -structures:
    
    1688
    -
    
    1689
    -  1. AVX2 -> AVX -> SSE4.2 -> SSE4 -> SSSE3 -> SSE3 -> SSE2 -> SSE1
    
    1690
    -  2. BMI2 -> BMI1
    
    1691
    -
    
    1692
    -together with other implications such as
    
    1693
    -
    
    1694
    -  3. FMA -> AVX
    
    1695
    -  4. AVX512{BW,CD,DQ,ER,PF,VL} -> AVX512F -> AVX2
    
    1696
    -
    
    1697
    -
    
    1698
    -We handle this as follows:
    
    1699
    -
    
    1700
    -  A. When parsing command line options into `DynFlags`, we record:
    
    1701
    -    - an `SseAvxVersion` which gives the SSE/AVX level supported in
    
    1702
    -      the total order (1),
    
    1703
    -    - a `BmiVersion` for (2),
    
    1704
    -    - whether FMA is enabled,
    
    1705
    -    - various AVX512 flags saying which AVX512 extensions are supported
    
    1706
    -
    
    1707
    -  B. When converting these "raw" `DynFlags` into a `CmmConfig` for use
    
    1708
    -     in code generator backends, we handle the remaining implications (3) (4),
    
    1709
    -     e.g. if the user passed -mavx512f then we also set the `SseAvxVersion`
    
    1710
    -     to `AVX2`.
    
    1711
    --}
    
    1591
    +-- | The CPU features enabled for the target.
    
    1592
    +--
    
    1593
    +-- See Note [CPU features] in GHC.Platform.CpuFeatures.
    
    1594
    +targetCpuFeatures :: DynFlags -> CpuFeatures
    
    1595
    +targetCpuFeatures dflags
    
    1596
    +  = initCpuFeatures (platformArch (targetPlatform dflags)) (cpuFeatures dflags)
    
    1712 1597
     
    
    1713 1598
     -- -----------------------------------------------------------------------------
    
    1714 1599
     -- LA664
    
    1715 1600
     isLa664Enabled :: DynFlags -> Bool
    
    1716 1601
     isLa664Enabled dflags = la664 dflags
    1717
    -
    
    1718
    --- -----------------------------------------------------------------------------
    
    1719
    --- BMI2
    
    1720
    -
    
    1721
    -isBmiEnabled :: DynFlags -> Bool
    
    1722
    -isBmiEnabled dflags = case platformArch (targetPlatform dflags) of
    
    1723
    -    ArchX86_64 -> bmiVersion dflags >= Just BMI1
    
    1724
    -    ArchX86    -> bmiVersion dflags >= Just BMI1
    
    1725
    -    _          -> False
    
    1726
    -
    
    1727
    -isBmi2Enabled :: DynFlags -> Bool
    
    1728
    -isBmi2Enabled dflags = case platformArch (targetPlatform dflags) of
    
    1729
    -    ArchX86_64 -> bmiVersion dflags >= Just BMI2
    
    1730
    -    ArchX86    -> bmiVersion dflags >= Just BMI2
    
    1731
    -    _          -> False

  • compiler/GHC/Driver/Pipeline/Execute.hs
    ... ... @@ -39,6 +39,7 @@ import GHC.Fingerprint
    39 39
     import GHC.Utils.Logger
    
    40 40
     import GHC.Utils.TmpFs
    
    41 41
     import GHC.Platform
    
    42
    +import GHC.Platform.CpuFeatures
    
    42 43
     import Data.List (intercalate, isInfixOf)
    
    43 44
     import qualified Data.List.NonEmpty as NE
    
    44 45
     import GHC.Unit.Env
    
    ... ... @@ -968,35 +969,46 @@ llvmOptions llvm_config llvm_version dflags =
    968 969
             arch = platformArch platform
    
    969 970
     
    
    970 971
             attrs :: String
    
    971
    -        attrs = intercalate "," $ mattr
    
    972
    -              ++ ["+sse4.2"  | isSse4_2Enabled dflags   ]
    
    973
    -              ++ ["+popcnt"  | isSse4_2Enabled dflags   ]
    
    974
    -                   -- LLVM gates POPCNT instructions behind the popcnt flag,
    
    975
    -                   -- while the GHC NCG (as well as GCC, Clang) gates it
    
    976
    -                   -- behind SSE4.2 instead.
    
    977
    -              ++ ["+sse4.1"  | isSse4_1Enabled dflags   ]
    
    978
    -              ++ ["+ssse3"   | isSsse3Enabled dflags    ]
    
    979
    -              ++ ["+sse3"    | isSse3Enabled dflags     ]
    
    980
    -              ++ ["+sse2"    | isSse2Enabled platform   ]
    
    981
    -              ++ ["+sse"     | isSseEnabled platform    ]
    
    982
    -              ++ ["+avx512f" | isAvx512fEnabled dflags  ]
    
    983
    -              ++ ["+evex512" | isAvx512fEnabled dflags
    
    984
    -                             , maybe False (>= LlvmVersion (18 NE.:| [])) llvm_version ]
    
    985
    -                   -- +evex512 is recognized by LLVM 18 or newer and needed on macOS (#26410).
    
    986
    -                   -- It may become deprecated in a future LLVM version, though.
    
    987
    -              ++ ["+avx2"    | isAvx2Enabled dflags     ]
    
    988
    -              ++ ["+avx"     | isAvxEnabled dflags      ]
    
    989
    -              ++ ["+avx512bw"| isAvx512bwEnabled dflags ]
    
    990
    -              ++ ["+avx512cd"| isAvx512cdEnabled dflags ]
    
    991
    -              ++ ["+avx512dq"| isAvx512dqEnabled dflags ]
    
    992
    -              ++ ["+avx512er"| isAvx512erEnabled dflags ]
    
    993
    -              ++ ["+avx512pf"| isAvx512pfEnabled dflags ]
    
    994
    -              ++ ["+avx512vl"| isAvx512vlEnabled dflags ]
    
    995
    -              -- For AArch64 +fma is not a option (it's unconditionally available).
    
    996
    -              ++ ["+fma"     | isFmaEnabled dflags && (arch /= ArchAArch64) ]
    
    997
    -              ++ ["+bmi"     | isBmiEnabled dflags      ]
    
    998
    -              ++ ["+bmi2"    | isBmi2Enabled dflags     ]
    
    999
    -              ++ ["+gfni"    | isGfniEnabled dflags     ]
    
    972
    +        attrs = intercalate "," $ mattr ++ cpu_attrs
    
    973
    +
    
    974
    +        cpu_attrs :: [String]
    
    975
    +        cpu_attrs = case targetCpuFeatures dflags of
    
    976
    +          X86CpuFeatures feats@(X86Features { x86SseAvx = sseAvx, x86Bmi = bmi, x86Gfni = gfni }) ->
    
    977
    +            let sse    = x86SseVersion sseAvx
    
    978
    +                avx512 = x86Avx512Exts sseAvx
    
    979
    +            in [ "+sse"     | sse >= SSE1  ]
    
    980
    +            ++ [ "+sse2"    | sse >= SSE2  ]
    
    981
    +            ++ [ "+sse3"    | sse >= SSE3  ]
    
    982
    +            ++ [ "+ssse3"   | sse >= SSSE3 ]
    
    983
    +            ++ [ "+sse4.1"  | sse >= SSE4  ]
    
    984
    +            ++ [ "+sse4.2"  | sse >= SSE42 ]
    
    985
    +            ++ [ "+popcnt"  | sse >= SSE42 ]
    
    986
    +                 -- LLVM gates POPCNT instructions behind the popcnt flag,
    
    987
    +                 -- while the GHC NCG (as well as GCC, Clang) gates it
    
    988
    +                 -- behind SSE4.2 instead.
    
    989
    +            ++ [ "+avx"     | x86AvxEnabled feats ]
    
    990
    +            ++ [ "+avx2"    | x86Avx2Enabled feats ]
    
    991
    +            ++ [ "+fma"     | x86FmaEnabled feats ]
    
    992
    +            ++ ( case avx512 of
    
    993
    +                   Nothing -> []
    
    994
    +                   Just (Avx512Exts { avx512bw = bw, avx512cd = cd, avx512dq = dq
    
    995
    +                                    , avx512er = er, avx512pf = pf, avx512vl = vl }) ->
    
    996
    +                        [ "+avx512f" ]
    
    997
    +                     ++ [ "+evex512" | maybe False (>= LlvmVersion (18 NE.:| [])) llvm_version ]
    
    998
    +                          -- +evex512 is recognized by LLVM 18 or newer and needed on macOS (#26410).
    
    999
    +                          -- It may become deprecated in a future LLVM version, though.
    
    1000
    +                     ++ [ "+avx512bw" | bw ]
    
    1001
    +                     ++ [ "+avx512cd" | cd ]
    
    1002
    +                     ++ [ "+avx512dq" | dq ]
    
    1003
    +                     ++ [ "+avx512er" | er ]
    
    1004
    +                     ++ [ "+avx512pf" | pf ]
    
    1005
    +                     ++ [ "+avx512vl" | vl ] )
    
    1006
    +            ++ [ "+bmi"     | bmi >= Just BMI1 ]
    
    1007
    +            ++ [ "+bmi2"    | bmi >= Just BMI2 ]
    
    1008
    +            ++ [ "+gfni"    | gfni ]
    
    1009
    +          GenericCpuFeatures { genericFma = fma } ->
    
    1010
    +            -- For AArch64 +fma is not a option (it's unconditionally available).
    
    1011
    +            [ "+fma" | fma && arch /= ArchAArch64 ]
    
    1000 1012
     
    
    1001 1013
             abi :: String
    
    1002 1014
             abi = case platformArch (targetPlatform dflags) of
    

  • compiler/GHC/Driver/Session.hs
    ... ... @@ -204,24 +204,8 @@ module GHC.Driver.Session (
    204 204
     
    
    205 205
             setUnsafeGlobalDynFlags,
    
    206 206
     
    
    207
    -        -- * SSE and AVX
    
    208
    -        isSse3Enabled,
    
    209
    -        isSsse3Enabled,
    
    210
    -        isSse4_1Enabled,
    
    211
    -        isSse4_2Enabled,
    
    212
    -        isBmiEnabled,
    
    213
    -        isBmi2Enabled,
    
    214
    -        isAvxEnabled,
    
    215
    -        isAvx2Enabled,
    
    216
    -        isAvx512bwEnabled,
    
    217
    -        isAvx512cdEnabled,
    
    218
    -        isAvx512dqEnabled,
    
    219
    -        isAvx512erEnabled,
    
    220
    -        isAvx512fEnabled,
    
    221
    -        isAvx512pfEnabled,
    
    222
    -        isAvx512vlEnabled,
    
    223
    -        isFmaEnabled,
    
    224
    -        isGfniEnabled,
    
    207
    +        -- * CPU features
    
    208
    +        targetCpuFeatures,
    
    225 209
     
    
    226 210
             -- LoongArch: ISA version: la664, la464(default)
    
    227 211
             isLa664Enabled,
    
    ... ... @@ -241,6 +225,7 @@ module GHC.Driver.Session (
    241 225
     import GHC.Prelude
    
    242 226
     
    
    243 227
     import GHC.Platform
    
    228
    +import GHC.Platform.CpuFeatures
    
    244 229
     import GHC.Platform.Ways
    
    245 230
     import GHC.Platform.Profile
    
    246 231
     import GHC.Platform.ArchOS
    
    ... ... @@ -1724,40 +1709,6 @@ dynamic_flags_deps = [
    1724 1709
             (setDumpFlag Opt_D_dump_faststrings)
    
    1725 1710
     
    
    1726 1711
             ------ Machine dependent (-m<blah>) stuff ---------------------------
    
    1727
    -        -- See Note [Implications between X86 CPU feature flags]
    
    1728
    -
    
    1729
    -  , make_ord_flag defGhcFlag "msse"         (noArg (\d ->
    
    1730
    -                                                  d { sseAvxVersion = max (Just SSE1) (sseAvxVersion d) }))
    
    1731
    -  , make_ord_flag defGhcFlag "msse2"        (noArg (\d ->
    
    1732
    -                                                  d { sseAvxVersion = max (Just SSE2) (sseAvxVersion d) }))
    
    1733
    -  , make_ord_flag defGhcFlag "msse3"        (noArg (\d ->
    
    1734
    -                                                  d { sseAvxVersion = max (Just SSE3) (sseAvxVersion d) }))
    
    1735
    -  , make_ord_flag defGhcFlag "mssse3"       (noArg (\d ->
    
    1736
    -                                                  d { sseAvxVersion = max (Just SSSE3) (sseAvxVersion d) }))
    
    1737
    -  , make_ord_flag defGhcFlag "msse4"        (noArg (\d ->
    
    1738
    -                                                  d { sseAvxVersion = max (Just SSE4) (sseAvxVersion d) }))
    
    1739
    -  , make_ord_flag defGhcFlag "msse4.2"      (noArg (\d ->
    
    1740
    -                                                 d { sseAvxVersion = max (Just SSE42) (sseAvxVersion d) }))
    
    1741
    -  , make_ord_flag defGhcFlag "mbmi"         (noArg (\d ->
    
    1742
    -                                                 d { bmiVersion = max (Just BMI1) (bmiVersion d) }))
    
    1743
    -  , make_ord_flag defGhcFlag "mbmi2"        (noArg (\d ->
    
    1744
    -                                                 d { bmiVersion = Just BMI2 }))
    
    1745
    -  , make_ord_flag defGhcFlag "mavx"         (noArg (\d ->
    
    1746
    -                                                 d { sseAvxVersion = max (Just AVX1) (sseAvxVersion d) }))
    
    1747
    -  , make_ord_flag defGhcFlag "mavx2"        (noArg (\d ->
    
    1748
    -                                                 d { sseAvxVersion = max (Just AVX2) (sseAvxVersion d) }))
    
    1749
    -  , make_ord_flag defGhcFlag "mavx512bw"    (noArg (\d -> d { avx512bw = True }))
    
    1750
    -  , make_ord_flag defGhcFlag "mavx512cd"    (noArg (\d -> d { avx512cd = True }))
    
    1751
    -  , make_ord_flag defGhcFlag "mavx512dq"    (noArg (\d -> d { avx512dq = True }))
    
    1752
    -  , make_dep_flag defGhcFlag "mavx512er"    (noArg (\d -> d { avx512er = True }))
    
    1753
    -        "AVX-512ER was only available on Xeon Phi"
    
    1754
    -  , make_ord_flag defGhcFlag "mavx512f"     (noArg (\d -> d { avx512f = True }))
    
    1755
    -  , make_dep_flag defGhcFlag "mavx512pf"    (noArg (\d -> d { avx512pf = True }))
    
    1756
    -        "AVX-512PF was only available on Xeon Phi"
    
    1757
    -  , make_ord_flag defGhcFlag "mavx512vl"    (noArg (\d -> d { avx512vl = True }))
    
    1758
    -  , make_ord_flag defGhcFlag "mfma"         (noArg (\d -> d { fma = True }))
    
    1759
    -  , make_ord_flag defGhcFlag "mgfni"        (noArg (\d -> d { gfni = True }))
    
    1760
    -
    
    1761 1712
     
    
    1762 1713
       , make_ord_flag defGhcFlag "mla664"       (noArg (\d -> d { la664 = True }))
    
    1763 1714
     
    
    ... ... @@ -2021,6 +1972,11 @@ dynamic_flags_deps = [
    2021 1972
              ------ Debugging flags ----------------------------------------------
    
    2022 1973
       , make_ord_flag defGhcFlag "g"             (OptIntSuffix setDebugLevel)
    
    2023 1974
      ]
    
    1975
    +         ------ CPU features -------------------------------------------------
    
    1976
    + ++ map cpuFeatureFlagDep [minBound .. maxBound]
    
    1977
    +
    
    1978
    +         ------ Negation -----------------------------------------------------
    
    1979
    +
    
    2024 1980
      ++ map (mkFlag turnOn  ""          setGeneralFlag    ) negatableFlagsDeps
    
    2025 1981
      ++ map (mkFlag turnOff "no-"       unSetGeneralFlag  ) negatableFlagsDeps
    
    2026 1982
      ++ map (mkFlag turnOn  "d"         setGeneralFlag    ) dFlagsDeps
    
    ... ... @@ -2975,6 +2931,18 @@ optIntSuffixM fn = OptIntSuffix (\mi -> updM (fn mi))
    2975 2931
     setDumpFlag :: DumpFlag -> OptKind (CmdLineP DynFlags)
    
    2976 2932
     setDumpFlag dump_flag = NoArg (setDumpFlag' dump_flag)
    
    2977 2933
     
    
    2934
    +setCpuFeature :: CpuFeature -> DynFlags -> DynFlags
    
    2935
    +setCpuFeature feat dflags = dflags { cpuFeatures = EnumSet.insert feat (cpuFeatures dflags) }
    
    2936
    +
    
    2937
    +-- | The @-m\<feature\>@ flag for a 'CpuFeature'.
    
    2938
    +cpuFeatureFlagDep :: CpuFeature -> (Deprecation, Flag (CmdLineP DynFlags))
    
    2939
    +cpuFeatureFlagDep feat =
    
    2940
    +  case cpuFeatureFlag feat of
    
    2941
    +    (name, Nothing ) -> make_ord_flag defGhcFlag ('m' : name) set
    
    2942
    +    (name, Just msg) -> make_dep_flag defGhcFlag ('m' : name) set msg
    
    2943
    +  where
    
    2944
    +    set = noArg (setCpuFeature feat)
    
    2945
    +
    
    2978 2946
     --------------------------
    
    2979 2947
     addWayDynP :: Way -> DynP ()
    
    2980 2948
     addWayDynP = upd . addWay'
    

  • compiler/GHC/Platform.hs
    ... ... @@ -29,12 +29,7 @@ module GHC.Platform
    29 29
        , platformCConvNeedsExtension
    
    30 30
        , platformHasRTSLinker
    
    31 31
        , PlatformMisc(..)
    
    32
    -   , SseAvxVersion (..)
    
    33
    -   , BmiVersion (..)
    
    34 32
        , wordAlignment
    
    35
    -   -- * SSE and AVX
    
    36
    -   , isSseEnabled
    
    37
    -   , isSse2Enabled
    
    38 33
        -- * Platform constants
    
    39 34
        , PlatformConstants(..)
    
    40 35
        , lookupPlatformConstants
    
    ... ... @@ -116,33 +111,6 @@ data Platform = Platform
    116 111
     wordAlignment :: Platform -> Alignment
    
    117 112
     wordAlignment platform = alignmentOf (platformWordSizeInBytes platform)
    
    118 113
     
    
    119
    --- -----------------------------------------------------------------------------
    
    120
    --- SSE and AVX
    
    121
    -
    
    122
    --- TODO: Instead of using a separate predicate (i.e. isSse2Enabled) to
    
    123
    --- check if SSE is enabled, we might have x86-64 imply the -msse2
    
    124
    --- flag.
    
    125
    -
    
    126
    -isSseEnabled :: Platform -> Bool
    
    127
    -isSseEnabled platform = case platformArch platform of
    
    128
    -    ArchX86_64 -> True
    
    129
    -    ArchX86    -> True
    
    130
    -    _          -> False
    
    131
    -
    
    132
    -isSse2Enabled :: Platform -> Bool
    
    133
    -isSse2Enabled platform = case platformArch platform of
    
    134
    -  -- We assume  SSE1 and SSE2 operations are available on both
    
    135
    -  -- x86 and x86_64. Historically we didn't default to SSE2 and
    
    136
    -  -- SSE1 on x86, which results in defacto nondeterminism for how
    
    137
    -  -- rounding behaves in the associated x87 floating point instructions
    
    138
    -  -- because variations in the spill/fpu stack placement of arguments for
    
    139
    -  -- operations would change the precision and final result of what
    
    140
    -  -- would otherwise be the same expressions with respect to single or
    
    141
    -  -- double precision IEEE floating point computations.
    
    142
    -    ArchX86_64 -> True
    
    143
    -    ArchX86    -> True
    
    144
    -    _          -> False
    
    145
    -
    
    146 114
     -- -----------------------------------------------------------------------------
    
    147 115
     -- Platform Constants
    
    148 116
     
    
    ... ... @@ -279,28 +247,6 @@ platformHasRTSLinker p = case archOS_arch (platformArchOS p) of
    279 247
     
    
    280 248
     
    
    281 249
     
    
    282
    ---------------------------------------------------
    
    283
    --- Instruction sets
    
    284
    ---------------------------------------------------
    
    285
    -
    
    286
    --- | x86 SSE and AVX instructions
    
    287
    -data SseAvxVersion
    
    288
    -   = SSE1
    
    289
    -   | SSE2
    
    290
    -   | SSE3
    
    291
    -   | SSSE3
    
    292
    -   | SSE4
    
    293
    -   | SSE42
    
    294
    -   | AVX1
    
    295
    -   | AVX2
    
    296
    -   deriving (Eq, Ord)
    
    297
    -
    
    298
    --- | x86 BMI (bit manipulation) instructions
    
    299
    -data BmiVersion
    
    300
    -   = BMI1
    
    301
    -   | BMI2
    
    302
    -   deriving (Eq, Ord)
    
    303
    -
    
    304 250
     -- | Platform-specific settings formerly hard-coded in Config.hs.
    
    305 251
     --
    
    306 252
     -- These should probably be all be triaged whether they can be computed from
    

  • compiler/GHC/Platform/CpuFeatures.hs
    1
    +{-# LANGUAGE LambdaCase #-}
    
    2
    +
    
    3
    +-- | CPU features and corresponding @-m\<feature\>@ flags.
    
    4
    +--
    
    5
    +-- See Note [CPU features].
    
    6
    +module GHC.Platform.CpuFeatures
    
    7
    +  ( -- * Feature flags
    
    8
    +    CpuFeature (..)
    
    9
    +  , cpuFeatureFlag
    
    10
    +
    
    11
    +    -- * Enabled instruction sets
    
    12
    +  , CpuFeatures (..)
    
    13
    +  , initCpuFeatures
    
    14
    +  , cpuFmaEnabled
    
    15
    +
    
    16
    +    -- ** x86
    
    17
    +  , X86Features (..)
    
    18
    +  , SseAvxVersion (..)
    
    19
    +  , AvxLevel (..)
    
    20
    +  , x86SseVersion
    
    21
    +  , x86Avx512Exts
    
    22
    +  , sseAvxVersionIncludes
    
    23
    +  , unionSseAvxVersion
    
    24
    +  , sseAvxVectorRequirement
    
    25
    +  , x86BaselineSseAvx
    
    26
    +  , sseAvxVersionFlags
    
    27
    +  , SseVersion (..)
    
    28
    +  , Avx512Exts (..)
    
    29
    +  , noAvx512Exts
    
    30
    +  , BmiVersion (..)
    
    31
    +
    
    32
    +    -- *** Querying x86 features
    
    33
    +    -- | These are not independent; see Note [CPU features].
    
    34
    +  , x86Ssse3Enabled
    
    35
    +  , x86Sse4_1Enabled
    
    36
    +  , x86Sse4_2Enabled
    
    37
    +  , x86AvxEnabled
    
    38
    +  , x86Avx2Enabled
    
    39
    +  , x86FmaEnabled
    
    40
    +  , x86Avx512FEnabled
    
    41
    +  , x86Avx512DQEnabled
    
    42
    +  , x86Avx512VLEnabled
    
    43
    +  , x86Bmi2Enabled
    
    44
    +  )
    
    45
    +where
    
    46
    +
    
    47
    +import GHC.Prelude
    
    48
    +
    
    49
    +import GHC.Platform.ArchOS
    
    50
    +import GHC.Data.EnumSet (EnumSet)
    
    51
    +import qualified GHC.Data.EnumSet as EnumSet
    
    52
    +
    
    53
    +import Data.Maybe (isJust)
    
    54
    +
    
    55
    +{- Note [CPU features]
    
    56
    +~~~~~~~~~~~~~~~~~~~~~~
    
    57
    +The -m<feature> flags enable CPU instruction set extensions. Many of them imply
    
    58
    +others:
    
    59
    +
    
    60
    +  1. AVX2 -> AVX -> SSE4.2 -> SSE4 -> SSSE3 -> SSE3 -> SSE2 -> SSE1
    
    61
    +  2. BMI2 -> BMI1
    
    62
    +  3. FMA -> AVX    (on X86)
    
    63
    +  4. AVX512{BW,CD,DQ,ER,PF,VL} -> AVX512F -> AVX2 + FMA
    
    64
    +
    
    65
    +We keep two representations:
    
    66
    +
    
    67
    +  A. 'DynFlags' records the set of flags that were passed, as an
    
    68
    +     'EnumSet' of 'CpuFeature'. Nothing is implied at this stage.
    
    69
    +
    
    70
    +  B. 'initCpuFeatures' turns this set into a 'CpuFeatures' value, applying the
    
    71
    +     implications and the baseline of the target architecture. This
    
    72
    +     representation makes the implications structural: 'SseAvxVersion' is a
    
    73
    +     point in the total order (1), FMA can only be recorded together with AVX,
    
    74
    +     and AVX-512 sits above AVX2 and FMA.
    
    75
    +
    
    76
    +Code generation and the driver only consult the second representation, so
    
    77
    +whether an instruction set is enabled is decided in one place.
    
    78
    +-}
    
    79
    +
    
    80
    +-- | A CPU feature flag, @-m\<feature\>@.
    
    81
    +data CpuFeature
    
    82
    +  = Feat_SSE
    
    83
    +  | Feat_SSE2
    
    84
    +  | Feat_SSE3
    
    85
    +  | Feat_SSSE3
    
    86
    +  | Feat_SSE4
    
    87
    +  | Feat_SSE4_2
    
    88
    +  | Feat_AVX
    
    89
    +  | Feat_AVX2
    
    90
    +  | Feat_AVX512F
    
    91
    +  | Feat_AVX512BW
    
    92
    +  | Feat_AVX512CD
    
    93
    +  | Feat_AVX512DQ
    
    94
    +  | Feat_AVX512ER
    
    95
    +  | Feat_AVX512PF
    
    96
    +  | Feat_AVX512VL
    
    97
    +  | Feat_FMA
    
    98
    +  | Feat_BMI
    
    99
    +  | Feat_BMI2
    
    100
    +  | Feat_GFNI
    
    101
    +  deriving (Eq, Show, Enum, Bounded)
    
    102
    +
    
    103
    +-- | The name of the @-m\<feature\>@ flag for a 'CpuFeature' (without the
    
    104
    +-- leading @m@).
    
    105
    +--
    
    106
    +-- Additionally returns an optional deprecation message.
    
    107
    +cpuFeatureFlag :: CpuFeature -> (String, Maybe String)
    
    108
    +cpuFeatureFlag = \case
    
    109
    +  Feat_SSE      -> ("sse"      , Nothing)
    
    110
    +  Feat_SSE2     -> ("sse2"     , Nothing)
    
    111
    +  Feat_SSE3     -> ("sse3"     , Nothing)
    
    112
    +  Feat_SSSE3    -> ("ssse3"    , Nothing)
    
    113
    +  Feat_SSE4     -> ("sse4"     , Nothing)
    
    114
    +  Feat_SSE4_2   -> ("sse4.2"   , Nothing)
    
    115
    +  Feat_AVX      -> ("avx"      , Nothing)
    
    116
    +  Feat_AVX2     -> ("avx2"     , Nothing)
    
    117
    +  Feat_AVX512F  -> ("avx512f"  , Nothing)
    
    118
    +  Feat_AVX512BW -> ("avx512bw" , Nothing)
    
    119
    +  Feat_AVX512CD -> ("avx512cd" , Nothing)
    
    120
    +  Feat_AVX512DQ -> ("avx512dq" , Nothing)
    
    121
    +  Feat_AVX512ER -> ("avx512er" , Just "AVX-512ER was only available on Xeon Phi")
    
    122
    +  Feat_AVX512PF -> ("avx512pf" , Just "AVX-512PF was only available on Xeon Phi")
    
    123
    +  Feat_AVX512VL -> ("avx512vl" , Nothing)
    
    124
    +  Feat_FMA      -> ("fma"      , Nothing)
    
    125
    +  Feat_BMI      -> ("bmi"      , Nothing)
    
    126
    +  Feat_BMI2     -> ("bmi2"     , Nothing)
    
    127
    +  Feat_GFNI     -> ("gfni"     , Nothing)
    
    128
    +
    
    129
    +-- | The CPU features that are enabled for the target.
    
    130
    +--
    
    131
    +-- See Note [CPU features].
    
    132
    +data CpuFeatures
    
    133
    +  -- | x86 and x86_64 CPU features.
    
    134
    +  = X86CpuFeatures !X86Features
    
    135
    +  -- | A generic set of CPU features.
    
    136
    +  --
    
    137
    +  -- For now, code generation for non-X86 architectures assumes a fixed
    
    138
    +  -- baseline ISA, with the only exception of FMA support.
    
    139
    +  --
    
    140
    +  -- In the future, we can add architecture-specific constructors, e.g. for
    
    141
    +  -- RISC-V (vector support, bit manipulation, etc).
    
    142
    +  | GenericCpuFeatures
    
    143
    +    { genericFma :: !Bool -- ^ are FMA operations enabled?
    
    144
    +    }
    
    145
    +  deriving (Eq, Show)
    
    146
    +
    
    147
    +-- | The CPU features enabled by the given flags on the given architecture.
    
    148
    +--
    
    149
    +-- See Note [CPU features].
    
    150
    +initCpuFeatures :: Arch -> EnumSet CpuFeature -> CpuFeatures
    
    151
    +initCpuFeatures arch feats = case arch of
    
    152
    +  ArchX86     -> X86CpuFeatures (initX86Features feats)
    
    153
    +  ArchX86_64  -> X86CpuFeatures (initX86Features feats)
    
    154
    +  -- AArch64 always has fused multiply-add instructions.
    
    155
    +  ArchAArch64 -> GenericCpuFeatures { genericFma = True }
    
    156
    +  _           -> GenericCpuFeatures { genericFma = EnumSet.member Feat_FMA feats }
    
    157
    +
    
    158
    +-- | Whether fused multiply-add instructions are enabled.
    
    159
    +cpuFmaEnabled :: CpuFeatures -> Bool
    
    160
    +cpuFmaEnabled = \case
    
    161
    +  X86CpuFeatures feats                    -> x86FmaEnabled feats
    
    162
    +  GenericCpuFeatures { genericFma = fma } -> fma
    
    163
    +
    
    164
    +--------------------------------------------------------------------------------
    
    165
    +-- x86
    
    166
    +
    
    167
    +-- | The x86 CPU features that are enabled.
    
    168
    +data X86Features = X86Features
    
    169
    +  { x86SseAvx :: !SseAvxVersion
    
    170
    +  , x86Bmi    :: !(Maybe BmiVersion)
    
    171
    +  , x86Gfni   :: !Bool
    
    172
    +  }
    
    173
    +  deriving (Eq, Show)
    
    174
    +
    
    175
    +-- | Enabled SSE/AVX instruction sets, and whether FMA is enabled.
    
    176
    +--
    
    177
    +-- See Note [CPU features].
    
    178
    +data SseAvxVersion
    
    179
    +  -- | SSE, but no AVX (and thus no FMA).
    
    180
    +  = Sse !SseVersion
    
    181
    +  -- | AVX, and potentially more (AVX2, FMA, etc).
    
    182
    +  | Avx !AvxLevel
    
    183
    +  deriving (Eq, Show)
    
    184
    +-- NB: no 'Ord' instance, as this is only a partial order.
    
    185
    +-- See 'sseAvxVersionIncludes'.
    
    186
    +
    
    187
    +-- | Level of enabled AVX instruction sets, and whether FMA is enabled.
    
    188
    +data AvxLevel
    
    189
    +  -- | AVX (with or without FMA).
    
    190
    +  = Avx1 { avxFma :: !Bool }
    
    191
    +  -- | AVX2 (with or without FMA).
    
    192
    +  | Avx2 { avxFma :: !Bool }
    
    193
    +  -- | AVX-512F (which includes AVX2 and FMA), with the given extensions.
    
    194
    +  | Avx512 !Avx512Exts
    
    195
    +  deriving (Eq, Show)
    
    196
    +
    
    197
    +-- | x86 SSE instruction sets (each including the previous ones).
    
    198
    +data SseVersion
    
    199
    +  = SSE1
    
    200
    +  | SSE2
    
    201
    +  | SSE3
    
    202
    +  | SSSE3
    
    203
    +  | SSE4
    
    204
    +  | SSE42
    
    205
    +  deriving (Eq, Ord, Show)
    
    206
    +
    
    207
    +-- | The AVX-512 extensions beyond AVX-512F.
    
    208
    +data Avx512Exts = Avx512Exts
    
    209
    +  { avx512bw :: !Bool -- ^ byte and word operations
    
    210
    +  , avx512cd :: !Bool -- ^ conflict detection
    
    211
    +  , avx512dq :: !Bool -- ^ doubleword and quadword operations
    
    212
    +  , avx512er :: !Bool -- ^ exponential and reciprocal
    
    213
    +  , avx512pf :: !Bool -- ^ prefetch
    
    214
    +  , avx512vl :: !Bool -- ^ AVX-512 instructions on 128-bit and 256-bit vectors
    
    215
    +  }
    
    216
    +  deriving (Eq, Show)
    
    217
    +
    
    218
    +noAvx512Exts :: Avx512Exts
    
    219
    +noAvx512Exts = Avx512Exts False False False False False False
    
    220
    +
    
    221
    +-- | x86 BMI (bit manipulation) instruction sets (BMI2 including BMI1).
    
    222
    +data BmiVersion
    
    223
    +  = BMI1
    
    224
    +  | BMI2
    
    225
    +  deriving (Eq, Ord, Show)
    
    226
    +
    
    227
    +
    
    228
    +-- | The baseline ISA that we assume for both x86 and x86_64: SSE2.
    
    229
    +--
    
    230
    +-- Historical remark: prior to GHC 8.10, we used to not require SSE2 on 32-bit
    
    231
    +-- x86 architectures. This resulted in defacto nondeterminism for rounding
    
    232
    +-- behaviour due to oddities of the x87 stack-based floating-point implementation.
    
    233
    +x86BaselineSseAvx :: SseAvxVersion
    
    234
    +x86BaselineSseAvx = Sse SSE2
    
    235
    +
    
    236
    +-- | Enable the user-specified features, on top of the X86 baseline feature set
    
    237
    +-- ('x86BaselineSseAvx').
    
    238
    +--
    
    239
    +-- The implication structure of CPU feature flags is detailed in Note [CPU features].
    
    240
    +initX86Features
    
    241
    +  :: EnumSet CpuFeature -- ^ user-enabled features
    
    242
    +  -> X86Features
    
    243
    +initX86Features feats = X86Features
    
    244
    +  { x86SseAvx = sseAvx
    
    245
    +  , x86Bmi    = bmi
    
    246
    +  , x86Gfni   = has Feat_GFNI
    
    247
    +  }
    
    248
    +  where
    
    249
    +    has = (`EnumSet.member` feats)
    
    250
    +    fma = has Feat_FMA
    
    251
    +    avx512 = Avx512Exts
    
    252
    +      { avx512bw = has Feat_AVX512BW
    
    253
    +      , avx512cd = has Feat_AVX512CD
    
    254
    +      , avx512dq = has Feat_AVX512DQ
    
    255
    +      , avx512er = has Feat_AVX512ER
    
    256
    +      , avx512pf = has Feat_AVX512PF
    
    257
    +      , avx512vl = has Feat_AVX512VL
    
    258
    +      }
    
    259
    +    sseAvx
    
    260
    +      | has Feat_AVX512F || avx512 /= noAvx512Exts = Avx (Avx512 avx512)
    
    261
    +      | has Feat_AVX2                              = Avx (Avx2 fma)
    
    262
    +      | has Feat_AVX || fma                        = Avx (Avx1 fma)
    
    263
    +      | has Feat_SSE4_2                            = Sse SSE42
    
    264
    +      | has Feat_SSE4                              = Sse SSE4
    
    265
    +      | has Feat_SSSE3                             = Sse SSSE3
    
    266
    +      | has Feat_SSE3                              = Sse SSE3
    
    267
    +      | otherwise                                  = x86BaselineSseAvx
    
    268
    +    bmi
    
    269
    +      | has Feat_BMI2 = Just BMI2
    
    270
    +      | has Feat_BMI  = Just BMI1
    
    271
    +      | otherwise     = Nothing
    
    272
    +
    
    273
    +x86SseVersion :: SseAvxVersion -> SseVersion
    
    274
    +x86SseVersion = \case
    
    275
    +  Sse v -> v
    
    276
    +  Avx _ -> SSE42
    
    277
    +
    
    278
    +x86Avx512Exts :: SseAvxVersion -> Maybe Avx512Exts
    
    279
    +x86Avx512Exts = \case
    
    280
    +  Avx (Avx512 exts) -> Just exts
    
    281
    +  _                 -> Nothing
    
    282
    +
    
    283
    +--------------------------------------------------------------------------------
    
    284
    +-- Querying x86 features
    
    285
    +
    
    286
    +-- NB: the predicates below are not independent, because there are implications
    
    287
    +-- between feature flags (e.g. AVX2 implies SSE4.2).
    
    288
    +--
    
    289
    +-- See Note [CPU features].
    
    290
    +
    
    291
    +x86Ssse3Enabled :: X86Features -> Bool
    
    292
    +x86Ssse3Enabled = (>= SSSE3) . x86SseVersion . x86SseAvx
    
    293
    +
    
    294
    +x86Sse4_1Enabled :: X86Features -> Bool
    
    295
    +x86Sse4_1Enabled = (>= SSE4) . x86SseVersion . x86SseAvx
    
    296
    +
    
    297
    +x86Sse4_2Enabled :: X86Features -> Bool
    
    298
    +x86Sse4_2Enabled = (>= SSE42) . x86SseVersion . x86SseAvx
    
    299
    +
    
    300
    +x86AvxEnabled :: X86Features -> Bool
    
    301
    +x86AvxEnabled feats = case x86SseAvx feats of
    
    302
    +  Sse _ -> False
    
    303
    +  Avx _ -> True
    
    304
    +
    
    305
    +x86Avx2Enabled :: X86Features -> Bool
    
    306
    +x86Avx2Enabled feats = case x86SseAvx feats of
    
    307
    +  Sse _          -> False
    
    308
    +  Avx (Avx1 _)   -> False
    
    309
    +  Avx (Avx2 _)   -> True
    
    310
    +  Avx (Avx512 _) -> True
    
    311
    +
    
    312
    +x86FmaEnabled :: X86Features -> Bool
    
    313
    +x86FmaEnabled feats = case x86SseAvx feats of
    
    314
    +  Sse _            -> False
    
    315
    +  Avx (Avx1 fma)   -> fma
    
    316
    +  Avx (Avx2 fma)   -> fma
    
    317
    +  Avx (Avx512 _)   -> True
    
    318
    +
    
    319
    +x86Avx512FEnabled :: X86Features -> Bool
    
    320
    +x86Avx512FEnabled = isJust . x86Avx512Exts . x86SseAvx
    
    321
    +
    
    322
    +x86Avx512DQEnabled :: X86Features -> Bool
    
    323
    +x86Avx512DQEnabled = maybe False avx512dq . x86Avx512Exts . x86SseAvx
    
    324
    +
    
    325
    +x86Avx512VLEnabled :: X86Features -> Bool
    
    326
    +x86Avx512VLEnabled = maybe False avx512vl . x86Avx512Exts . x86SseAvx
    
    327
    +
    
    328
    +x86Bmi2Enabled :: X86Features -> Bool
    
    329
    +x86Bmi2Enabled = (>= Just BMI2) . x86Bmi
    
    330
    +
    
    331
    +--------------------------------------------------------------------------------
    
    332
    +-- Comparing x86 feature sets
    
    333
    +
    
    334
    +-- | @enabled \`sseAvxVersionIncludes\` required@ answers whether the @enabled@
    
    335
    +-- features provide everything required by @required@, taking into account
    
    336
    +-- implications between instruction sets. See Note [CPU features].
    
    337
    +--
    
    338
    +-- This is a partial order, as FMA and the AVX-512 extensions are independent
    
    339
    +-- of each other.
    
    340
    +sseAvxVersionIncludes :: SseAvxVersion -> SseAvxVersion -> Bool
    
    341
    +sseAvxVersionIncludes enabled required = case (enabled, required) of
    
    342
    +  (Sse e, Sse r) -> e >= r
    
    343
    +  (Avx _, Sse _) -> True
    
    344
    +  (Sse _, Avx _) -> False
    
    345
    +  (Avx e, Avx r) -> e `avxLevelIncludes` r
    
    346
    +  where
    
    347
    +    avxLevelIncludes :: AvxLevel -> AvxLevel -> Bool
    
    348
    +    avxLevelIncludes e r = case (e, r) of
    
    349
    +      (Avx512 ee, Avx512 re) -> ee `avx512ExtsInclude` re
    
    350
    +      (Avx512 _, _)          -> True
    
    351
    +      (_, Avx512 _)          -> False
    
    352
    +      (Avx1 ef, Avx1 rf)     -> rf `implies` ef
    
    353
    +      (Avx2 ef, Avx1 rf)     -> rf `implies` ef
    
    354
    +      (Avx2 ef, Avx2 rf)     -> rf `implies` ef
    
    355
    +      (Avx1 _, Avx2 _)       -> False
    
    356
    +
    
    357
    +    avx512ExtsInclude :: Avx512Exts -> Avx512Exts -> Bool
    
    358
    +    avx512ExtsInclude
    
    359
    +      (Avx512Exts ebw ecd edq eer epf evl)
    
    360
    +      (Avx512Exts rbw rcd rdq rer rpf rvl)
    
    361
    +      =  rbw `implies` ebw
    
    362
    +      && rcd `implies` ecd
    
    363
    +      && rdq `implies` edq
    
    364
    +      && rer `implies` eer
    
    365
    +      && rpf `implies` epf
    
    366
    +      && rvl `implies` evl
    
    367
    +
    
    368
    +    implies :: Bool -> Bool -> Bool
    
    369
    +    implies a b = b || not a
    
    370
    +
    
    371
    +-- | The least 'SseAvxVersion' providing everything that both arguments do.
    
    372
    +unionSseAvxVersion :: SseAvxVersion -> SseAvxVersion -> SseAvxVersion
    
    373
    +unionSseAvxVersion v1 v2 = case (v1, v2) of
    
    374
    +  (Sse a, Sse b) -> Sse (max a b)
    
    375
    +  (Sse _, Avx _) -> v2
    
    376
    +  (Avx _, Sse _) -> v1
    
    377
    +  (Avx a, Avx b) -> Avx (a `avxLevelJoin` b)
    
    378
    +  where
    
    379
    +    avxLevelJoin :: AvxLevel -> AvxLevel -> AvxLevel
    
    380
    +    avxLevelJoin a b = case (a, b) of
    
    381
    +      (Avx512 ea, Avx512 eb) -> Avx512 (ea `avx512ExtsUnion` eb)
    
    382
    +      (Avx512 _, _)          -> a
    
    383
    +      (_, Avx512 _)          -> b
    
    384
    +      (Avx1 fa, Avx1 fb)     -> Avx1 (fa || fb)
    
    385
    +      (Avx1 fa, Avx2 fb)     -> Avx2 (fa || fb)
    
    386
    +      (Avx2 fa, Avx1 fb)     -> Avx2 (fa || fb)
    
    387
    +      (Avx2 fa, Avx2 fb)     -> Avx2 (fa || fb)
    
    388
    +    avx512ExtsUnion (Avx512Exts bw1 cd1 dq1 er1 pf1 vl1) (Avx512Exts bw2 cd2 dq2 er2 pf2 vl2)
    
    389
    +      = Avx512Exts (bw1 || bw2) (cd1 || cd2) (dq1 || dq2) (er1 || er2) (pf1 || pf2) (vl1 || vl2)
    
    390
    +
    
    391
    +-- | The SSE/AVX instruction sets required to operate on vectors of the given
    
    392
    +-- width in bits, with floating-point or integer elements.
    
    393
    +--
    
    394
    +-- 128-bit vectors need SSE2 (SSE1 only covers single-precision elements).
    
    395
    +sseAvxVectorRequirement
    
    396
    +  :: Bool -- ^ floating-point elements?
    
    397
    +  -> Int  -- ^ width of the vector, in bits
    
    398
    +  -> SseAvxVersion
    
    399
    +sseAvxVectorRequirement float bits
    
    400
    +  | bits <= 128 = Sse SSE2
    
    401
    +  | bits <= 256 = Avx $ if float then Avx1 False else Avx2 False
    
    402
    +  | otherwise   = Avx $ Avx512 noAvx512Exts
    
    403
    +
    
    404
    +-- | A minimal set of flags that imply the given 'SseAvxVersion'.
    
    405
    +sseAvxVersionFlags :: SseAvxVersion -> [String]
    
    406
    +sseAvxVersionFlags = \case
    
    407
    +  Sse v ->
    
    408
    +    [ case v of
    
    409
    +        SSE1  -> "-msse"
    
    410
    +        SSE2  -> "-msse2"
    
    411
    +        SSE3  -> "-msse3"
    
    412
    +        SSSE3 -> "-mssse3"
    
    413
    +        SSE4  -> "-msse4"
    
    414
    +        SSE42 -> "-msse4.2"
    
    415
    +    ]
    
    416
    +  Avx (Avx1 fma)
    
    417
    +    | fma       -> [ "-mfma" ] -- FMA implies AVX
    
    418
    +    | otherwise -> [ "-mavx" ]
    
    419
    +  Avx (Avx2 fma) -> "-mavx2" : [ "-mfma" | fma ]
    
    420
    +  Avx (Avx512 (Avx512Exts bw cd dq er pf vl))
    
    421
    +    -- Every AVX-512 extension implies AVX-512F
    
    422
    +    | null exts -> [ "-mavx512f" ]
    
    423
    +    | otherwise -> exts
    
    424
    +    where
    
    425
    +      exts =
    
    426
    +        [ flag
    
    427
    +        | (flag, enabled) <-
    
    428
    +            [ ("-mavx512bw", bw)
    
    429
    +            , ("-mavx512cd", cd)
    
    430
    +            , ("-mavx512dq", dq)
    
    431
    +            , ("-mavx512er", er)
    
    432
    +            , ("-mavx512pf", pf)
    
    433
    +            , ("-mavx512vl", vl)
    
    434
    +            ]
    
    435
    +        , enabled ]

  • compiler/GHC/StgToCmm/Config.hs
    ... ... @@ -7,6 +7,7 @@ module GHC.StgToCmm.Config
    7 7
     
    
    8 8
     import GHC.Platform.Profile
    
    9 9
     import GHC.Platform
    
    10
    +import GHC.Platform.CpuFeatures
    
    10 11
     import GHC.Unit.Module
    
    11 12
     import GHC.Utils.Outputable
    
    12 13
     import GHC.Utils.TmpFs
    
    ... ... @@ -76,16 +77,9 @@ data StgToCmmConfig = StgToCmmConfig
    76 77
       , stgToCmmUseStdApThunk             :: !Bool   -- ^ Use precomputed standard AP thunks in the RTS.
    
    77 78
       , stgToCmmSaveFCallTargetToLocal    :: !Bool   -- ^ Save a foreign call target to a Cmm local, see
    
    78 79
                                                      -- Note [Saving foreign call target to local] for details
    
    79
    -  ------------------------------ SIMD flags ------------------------------------
    
    80
    -  -- Each of these flags checks vector compatibility with the backend requested
    
    81
    -  -- during compilation. In essence, this means checking for @-fllvm@ which is
    
    82
    -  -- the only backend that currently allows SIMD instructions, see
    
    83
    -  -- Ghc.StgToCmm.Prim.checkVecCompatibility for these flags only call site.
    
    84 80
       , stgToCmmVecInstrsErr   :: Maybe String       -- ^ Error (if any) to raise when vector instructions are
    
    85 81
                                                      -- used, see @StgToCmm.Prim.checkVecCompatibility@
    
    86
    -  , stgToCmmAvx            :: !Bool              -- ^ check for Advanced Vector Extensions
    
    87
    -  , stgToCmmAvx2           :: !Bool              -- ^ check for Advanced Vector Extensions 2
    
    88
    -  , stgToCmmAvx512f        :: !Bool              -- ^ check for Advanced Vector 512-bit Extensions
    
    82
    +  , stgToCmmCpuFeatures    :: !CpuFeatures       -- ^ Enabled CPU features
    
    89 83
       }
    
    90 84
     
    
    91 85
     
    

  • compiler/GHC/StgToCmm/Prim.hs
    ... ... @@ -18,6 +18,7 @@ module GHC.StgToCmm.Prim (
    18 18
     import GHC.Prelude hiding ((<*>))
    
    19 19
     
    
    20 20
     import GHC.Platform
    
    21
    +import GHC.Platform.CpuFeatures
    
    21 22
     import GHC.Platform.Profile
    
    22 23
     
    
    23 24
     import GHC.StgToCmm.Config
    
    ... ... @@ -2688,45 +2689,44 @@ vecCmmCat FloatVec = cmmFloat
    2688 2689
     --    it may very well be a design perspective that helps guide improving the NCG.
    
    2689 2690
     
    
    2690 2691
     
    
    2692
    +-- | Give up if the backend or the enabled CPU features do not support
    
    2693
    +-- operations on vectors of the given category, length and element width.
    
    2691 2694
     checkVecCompatibility :: StgToCmmConfig -> PrimOpVecCat -> Length -> Width -> FCode ()
    
    2692 2695
     checkVecCompatibility cfg vcat l w =
    
    2693
    -  case stgToCmmVecInstrsErr cfg of
    
    2694
    -    Nothing | isX86 -> checkX86 vecWidth vcat l w
    
    2695
    -            | platformArch platform == ArchAArch64 -> checkAArch64 vecWidth
    
    2696
    -            | otherwise -> sorry "SIMD vector instructions are not supported on this architecture."
    
    2697
    -    Just err -> sorry err  -- incompatible backend, do panic
    
    2696
    +  case unsupported of
    
    2697
    +    Nothing     -> return ()
    
    2698
    +    Just reason -> sorry reason
    
    2698 2699
       where
    
    2699
    -    platform = stgToCmmPlatform cfg
    
    2700
    -    isX86 = case platformArch platform of
    
    2701
    -      ArchX86_64 -> True
    
    2702
    -      ArchX86 -> True
    
    2703
    -      _ -> False
    
    2704
    -    checkX86 :: Width -> PrimOpVecCat -> Length -> Width -> FCode ()
    
    2705
    -    checkX86 W128 FloatVec 4 W32 | isSseEnabled platform = return ()
    
    2706
    -                                 | otherwise =
    
    2707
    -        sorry $ "128-bit wide single-precision floating point " ++
    
    2708
    -                "SIMD vector instructions require at least -msse."
    
    2709
    -    checkX86 W128 _ _ _ | not (isSse2Enabled platform) =
    
    2710
    -        sorry $ "128-bit wide integer and double precision " ++
    
    2711
    -                "SIMD vector instructions require at least -msse2."
    
    2712
    -    checkX86 W256 FloatVec _ _ | stgToCmmAvx cfg = return ()
    
    2713
    -                               | otherwise =
    
    2714
    -        sorry $ "256-bit wide floating point " ++
    
    2715
    -                "SIMD vector instructions require at least -mavx."
    
    2716
    -    checkX86 W256 _ _ _ | not (stgToCmmAvx2 cfg) =
    
    2717
    -        sorry $ "256-bit wide integer " ++
    
    2718
    -                "SIMD vector instructions require at least -mavx2."
    
    2719
    -    checkX86 W512 _ _ _ | not (stgToCmmAvx512f cfg) =
    
    2720
    -        sorry $ "512-bit wide " ++
    
    2721
    -                "SIMD vector instructions require -mavx512f."
    
    2722
    -    checkX86 _ _ _ _ = return ()
    
    2723
    -
    
    2724
    -    checkAArch64 :: Width -> FCode ()
    
    2725
    -    checkAArch64 W256 = sorry $ "256-bit wide SIMD vector instructions are not supported."
    
    2726
    -    checkAArch64 W512 = sorry $ "512-bit wide SIMD vector instructions are not supported."
    
    2727
    -    checkAArch64 _ = return ()
    
    2700
    +    unsupported :: Maybe String
    
    2701
    +    unsupported
    
    2702
    +      -- The backend does not support vector instructions at all.
    
    2703
    +      | Just err <- stgToCmmVecInstrsErr cfg
    
    2704
    +      = Just err
    
    2705
    +      | otherwise
    
    2706
    +      = case stgToCmmCpuFeatures cfg of
    
    2707
    +          X86CpuFeatures feats
    
    2708
    +            | x86SseAvx feats `sseAvxVersionIncludes` required
    
    2709
    +            -> Nothing
    
    2710
    +            | otherwise
    
    2711
    +            -> Just $ bits ++ "-bit wide " ++ category ++ " SIMD vector instructions require at least "
    
    2712
    +                   ++ unwords (sseAvxVersionFlags required) ++ "."
    
    2713
    +            where required = sseAvxVectorRequirement floatElems (widthInBits vecWidth)
    
    2714
    +          _ | platformArch (stgToCmmPlatform cfg) == ArchAArch64
    
    2715
    +            -> case vecWidth of
    
    2716
    +                 W128 -> Nothing
    
    2717
    +                 _    -> Just $ bits ++ "-bit wide SIMD vector instructions are not supported."
    
    2718
    +            | otherwise
    
    2719
    +            -> Just "SIMD vector instructions are not supported on this architecture."
    
    2728 2720
     
    
    2729 2721
         vecWidth = typeWidth (vecCmmType vcat l w)
    
    2722
    +    bits = show (widthInBits vecWidth)
    
    2723
    +    floatElems = case vcat of
    
    2724
    +      FloatVec -> True
    
    2725
    +      IntVec   -> False
    
    2726
    +      WordVec  -> False
    
    2727
    +    category
    
    2728
    +      | floatElems = "floating-point"
    
    2729
    +      | otherwise  = "integer"
    
    2730 2730
     
    
    2731 2731
     ------------------------------------------------------------------------------
    
    2732 2732
     -- Helpers for translating vector packing and unpacking.
    

  • compiler/GHC/SysTools/Cpp.hs
    ... ... @@ -18,6 +18,7 @@ import GHC.Driver.Backend
    18 18
     import GHC.CmmToLlvm.Version
    
    19 19
     import GHC.Platform
    
    20 20
     import GHC.Platform.ArchOS
    
    21
    +import GHC.Platform.CpuFeatures
    
    21 22
     
    
    22 23
     import GHC.SysTools
    
    23 24
     
    
    ... ... @@ -151,30 +152,30 @@ doCpp logger tmpfs dflags unit_env opts input_fn output_fn = do
    151 152
               [ "-D__IO_MANAGER_WINIO__=2" | isWindows ] ++
    
    152 153
               [ "-D__IO_MANAGER_MIO__=1"               ]
    
    153 154
     
    
    154
    -    let sse_defs =
    
    155
    -          [ "-D__SSE__"      | isSseEnabled      platform ] ++
    
    156
    -          [ "-D__SSE2__"     | isSse2Enabled     platform ] ++
    
    157
    -          [ "-D__SSE3__"     | isSse3Enabled     dflags ] ++
    
    158
    -          [ "-D__SSSE3__"    | isSsse3Enabled    dflags ] ++
    
    159
    -          [ "-D__SSE4_1__"   | isSse4_1Enabled   dflags ] ++
    
    160
    -          [ "-D__SSE4_2__"   | isSse4_2Enabled   dflags ]
    
    161
    -
    
    162
    -    let fma_def =
    
    163
    -         [ "-D__FMA__"       | isFmaEnabled dflags ]
    
    164
    -
    
    165
    -    let avx_defs =
    
    166
    -          [ "-D__AVX__"      | isAvxEnabled      dflags ] ++
    
    167
    -          [ "-D__AVX2__"     | isAvx2Enabled     dflags ] ++
    
    168
    -          [ "-D__AVX512BW__" | isAvx512bwEnabled dflags ] ++
    
    169
    -          [ "-D__AVX512CD__" | isAvx512cdEnabled dflags ] ++
    
    170
    -          [ "-D__AVX512DQ__" | isAvx512dqEnabled dflags ] ++
    
    171
    -          [ "-D__AVX512ER__" | isAvx512erEnabled dflags ] ++
    
    172
    -          [ "-D__AVX512F__"  | isAvx512fEnabled  dflags ] ++
    
    173
    -          [ "-D__AVX512PF__" | isAvx512pfEnabled dflags ] ++
    
    174
    -          [ "-D__AVX512VL__" | isAvx512vlEnabled dflags ]
    
    175
    -
    
    176
    -    let gfni_def =
    
    177
    -          [ "-D__GFNI__"     | isGfniEnabled dflags ]
    
    155
    +    let cpu_feats = targetCpuFeatures dflags
    
    156
    +        cpu_defs =
    
    157
    +          [ "-D__FMA__" | cpuFmaEnabled cpu_feats ] ++
    
    158
    +          case cpu_feats of
    
    159
    +            X86CpuFeatures feats@(X86Features { x86SseAvx = sseAvx, x86Gfni = gfni }) ->
    
    160
    +              let sse    = x86SseVersion sseAvx
    
    161
    +                  avx512 = x86Avx512Exts sseAvx
    
    162
    +              in [ "-D__SSE__"      | sse >= SSE1  ] ++
    
    163
    +                 [ "-D__SSE2__"     | sse >= SSE2  ] ++
    
    164
    +                 [ "-D__SSE3__"     | sse >= SSE3  ] ++
    
    165
    +                 [ "-D__SSSE3__"    | sse >= SSSE3 ] ++
    
    166
    +                 [ "-D__SSE4_1__"   | sse >= SSE4  ] ++
    
    167
    +                 [ "-D__SSE4_2__"   | sse >= SSE42 ] ++
    
    168
    +                 [ "-D__AVX__"      | x86AvxEnabled feats ] ++
    
    169
    +                 [ "-D__AVX2__"     | x86Avx2Enabled feats ] ++
    
    170
    +                 [ "-D__AVX512F__"  | isJust avx512 ] ++
    
    171
    +                 [ "-D__AVX512BW__" | maybe False avx512bw avx512 ] ++
    
    172
    +                 [ "-D__AVX512CD__" | maybe False avx512cd avx512 ] ++
    
    173
    +                 [ "-D__AVX512DQ__" | maybe False avx512dq avx512 ] ++
    
    174
    +                 [ "-D__AVX512ER__" | maybe False avx512er avx512 ] ++
    
    175
    +                 [ "-D__AVX512PF__" | maybe False avx512pf avx512 ] ++
    
    176
    +                 [ "-D__AVX512VL__" | maybe False avx512vl avx512 ] ++
    
    177
    +                 [ "-D__GFNI__"     | gfni ]
    
    178
    +            GenericCpuFeatures {} -> []
    
    178 179
     
    
    179 180
         backend_defs <- applyCDefs (backendCDefs $ backend dflags) logger dflags
    
    180 181
     
    
    ... ... @@ -212,10 +213,7 @@ doCpp logger tmpfs dflags unit_env opts input_fn output_fn = do
    212 213
                         ++ map GHC.SysTools.Option th_defs
    
    213 214
                         ++ map GHC.SysTools.Option asserts_def
    
    214 215
                         ++ map GHC.SysTools.Option hscpp_opts
    
    215
    -                    ++ map GHC.SysTools.Option sse_defs
    
    216
    -                    ++ map GHC.SysTools.Option fma_def
    
    217
    -                    ++ map GHC.SysTools.Option avx_defs
    
    218
    -                    ++ map GHC.SysTools.Option gfni_def
    
    216
    +                    ++ map GHC.SysTools.Option cpu_defs
    
    219 217
                         ++ map GHC.SysTools.Option io_manager_defs
    
    220 218
                         ++ mb_macro_include
    
    221 219
                         ++ line_pragmas
    

  • compiler/ghc.cabal.in
    ... ... @@ -689,6 +689,7 @@ Library
    689 689
             GHC.Platform.ARM
    
    690 690
             GHC.Platform.AArch64
    
    691 691
             GHC.Platform.Constants
    
    692
    +        GHC.Platform.CpuFeatures
    
    692 693
             GHC.Platform.LA64
    
    693 694
             GHC.Platform.NoRegs
    
    694 695
             GHC.Platform.PPC
    

  • testsuite/tests/count-deps/CountDepsParser.stdout
    ... ... @@ -150,6 +150,7 @@ GHC.Parser.String
    150 150
     GHC.Parser.Types
    
    151 151
     GHC.Platform
    
    152 152
     GHC.Platform.Constants
    
    153
    +GHC.Platform.CpuFeatures
    
    153 154
     GHC.Platform.Profile
    
    154 155
     GHC.Platform.Tag
    
    155 156
     GHC.Platform.Ways