Simon Jakobi pushed to branch wip/sjakobi/udfm-placement at Glasgow Haskell Compiler / GHC

Commits:

1 changed file:

Changes:

  • compiler/GHC/Types/Unique/DFM.hs
    ... ... @@ -99,7 +99,8 @@ import qualified GHC.Data.Word64Set as W
    99 99
     --
    
    100 100
     -- There is an implementation cost: each element is given a serial number
    
    101 101
     -- as it is added, and `udfmToList` orders its result by this serial number
    
    102
    --- (see Note [Placement sort in eltsUDFM]). So you should only use `UniqDFM`
    
    102
    +-- (see Note [Placement sort in eltsUDFM] and
    
    103
    +-- Note [Cost of deterministic iteration]). So you should only use `UniqDFM`
    
    103 104
     -- if you need the deterministic property.
    
    104 105
     --
    
    105 106
     -- `foldUDFM` also preserves determinism.
    
    ... ... @@ -159,11 +160,15 @@ data UniqDFM key ele =
    159 160
                                     -- time. See Note [Overflow on plusUDFM]
    
    160 161
       deriving (Data, Functor)
    
    161 162
     
    
    162
    --- | Deterministic. See Note [Placement sort in eltsUDFM] for the cost.
    
    163
    +-- | Deterministic.
    
    164
    +--
    
    165
    +-- See Note [Cost of deterministic iteration].
    
    163 166
     instance Foldable (UniqDFM key) where
    
    164 167
       foldr = foldUDFM
    
    165 168
     
    
    166
    --- | Deterministic. See Note [Placement sort in eltsUDFM] for the cost.
    
    169
    +-- | Deterministic.
    
    170
    +--
    
    171
    +-- See Note [Cost of deterministic iteration].
    
    167 172
     instance Traversable (UniqDFM key) where
    
    168 173
       traverse f = fmap listToUDFM_Directly
    
    169 174
                  . traverse (\(u,a) -> (u,) <$> f a)
    
    ... ... @@ -316,14 +321,18 @@ elemUDFM :: Uniquable key => key -> UniqDFM key elt -> Bool
    316 321
     elemUDFM k (UDFM m _i) = M.member (getKey $ getUnique k) m
    
    317 322
     
    
    318 323
     -- | Performs a deterministic fold over the UniqDFM.
    
    324
    +--
    
    319 325
     -- It's O(n) in the common case, with an O(n log n) fallback
    
    320
    --- (see Note [Placement sort in eltsUDFM]).
    
    326
    +-- (see Note [Placement sort in eltsUDFM]), and pays that in full even if
    
    327
    +-- only a prefix is demanded (see Note [Cost of deterministic iteration]).
    
    321 328
     foldUDFM :: (elt -> a -> a) -> a -> UniqDFM key elt -> a
    
    322 329
     {-# INLINE foldUDFM #-}
    
    323 330
     -- This INLINE prevents a regression in !10568
    
    324 331
     foldUDFM k z m = foldr k z (eltsUDFM m)
    
    325 332
     
    
    326
    --- | Like 'foldUDFM' but the function also receives a key
    
    333
    +-- | Like 'foldUDFM' but the function also receives a key.
    
    334
    +--
    
    335
    +-- See Note [Cost of deterministic iteration].
    
    327 336
     foldWithKeyUDFM :: (Unique -> elt -> a -> a) -> a -> UniqDFM key elt -> a
    
    328 337
     {-# INLINE foldWithKeyUDFM #-}
    
    329 338
     -- This INLINE was copied from foldUDFM
    
    ... ... @@ -338,6 +347,24 @@ nonDetStrictFoldUDFM k z (UDFM m _i) = foldl' k' z m
    338 347
       where
    
    339 348
         k' acc (TaggedVal v _) = k v acc
    
    340 349
     
    
    350
    +-- Note [Cost of deterministic iteration]
    
    351
    +-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    352
    +-- Deterministic iteration orders elements by insertion tag, and any such
    
    353
    +-- ordering must inspect every element's tag before it can emit the first
    
    354
    +-- element. So even the head of the result costs a full O(n) traversal of the
    
    355
    +-- map -- the iteration is not incremental, and laziness in the result list (see
    
    356
    +-- Note [Placement sort in eltsUDFM]) saves allocation for undemanded
    
    357
    +-- elements, not that up-front traversal. #27459 shows this cost biting in
    
    358
    +-- consumers that demanded only the head.
    
    359
    +--
    
    360
    +-- So: to test for emptiness, use isNullUDFM rather than null on eltsUDFM;
    
    361
    +-- for order-oblivious queries, prefer short-circuiting anyUDFM/allUDFM; and
    
    362
    +-- if you don't need the deterministic order at all, use the nonDet functions
    
    363
    +-- (with a justification).
    
    364
    +
    
    365
    +-- | Deterministic, in order of insertion.
    
    366
    +--
    
    367
    +-- See Note [Cost of deterministic iteration].
    
    341 368
     eltsUDFM :: UniqDFM key elt -> [elt]
    
    342 369
     {-# INLINE eltsUDFM #-}
    
    343 370
     -- The INLINE makes it a good producer (from the map)
    
    ... ... @@ -359,7 +386,8 @@ sort_it m = sortBy (compare `on` taggedSnd) (M.elems m)
    359 386
     -- its tag, freeze, and read out in index order. That's O(i) work (which
    
    360 387
     -- subsumes the O(n) fill, since distinct tags force n <= i), no comparisons,
    
    361 388
     -- and the readout is lazy, so consumers that demand only a prefix pay almost
    
    362
    --- nothing beyond the fill.
    
    389
    +-- nothing beyond the fill (but the fill itself is unavoidable; see
    
    390
    +-- Note [Cost of deterministic iteration]).
    
    363 391
     --
    
    364 392
     -- Holes: slots whose tag never occurs keep the initial sentinel, a TaggedVal
    
    365 393
     -- with tag -1. Real tags are non-negative, so the readout skips on tag < 0;
    
    ... ... @@ -378,7 +406,9 @@ usePlacement :: Int -> Int -> Bool
    378 406
     usePlacement n i = i <= 4 * n
    
    379 407
     
    
    380 408
     -- | Order a list of 'TaggedVal's by tag, by placing each at array index =
    
    381
    --- its tag. The tags must be distinct and in @[0, i)@.
    
    409
    +-- its tag.
    
    410
    +--
    
    411
    +-- The tags must be distinct and in @[0, i)@.
    
    382 412
     -- See Note [Placement sort in eltsUDFM].
    
    383 413
     placementSort :: forall r. Int -> [TaggedVal r] -> [r]
    
    384 414
     placementSort i tvs = runST (ST (\s0 ->
    
    ... ... @@ -420,8 +450,10 @@ udfmRestrictKeysSet (UDFM val_set i) set =
    420 450
       in UDFM (M.restrictKeys val_set key_set) i
    
    421 451
     
    
    422 452
     -- | Converts `UniqDFM` to a list, with elements in deterministic order.
    
    453
    +--
    
    423 454
     -- It's O(n) in the common case, with an O(n log n) fallback
    
    424
    --- (see Note [Placement sort in eltsUDFM]).
    
    455
    +-- (see Note [Placement sort in eltsUDFM]), and pays that in full even if
    
    456
    +-- only a prefix is demanded (see Note [Cost of deterministic iteration]).
    
    425 457
     udfmToList :: UniqDFM key elt -> [(Unique, elt)]
    
    426 458
     udfmToList (UDFM m i)
    
    427 459
       | n <= 1           = [ (mkUniqueGrimily k, taggedFst v) | (k, v) <- M.toList m ]