Andreas Klebinger pushed to branch wip/andreask/cbv_array at Glasgow Haskell Compiler / GHC

Commits:

17 changed files:

Changes:

  • compiler/GHC/Builtin/PrimOps.hs
    ... ... @@ -9,7 +9,7 @@
    9 9
     
    
    10 10
     module GHC.Builtin.PrimOps (
    
    11 11
             PrimOp(..), PrimOpVecCat(..), allThePrimOps,
    
    12
    -        primOpType, primOpSig, primOpResultType,
    
    12
    +        primOpType, primOpSig, primOpResultType, primOpCbv,
    
    13 13
             primOpTag, maxPrimOpTag, primOpOcc,
    
    14 14
             primOpWrapperId,
    
    15 15
             pprPrimOp,
    
    ... ... @@ -146,6 +146,22 @@ primOpStrictness :: PrimOp -> Arity -> DmdSig
    146 146
             -- this function isn't exported.
    
    147 147
     #include "primop-strictness.hs-incl"
    
    148 148
     
    
    149
    +{-
    
    150
    +************************************************************************
    
    151
    +*                                                                      *
    
    152
    +\subsubsection{Call by value info}
    
    153
    +*                                                                      *
    
    154
    +************************************************************************
    
    155
    +
    
    156
    +Some primops require us to only pass evaluated and properly tagged
    
    157
    +pointers for boxed arguments.
    
    158
    +
    
    159
    +See Note [Evaluated and Properly Tagged]
    
    160
    +-}
    
    161
    +
    
    162
    +primOpCbv :: PrimOp -> [CbvMark]
    
    163
    +#include "primop-cbv.hs-incl"
    
    164
    +
    
    149 165
     {-
    
    150 166
     ************************************************************************
    
    151 167
     *                                                                      *
    

  • compiler/GHC/Builtin/primops.txt.pp
    ... ... @@ -150,6 +150,7 @@ defaults
    150 150
        div_like         = False   -- Second argument expected to be non zero - used for tests
    
    151 151
        shift_like       = False   -- Second argument expected to be atmost first argument's word size -1 - used for tests
    
    152 152
        defined_bits     = Nothing -- The number of bits the operation is defined for (if not all bits)
    
    153
    +   cbv_marks        = []
    
    153 154
     
    
    154 155
     -- Note [When do out-of-line primops go in primops.txt.pp]
    
    155 156
     -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    ... ... @@ -1621,6 +1622,28 @@ primop ReadArrayOp "readArray#" GenPrimOp
    1621 1622
        effect = ReadWriteEffect
    
    1622 1623
        can_fail_warning = YesWarnCanFail
    
    1623 1624
     
    
    1625
    +primop  ReadStrictArrayOp "unsafeReadStrictArray#" GenPrimOp
    
    1626
    +   MutableArray# s a -> Int# -> State# s -> (# State# s, a #)
    
    1627
    +   {Read from specified index of mutable array. Result is evaluated.
    
    1628
    +
    
    1629
    +    GHC will assume the value at the given index has been written
    
    1630
    +    by writeStrictArray#. This can allow GHC to elid an eval check when using the
    
    1631
    +    read value. Potentially given a performance benefit.
    
    1632
    +
    
    1633
    +    WARNING: Behaviour is undefined if the value read
    
    1634
    +    was not written using writeStrictArray#.
    
    1635
    +
    
    1636
    +    At runtime "strict" arrays and regular arrays have the same representation.
    
    1637
    +    The only difference is in the read/write operations.
    
    1638
    +
    
    1639
    +    The strict write operations ensure stored values are evaluated and properly
    
    1640
    +    tagged. Strict reads assume this fact, allowing GHC to sometimes avoid
    
    1641
    +    checking for thunks when using the read value.
    
    1642
    +   }
    
    1643
    +   with
    
    1644
    +   effect = ReadWriteEffect
    
    1645
    +   can_fail_warning = YesWarnCanFail
    
    1646
    +
    
    1624 1647
     primop  WriteArrayOp "writeArray#" GenPrimOp
    
    1625 1648
        MutableArray# s a_levpoly -> Int# -> a_levpoly -> State# s -> State# s
    
    1626 1649
        {Write to specified index of mutable array.}
    
    ... ... @@ -1629,6 +1652,15 @@ primop WriteArrayOp "writeArray#" GenPrimOp
    1629 1652
        can_fail_warning = YesWarnCanFail
    
    1630 1653
        code_size = 2 -- card update too
    
    1631 1654
     
    
    1655
    +primop  WriteStrictArrayOp "writeStrictArray#" GenPrimOp
    
    1656
    +   MutableArray# s a_levpoly -> Int# -> a_levpoly -> State# s -> State# s
    
    1657
    +   {Write to specified index of mutable array. Evaluates the argument before writing it.}
    
    1658
    +   with
    
    1659
    +   effect = ReadWriteEffect
    
    1660
    +   can_fail_warning = YesWarnCanFail
    
    1661
    +   code_size = 2 -- card update too
    
    1662
    +   cbv_marks = [!,!,!]
    
    1663
    +
    
    1632 1664
     primop  SizeofArrayOp "sizeofArray#" GenPrimOp
    
    1633 1665
        Array# a_levpoly -> Int#
    
    1634 1666
        {Return the number of elements in the array.}
    
    ... ... @@ -1637,6 +1669,23 @@ primop SizeofMutableArrayOp "sizeofMutableArray#" GenPrimOp
    1637 1669
        MutableArray# s a_levpoly -> Int#
    
    1638 1670
        {Return the number of elements in the array.}
    
    1639 1671
     
    
    1672
    +primop  IndexStrictArrayOp "unsafeIndexStrictArray#" GenPrimOp
    
    1673
    +   Array# a_levpoly -> Int# -> (# a_levpoly #)
    
    1674
    +   {Read from the specified index of an immutable array. The result is packaged
    
    1675
    +    into an unboxed unary tuple; the result itself is evaluated.
    
    1676
    +    Pattern matching on the tuple forces the indexing of the
    
    1677
    +    array to happen.
    
    1678
    +
    
    1679
    +    GHC will assume the value at the given index has been written
    
    1680
    +    by writeStrictArray#. This can allow GHC to elid an eval check when using the
    
    1681
    +    read value. Potentially given a performance benefit.
    
    1682
    +
    
    1683
    +    WARNING: Behaviour is undefined if the value read
    
    1684
    +    was not written using writeStrictArray#.
    
    1685
    +   }
    
    1686
    +   with
    
    1687
    +   effect = CanFail
    
    1688
    +
    
    1640 1689
     primop  IndexArrayOp "indexArray#" GenPrimOp
    
    1641 1690
        Array# a_levpoly -> Int# -> (# a_levpoly #)
    
    1642 1691
        {Read from the specified index of an immutable array. The result is packaged
    
    ... ... @@ -1838,6 +1887,27 @@ primop ReadSmallArrayOp "readSmallArray#" GenPrimOp
    1838 1887
        effect = ReadWriteEffect
    
    1839 1888
        can_fail_warning = YesWarnCanFail
    
    1840 1889
     
    
    1890
    +primop  ReadSmallStrictArrayOp "unsafeReadSmallStrictArray#" GenPrimOp
    
    1891
    +   SmallMutableArray# s a -> Int# -> State# s -> (# State# s, a #)
    
    1892
    +   {Read from specified index of mutable array.
    
    1893
    +
    
    1894
    +    GHC will assume the value at the given index has been evaluted *and tagged*
    
    1895
    +    by writeStrictArray#. This can allow GHC to elid an eval check when using the
    
    1896
    +    read value. Potentially given a performance benefit.
    
    1897
    +
    
    1898
    +    WARNING: Behaviour is undefined if the value read
    
    1899
    +    was not written using writeStrictArray#.
    
    1900
    +
    
    1901
    +    At runtime "strict" arrays and regular arrays have the same representation.
    
    1902
    +    The only difference is in the read/write operations.
    
    1903
    +
    
    1904
    +    The strict write operations ensure stored values are evaluated and properly
    
    1905
    +    tagged. Strict reads assume this fact, allowing GHC to sometimes avoid
    
    1906
    +    checking for thunks when using the read value.}
    
    1907
    +   with
    
    1908
    +   effect = ReadWriteEffect
    
    1909
    +   can_fail_warning = YesWarnCanFail
    
    1910
    +
    
    1841 1911
     primop  WriteSmallArrayOp "writeSmallArray#" GenPrimOp
    
    1842 1912
        SmallMutableArray# s a_levpoly -> Int# -> a_levpoly -> State# s -> State# s
    
    1843 1913
        {Write to specified index of mutable array.}
    
    ... ... @@ -1845,6 +1915,16 @@ primop WriteSmallArrayOp "writeSmallArray#" GenPrimOp
    1845 1915
        effect = ReadWriteEffect
    
    1846 1916
        can_fail_warning = YesWarnCanFail
    
    1847 1917
     
    
    1918
    +primop  WriteSmallStrictArrayOp "writeSmallStrictArray#" GenPrimOp
    
    1919
    +   SmallMutableArray# s a_levpoly -> Int# -> a_levpoly -> State# s -> State# s
    
    1920
    +   {Write to specified index of mutable array.
    
    1921
    +
    
    1922
    +   Evaluates the argument before storing it.}
    
    1923
    +   with
    
    1924
    +   effect = ReadWriteEffect
    
    1925
    +   can_fail_warning = YesWarnCanFail
    
    1926
    +   cbv_marks = [!,!,!]
    
    1927
    +
    
    1848 1928
     primop  SizeofSmallArrayOp "sizeofSmallArray#" GenPrimOp
    
    1849 1929
        SmallArray# a_levpoly -> Int#
    
    1850 1930
        {Return the number of elements in the array.}
    
    ... ... @@ -1870,6 +1950,20 @@ primop IndexSmallArrayOp "indexSmallArray#" GenPrimOp
    1870 1950
        with
    
    1871 1951
        effect = CanFail
    
    1872 1952
     
    
    1953
    +primop  IndexSmallStrictArrayOp "unsafeIndexSmallStrictArray#" GenPrimOp
    
    1954
    +   SmallArray# a -> Int# -> (# a #)
    
    1955
    +   {Read from specified index of immutable array. Result is packaged into
    
    1956
    +    an unboxed singleton;
    
    1957
    +
    
    1958
    +    GHC will assume the value at the given index has been written
    
    1959
    +    by writeSmallStrictArray#. This can allow GHC to elid an eval check when using the
    
    1960
    +    read value. Potentially given a performance benefit.
    
    1961
    +
    
    1962
    +    WARNING: Behaviour is undefined if the value read
    
    1963
    +    was not written using writeSmallStrictArray#}
    
    1964
    +   with
    
    1965
    +   effect = CanFail
    
    1966
    +
    
    1873 1967
     primop  UnsafeFreezeSmallArrayOp "unsafeFreezeSmallArray#" GenPrimOp
    
    1874 1968
        SmallMutableArray# s a_levpoly -> State# s -> (# State# s, SmallArray# a_levpoly #)
    
    1875 1969
        {Make a mutable array immutable, without copying.}
    

  • compiler/GHC/Stg/EnforceEpt.hs
    ... ... @@ -9,6 +9,7 @@ module GHC.Stg.EnforceEpt ( enforceEpt ) where
    9 9
     
    
    10 10
     import GHC.Prelude hiding (id)
    
    11 11
     
    
    12
    +import qualified GHC.Builtin.PrimOps as PrimOps
    
    12 13
     import GHC.Core.DataCon
    
    13 14
     import GHC.Core.Type
    
    14 15
     import GHC.Types.Id
    
    ... ... @@ -354,6 +355,16 @@ inferTags for_bytecode binds =
    354 355
       -- pprTrace "Binds" (pprGenStgTopBindings shortStgPprOpts $ binds) $
    
    355 356
       snd (mapAccumL inferTagTopBind (initEnv for_bytecode) binds)
    
    356 357
     
    
    358
    +inferPrimAppResult :: PrimOps.PrimOp -> TagInfo
    
    359
    +inferPrimAppResult op =
    
    360
    +  case op of
    
    361
    +    PrimOps.ReadSmallStrictArrayOp -> TagTuple [TagProper]
    
    362
    +    PrimOps.ReadStrictArrayOp -> TagTuple [TagProper]
    
    363
    +    PrimOps.IndexSmallStrictArrayOp -> TagTuple [TagProper]
    
    364
    +    PrimOps.IndexStrictArrayOp -> TagTuple [TagProper]
    
    365
    +    _ -> TagDunno
    
    366
    +
    
    367
    +
    
    357 368
     -----------------------
    
    358 369
     inferTagTopBind :: TagEnv 'CodeGen -> GenStgTopBinding 'CodeGen
    
    359 370
                     -> (TagEnv 'CodeGen, GenStgTopBinding 'InferTaggedBinders)
    
    ... ... @@ -409,11 +420,14 @@ inferTagExpr env (StgTick tick body)
    409 420
       where
    
    410 421
         (info, body') = inferTagExpr env body
    
    411 422
     
    
    412
    -inferTagExpr _ (StgOpApp op args ty)
    
    423
    +inferTagExpr _ (StgOpApp op args ty) =
    
    413 424
       -- Which primops guarantee to return a properly tagged value?
    
    414 425
       -- Probably none, and that is the conservative assumption anyway.
    
    415 426
       -- (And foreign calls definitely need not make promises.)
    
    416
    -  = (TagDunno, StgOpApp op args ty)
    
    427
    +  case op of
    
    428
    +      StgPrimOp prim_op -> (inferPrimAppResult prim_op, StgOpApp op args ty)
    
    429
    +      StgPrimCallOp {} -> (TagDunno, StgOpApp op args ty)
    
    430
    +      StgFCallOp {} -> (TagDunno, StgOpApp op args ty)
    
    417 431
     
    
    418 432
     inferTagExpr env (StgLet ext bind body)
    
    419 433
       = (info, StgLet ext bind' body')
    

  • compiler/GHC/Stg/EnforceEpt/Rewrite.hs
    ... ... @@ -12,7 +12,7 @@ where
    12 12
     
    
    13 13
     import GHC.Prelude
    
    14 14
     
    
    15
    -import GHC.Builtin.PrimOps ( PrimOp(..) )
    
    15
    +import GHC.Builtin.PrimOps ( PrimOp(..), primOpCbv )
    
    16 16
     import GHC.Types.Basic     ( CbvMark (..), isMarkedCbv
    
    17 17
                                , TopLevelFlag(..), isTopLevel )
    
    18 18
     import GHC.Types.Id
    
    ... ... @@ -399,8 +399,7 @@ rewriteExpr (StgTick t e) = StgTick t <$!> rewriteExpr e
    399 399
     rewriteExpr e@(StgConApp {})          = rewriteConApp e
    
    400 400
     rewriteExpr e@(StgApp {})             = rewriteApp e
    
    401 401
     rewriteExpr (StgLit lit)              = return $! (StgLit lit)
    
    402
    -rewriteExpr (StgOpApp op args res_ty) = (StgOpApp op) <$!> rewriteArgs args <*> pure res_ty
    
    403
    -
    
    402
    +rewriteExpr (StgOpApp op args res_ty) = rewriteOpApp (StgOpApp op args res_ty)
    
    404 403
     
    
    405 404
     rewriteCase :: InferStgExpr -> RM TgStgExpr
    
    406 405
     rewriteCase (StgCase scrut bndr alt_type alts) =
    
    ... ... @@ -452,6 +451,21 @@ rewriteConApp (StgConApp con cn args tys) = do
    452 451
     
    
    453 452
     rewriteConApp _ = panic "Impossible"
    
    454 453
     
    
    454
    +{-# INLINE eptArgs #-}
    
    455
    +-- Evaluate the relevant arguments, and construct an expression with the ids substituted
    
    456
    +-- for their evaluated parts.
    
    457
    +eptArgs :: [CbvMark] -> [StgArg] -> ([StgArg] -> TgStgExpr) -> RM TgStgExpr
    
    458
    +eptArgs relevant_marks args mkExpr = do
    
    459
    +    argTags <- mapM isArgTagged args
    
    460
    +    let argInfo = zipWith3 ((,,)) args (relevant_marks++repeat NotMarkedCbv)  argTags :: [(StgArg, CbvMark, Bool)]
    
    461
    +
    
    462
    +        -- untagged cbv arguments
    
    463
    +        cbvArgs = map fstOf3 . filter (\x -> sndOf3 x == MarkedCbv && thdOf3 x == False) $ argInfo
    
    464
    +        -- We only need to force ids
    
    465
    +        cbvArgIds = [x | StgVarArg x <- cbvArgs] :: [Id]
    
    466
    +    mkSeqs args cbvArgIds mkExpr
    
    467
    +
    
    468
    +
    
    455 469
     -- Special case: Atomic binders, usually in a case context like `case f of ...`.
    
    456 470
     rewriteApp :: InferStgExpr -> RM TgStgExpr
    
    457 471
     rewriteApp (StgApp f []) = do
    
    ... ... @@ -464,19 +478,8 @@ rewriteApp (StgApp f args)
    464 478
         , relevant_marks <- dropWhileEndLE (not . isMarkedCbv) marks
    
    465 479
         , any isMarkedCbv relevant_marks
    
    466 480
         = assertPpr (length relevant_marks <= length args) (ppr f $$ ppr args $$ ppr relevant_marks)
    
    467
    -      unliftArg relevant_marks
    
    468
    -
    
    469
    -    where
    
    470
    -      -- If the function expects any argument to be call-by-value ensure the argument is already
    
    471
    -      -- evaluated.
    
    472
    -      unliftArg relevant_marks = do
    
    473
    -        argTags <- mapM isArgTagged args
    
    474
    -        let argInfo = zipWith3 ((,,)) args (relevant_marks++repeat NotMarkedCbv)  argTags :: [(StgArg, CbvMark, Bool)]
    
    475
    -
    
    476
    -            -- untagged cbv argument positions
    
    477
    -            cbvArgInfo = filter (\x -> sndOf3 x == MarkedCbv && thdOf3 x == False) argInfo
    
    478
    -            cbvArgIds = [x | StgVarArg x <- map fstOf3 cbvArgInfo] :: [Id]
    
    479
    -        mkSeqs args cbvArgIds (\cbv_args -> StgApp f cbv_args)
    
    481
    +      -- Enforce relevant args are evaluated and tagged.
    
    482
    +      eptArgs relevant_marks args (\cbv_args -> StgApp f cbv_args)
    
    480 483
     
    
    481 484
     rewriteApp (StgApp f args) = return $ StgApp f args
    
    482 485
     rewriteApp _ = panic "Impossible"
    
    ... ... @@ -500,10 +503,14 @@ So for these we should call `rewriteArgs`.
    500 503
     
    
    501 504
     rewriteOpApp :: InferStgExpr -> RM TgStgExpr
    
    502 505
     rewriteOpApp (StgOpApp op args res_ty) = case op of
    
    506
    +  -- Should we just use cbv marks for DataToTag?
    
    503 507
       op@(StgPrimOp primOp)
    
    504 508
         | primOp == DataToTagSmallOp || primOp == DataToTagLargeOp
    
    505 509
         -- see Note [Rewriting primop arguments]
    
    506 510
         -> (StgOpApp op) <$!> rewriteArgs args <*> pure res_ty
    
    511
    +    | marks <- primOpCbv primOp
    
    512
    +    , not (null marks)
    
    513
    +    -> eptArgs marks args (\tagged_args -> (StgOpApp op tagged_args res_ty))
    
    507 514
       _ -> pure $! StgOpApp op args res_ty
    
    508 515
     rewriteOpApp _ = panic "Impossible"
    
    509 516
     
    

  • compiler/GHC/StgToCmm/Prim.hs
    ... ... @@ -380,17 +380,29 @@ emitPrimOp cfg primop =
    380 380
     
    
    381 381
       ReadArrayOp -> \[obj, ix] -> opIntoRegs $ \[res] ->
    
    382 382
         doReadPtrArrayOp res obj ix
    
    383
    +  ReadStrictArrayOp -> \[obj, ix] -> opIntoRegs $ \[res] ->
    
    384
    +    doReadPtrArrayOp res obj ix
    
    383 385
       IndexArrayOp -> \[obj, ix] -> opIntoRegs $ \[res] ->
    
    384 386
         doReadPtrArrayOp res obj ix
    
    387
    +  IndexStrictArrayOp -> \[obj, ix] -> opIntoRegs $ \[res] ->
    
    388
    +    doReadPtrArrayOp res obj ix
    
    385 389
       WriteArrayOp -> \[obj, ix, v] -> opIntoRegs $ \[] ->
    
    386 390
         doWritePtrArrayOp obj ix v
    
    391
    +  WriteStrictArrayOp -> \[obj, ix, v] -> opIntoRegs $ \[] ->
    
    392
    +    doWritePtrArrayOp obj ix v
    
    387 393
     
    
    388 394
       ReadSmallArrayOp -> \[obj, ix] -> opIntoRegs $ \[res] ->
    
    389 395
         doReadSmallPtrArrayOp res obj ix
    
    396
    +  ReadSmallStrictArrayOp -> \[obj, ix] -> opIntoRegs $ \[res] ->
    
    397
    +    doReadSmallPtrArrayOp res obj ix
    
    390 398
       IndexSmallArrayOp -> \[obj, ix] -> opIntoRegs $ \[res] ->
    
    391 399
         doReadSmallPtrArrayOp res obj ix
    
    400
    +  IndexSmallStrictArrayOp -> \[obj, ix] -> opIntoRegs $ \[res] ->
    
    401
    +    doReadSmallPtrArrayOp res obj ix
    
    392 402
       WriteSmallArrayOp -> \[obj,ix,v] -> opIntoRegs $ \[] ->
    
    393 403
         doWriteSmallPtrArrayOp obj ix v
    
    404
    +  WriteSmallStrictArrayOp -> \[obj,ix,v] -> opIntoRegs $ \[] ->
    
    405
    +    doWriteSmallPtrArrayOp obj ix v
    
    394 406
     
    
    395 407
     -- Getting the size of pointer arrays
    
    396 408
     
    

  • compiler/GHC/StgToJS/Prim.hs
    ... ... @@ -559,7 +559,9 @@ genPrim prof bound ty op = case op of
    559 559
     
    
    560 560
       NewArrayOp           -> \[r] [l,e]   -> pure $ PrimInline $ r |= app hdNewArrayStr [l,e]
    
    561 561
       ReadArrayOp          -> \[r] [a,i]   -> pure $ PrimInline $ bnd_arr bound a i (r |= a .! i)
    
    562
    +  ReadStrictArrayOp    -> \[r] [a,i]   -> pure $ PrimInline $ bnd_arr bound a i (r |= a .! i)
    
    562 563
       WriteArrayOp         -> \[]  [a,i,v] -> pure $ PrimInline $ bnd_arr bound a i (a .! i |= v)
    
    564
    +  WriteStrictArrayOp   -> \[]  [a,i,v] -> pure $ PrimInline $ bnd_arr bound a i (a .! i |= v)
    
    563 565
       SizeofArrayOp        -> \[r] [a]     -> pure $ PrimInline $ r |= a .^ lngth
    
    564 566
       SizeofMutableArrayOp -> \[r] [a]     -> pure $ PrimInline $ r |= a .^ lngth
    
    565 567
       IndexArrayOp         -> \[r] [a,i]   -> pure $ PrimInline $ bnd_arr bound a i (r |= a .! i)
    
    ... ... @@ -623,7 +625,9 @@ genPrim prof bound ty op = case op of
    623 625
     
    
    624 626
       NewSmallArrayOp            -> \[a]   [n,e]         -> pure $ PrimInline $ a |= app hdNewArrayStr [n,e]
    
    625 627
       ReadSmallArrayOp           -> \[r]   [a,i]         -> pure $ PrimInline $ bnd_arr bound a i (r |= a .! i)
    
    628
    +  ReadSmallStrictArrayOp           -> \[r]   [a,i]         -> pure $ PrimInline $ bnd_arr bound a i (r |= a .! i)
    
    626 629
       WriteSmallArrayOp          -> \[]    [a,i,e]       -> pure $ PrimInline $ bnd_arr bound a i (a .! i |= e)
    
    630
    +  WriteSmallStrictArrayOp    -> \[]    [a,i,e]       -> pure $ PrimInline $ bnd_arr bound a i (a .! i |= e) -- todo check-tags?
    
    627 631
       SizeofSmallArrayOp         -> \[r]   [a]           -> pure $ PrimInline $ r |= a .^ lngth
    
    628 632
       SizeofSmallMutableArrayOp  -> \[r]   [a]           -> pure $ PrimInline $ r |= a .^ lngth
    
    629 633
       IndexSmallArrayOp          -> \[r]   [a,i]         -> pure $ PrimInline $ bnd_arr bound a i (r |= a .! i)
    

  • compiler/GHC/Types/Id.hs
    ... ... @@ -513,8 +513,8 @@ isDFunId id = case Var.idDetails id of
    513 513
                             _         -> False
    
    514 514
     
    
    515 515
     isPrimOpId_maybe id = case Var.idDetails id of
    
    516
    -                        PrimOpId op _ -> Just op
    
    517
    -                        _             -> Nothing
    
    516
    +                        PrimOpId op _   -> Just op
    
    517
    +                        _               -> Nothing
    
    518 518
     
    
    519 519
     isFCallId id = case Var.idDetails id of
    
    520 520
                             FCallId _ -> True
    
    ... ... @@ -845,7 +845,7 @@ setIdCbvMarks id marks
    845 845
     
    
    846 846
     idCbvMarks_maybe :: Id -> Maybe [CbvMark]
    
    847 847
     idCbvMarks_maybe id = case idDetails id of
    
    848
    -  WorkerLikeId marks -> Just marks
    
    848
    +  WorkerLikeId marks   -> Just marks
    
    849 849
       JoinId _arity marks  -> marks
    
    850 850
       _                    -> Nothing
    
    851 851
     
    

  • compiler/GHC/Types/Id/Info.hs
    ... ... @@ -395,7 +395,7 @@ pprIdDetails VanillaId = empty
    395 395
     pprIdDetails other     = brackets (pp other)
    
    396 396
      where
    
    397 397
        pp VanillaId               = panic "pprIdDetails"
    
    398
    -   pp (WorkerLikeId dmds)     = text "StrictWorker" <> parens (ppr dmds)
    
    398
    +   pp (WorkerLikeId dmds)     = text "StrictWorker" <> pp_marks dmds
    
    399 399
        pp (DataConWorkId _)       = text "DataCon"
    
    400 400
        pp (DataConWrapId _)       = text "DataConWrapper"
    
    401 401
        pp (ClassOpId {})          = text "ClassOp"
    
    ... ... @@ -410,6 +410,9 @@ pprIdDetails other = brackets (pp other)
    410 410
        pp CoVarId                 = text "CoVarId"
    
    411 411
        pp (JoinId arity marks)    = text "JoinId" <> parens (int arity) <> parens (ppr marks)
    
    412 412
     
    
    413
    +   pp_marks [] = empty
    
    414
    +   pp_marks xs = ppr xs
    
    415
    +
    
    413 416
     {-
    
    414 417
     ************************************************************************
    
    415 418
     *                                                                      *
    

  • compiler/Setup.hs
    ... ... @@ -47,6 +47,7 @@ primopIncls =
    47 47
         , ("primop-commutable.hs-incl"        , "--commutable")
    
    48 48
         , ("primop-code-size.hs-incl"         , "--code-size")
    
    49 49
         , ("primop-strictness.hs-incl"        , "--strictness")
    
    50
    +    , ("primop-cbv.hs-incl"               , "--cbv")
    
    50 51
         , ("primop-is-work-free.hs-incl"      , "--is-work-free")
    
    51 52
         , ("primop-is-cheap.hs-incl"          , "--is-cheap")
    
    52 53
         , ("primop-fixity.hs-incl"            , "--fixity")
    

  • hadrian/src/Rules/Generate.hs
    ... ... @@ -92,6 +92,7 @@ compilerDependencies = do
    92 92
                       , "primop-out-of-line.hs-incl"
    
    93 93
                       , "primop-primop-info.hs-incl"
    
    94 94
                       , "primop-strictness.hs-incl"
    
    95
    +                  , "primop-cbv.hs-incl"
    
    95 96
                       , "primop-is-work-free.hs-incl"
    
    96 97
                       , "primop-is-cheap.hs-incl"
    
    97 98
                       , "primop-tag.hs-incl"
    

  • hadrian/src/Rules/Lint.hs
    ... ... @@ -111,6 +111,7 @@ hsIncls path = [ path </> "primop-vector-tycons.hs-incl"
    111 111
                    , path </> "primop-tag.hs-incl"
    
    112 112
                    , path </> "primop-list.hs-incl"
    
    113 113
                    , path </> "primop-strictness.hs-incl"
    
    114
    +               , path </> "primop-cbv.hs-incl"
    
    114 115
                    , path </> "primop-is-work-free.hs-incl"
    
    115 116
                    , path </> "primop-is-cheap.hs-incl"
    
    116 117
                    , path </> "primop-fixity.hs-incl"
    

  • hadrian/src/Settings/Builders/GenPrimopCode.hs
    ... ... @@ -14,6 +14,7 @@ genPrimopCodeBuilderArgs = builder GenPrimopCode ? mconcat
    14 14
         , output "//primop-commutable.hs-incl"         ? arg "--commutable"
    
    15 15
         , output "//primop-code-size.hs-incl"          ? arg "--code-size"
    
    16 16
         , output "//primop-strictness.hs-incl"         ? arg "--strictness"
    
    17
    +    , output "//primop-cbv.hs-incl"                ? arg "--cbv"
    
    17 18
         , output "//primop-is-work-free.hs-incl"       ? arg "--is-work-free"
    
    18 19
         , output "//primop-is-cheap.hs-incl"           ? arg "--is-cheap"
    
    19 20
         , output "//primop-fixity.hs-incl"             ? arg "--fixity"
    

  • utils/genprimopcode/Lexer.x
    ... ... @@ -36,6 +36,8 @@ words :-
    36 36
         <0>         "]"                 { mkT TCloseBracket }
    
    37 37
         <0>         "<"                 { mkT TOpenAngle }
    
    38 38
         <0>         ">"                 { mkT TCloseAngle }
    
    39
    +    <0>         "!"                 { mkT TBang }
    
    40
    +    <0>         "~"                 { mkT TTilde }
    
    39 41
         <0>         "section"           { mkT TSection }
    
    40 42
         <0>         "primop"            { mkT TPrimop }
    
    41 43
         <0>         "pseudoop"          { mkT TPseudoop }
    
    ... ... @@ -62,6 +64,7 @@ words :-
    62 64
         <0>         "WarnIfEffectIsCanFail" { mkT TWarnIfEffectIsCanFail }
    
    63 65
         <0>         "YesWarnCanFail"    { mkT TYesWarnCanFail }
    
    64 66
         <0>         "vector"            { mkT TVector }
    
    67
    +    <0>         "cbv_marks"         { mkT TCbv_marks }
    
    65 68
         <0>         "bytearray_access_ops" { mkT TByteArrayAccessOps }
    
    66 69
         <0>         "addr_access_ops"   { mkT TAddrAccessOps }
    
    67 70
         <0>         "thats_all_folks"   { mkT TThatsAllFolks }
    

  • utils/genprimopcode/Main.hs
    ... ... @@ -170,6 +170,11 @@ main = getArgs >>= \args ->
    170 170
                                            "strictness"
    
    171 171
                                            "primOpStrictness" p_o_specs)
    
    172 172
     
    
    173
    +                      "--cbv"
    
    174
    +                         -> putStr (gen_switch_from_attribs
    
    175
    +                                       "cbv_marks"
    
    176
    +                                       "primOpCbv" p_o_specs)
    
    177
    +
    
    173 178
                           "--fixity"
    
    174 179
                              -> putStr (gen_switch_from_attribs
    
    175 180
                                            "fixity"
    
    ... ... @@ -228,6 +233,7 @@ known_args
    228 233
            "--is-work-free",
    
    229 234
            "--is-cheap",
    
    230 235
            "--strictness",
    
    236
    +       "--cbv",
    
    231 237
            "--fixity",
    
    232 238
            "--primop-effects",
    
    233 239
            "--primop-primop-info",
    
    ... ... @@ -318,6 +324,7 @@ gen_hs_source (Info defaults entries) =
    318 324
                opt (OptionInteger n v) = n ++ " = " ++ show v
    
    319 325
                opt (OptionVector _)    = ""
    
    320 326
                opt (OptionFixity mf) = "fixity = " ++ show mf
    
    327
    +           opt (OptionCbvMarks marks) = "cbv_marks = " ++ show marks
    
    321 328
                opt (OptionEffect eff) = "effect = " ++ show eff
    
    322 329
                opt (OptionDefinedBits bc) = "defined_bits = " ++ show bc
    
    323 330
                opt (OptionCanFailWarnFlag wf) = "can_fail_warning = " ++ show wf
    
    ... ... @@ -645,6 +652,11 @@ gen_switch_from_attribs attrib_name fn_name (Info defaults entries)
    645 652
              getAltRhs (OptionString _ s) = s
    
    646 653
              getAltRhs (OptionVector _) = "True"
    
    647 654
              getAltRhs (OptionFixity mf) = show mf
    
    655
    +         getAltRhs (OptionCbvMarks marks) =
    
    656
    +            "[" ++ concat (intersperse "," (map showMark marks)) ++ "]"
    
    657
    +            where
    
    658
    +               showMark True = "MarkedCbv"
    
    659
    +               showMark False = "NotMarkedCbv"
    
    648 660
              getAltRhs (OptionEffect eff) = show eff
    
    649 661
              getAltRhs (OptionDefinedBits bc) = show bc
    
    650 662
              getAltRhs (OptionCanFailWarnFlag wf) = show wf
    

  • utils/genprimopcode/Parser.y
    ... ... @@ -30,6 +30,8 @@ import AccessOps
    30 30
         ']'             { TCloseBracket }
    
    31 31
         '<'             { TOpenAngle }
    
    32 32
         '>'             { TCloseAngle }
    
    33
    +    '!'             { TBang }
    
    34
    +    '~'             { TTilde }
    
    33 35
         section         { TSection }
    
    34 36
         primop          { TPrimop }
    
    35 37
         pseudoop        { TPseudoop }
    
    ... ... @@ -56,6 +58,7 @@ import AccessOps
    56 58
         WarnIfEffectIsCanFail { TWarnIfEffectIsCanFail }
    
    57 59
         YesWarnCanFail  { TYesWarnCanFail }
    
    58 60
         vector          { TVector }
    
    61
    +    cbv_marks       { TCbv_marks }
    
    59 62
         SCALAR          { TSCALAR }
    
    60 63
         VECTOR          { TVECTOR }
    
    61 64
         VECTUPLE        { TVECTUPLE }
    
    ... ... @@ -87,6 +90,7 @@ pOption : lowerName '=' false { OptionFalse $1 }
    87 90
             | lowerName        '=' pStuffBetweenBraces    { OptionString  $1  $3 }
    
    88 91
             | lowerName        '=' integer                { OptionInteger $1  $3 }
    
    89 92
             | vector           '=' pVectorTemplate        { OptionVector      $3 }
    
    93
    +        | cbv_marks        '=' pCbvMarks              { OptionCbvMarks    $3 }
    
    90 94
             | fixity           '=' pInfix                 { OptionFixity      $3 }
    
    91 95
             | effect           '=' pEffect                { OptionEffect      $3 }
    
    92 96
             | defined_bits     '=' pGoodBits              { OptionDefinedBits $3 }
    
    ... ... @@ -175,6 +179,18 @@ pInside :: { String }
    175 179
     pInside : '{' pInsides '}' { "{" ++ $2 ++ "}" }
    
    176 180
             | noBraces         { $1 }
    
    177 181
     
    
    182
    +pCbvMarks :: { [Bool] }
    
    183
    +pCbvMarks : '[' pMarks ']' { $2 }
    
    184
    +
    
    185
    +pMarks :: { [Bool] }
    
    186
    +pMarks : pMark ',' pMarks { [$1] ++ $3 }
    
    187
    +       | pMark              { [$1] }
    
    188
    +       | {- empty -}          { [] }
    
    189
    +
    
    190
    +pMark :: { Bool }
    
    191
    +pMark : '!'  { True }
    
    192
    +      | '~'  { False }
    
    193
    +
    
    178 194
     pVectorTemplate :: { [(String, String, Int)] }
    
    179 195
     pVectorTemplate : '[' pVectors ']' { $2 }
    
    180 196
     
    

  • utils/genprimopcode/ParserM.hs
    ... ... @@ -75,6 +75,8 @@ init_state = St {
    75 75
     
    
    76 76
     data Token = TEOF
    
    77 77
                | TArrow
    
    78
    +           | TBang
    
    79
    +           | TTilde
    
    78 80
                | TDArrow
    
    79 81
                | TEquals
    
    80 82
                | TComma
    
    ... ... @@ -122,6 +124,7 @@ data Token = TEOF
    122 124
                | TWarnIfEffectIsCanFail
    
    123 125
                | TYesWarnCanFail
    
    124 126
                | TVector
    
    127
    +           | TCbv_marks
    
    125 128
                | TSCALAR
    
    126 129
                | TVECTOR
    
    127 130
                | TVECTUPLE
    

  • utils/genprimopcode/Syntax.hs
    ... ... @@ -83,6 +83,7 @@ data Option
    83 83
        | OptionEffect PrimOpEffect    -- effect = NoEffect | DoNotSpeculate | CanFail | ThrowsException | ReadWriteEffect | FallibleReadWriteEffect
    
    84 84
        | OptionCanFailWarnFlag PrimOpCanFailWarnFlag -- can_fail_warning = DoNotWarnCanFail | WarnIfEffectIsCanFail | YesWarnCanFail
    
    85 85
        | OptionDefinedBits (Maybe Word) -- defined_bits = Just 16 | Nothing
    
    86
    +   | OptionCbvMarks [Bool] -- defined_bits = Just 16 | Nothing
    
    86 87
          deriving Show
    
    87 88
     
    
    88 89
     -- categorises primops
    
    ... ... @@ -200,6 +201,7 @@ get_attrib_name (OptionTrue nm) = nm
    200 201
     get_attrib_name (OptionString nm _) = nm
    
    201 202
     get_attrib_name (OptionInteger nm _) = nm
    
    202 203
     get_attrib_name (OptionVector _) = "vector"
    
    204
    +get_attrib_name (OptionCbvMarks _) = "cbv_marks"
    
    203 205
     get_attrib_name (OptionFixity _) = "fixity"
    
    204 206
     get_attrib_name (OptionEffect _) = "effect"
    
    205 207
     get_attrib_name (OptionCanFailWarnFlag _) = "can_fail_warning"