| ... |
... |
@@ -327,28 +327,60 @@ instance TrieMap m => Foldable (ListMap m) where |
|
327
|
327
|
instance (TrieMap m, Outputable a) => Outputable (ListMap m a) where
|
|
328
|
328
|
ppr m = text "List elts" <+> ppr (foldTM (:) m [])
|
|
329
|
329
|
|
|
|
330
|
+{- Note [Making ListMap operations specialisable]
|
|
|
331
|
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
332
|
+The 'TrieMap (ListMap m)' methods are thin wrappers around these helpers:
|
|
|
333
|
+
|
|
|
334
|
+ lookupTM = lkList lookupTM
|
|
|
335
|
+ alterTM = xtList alterTM
|
|
|
336
|
+ foldTM = fdList
|
|
|
337
|
+ filterTM = ftList
|
|
|
338
|
+ mapMaybeTM = mpList
|
|
|
339
|
+
|
|
|
340
|
+When these methods are used from another module, the wrappers would otherwise
|
|
|
341
|
+remain higher-order and polymorphic in the inner trie map. That leaves the
|
|
|
342
|
+recursive loops in 'xtList', 'fdList', 'ftList', and 'mpList' calling the
|
|
|
343
|
+inner-map operations indirectly via the 'TrieMap m' dictionary (#27097).
|
|
|
344
|
+
|
|
|
345
|
+Marking the helpers 'INLINABLE' exposes unfoldings to importing modules, so
|
|
|
346
|
+the specialiser can monomorphise those loops; see Note [Specialising imported
|
|
|
347
|
+functions] in GHC.Core.Opt.Specialise.
|
|
|
348
|
+
|
|
|
349
|
+Adding the 'INLINABLE' pragmas reduced compiler allocations by 2.9% in
|
|
|
350
|
+InstanceMatching and by 2.0% in T24984.
|
|
|
351
|
+
|
|
|
352
|
+We mark 'lkList' too, even though it does not itself use the 'TrieMap m'
|
|
|
353
|
+dictionary and GHC already gives it a non-dictionary-passing worker, for
|
|
|
354
|
+consistency with the other ListMap operations.
|
|
|
355
|
+-}
|
|
|
356
|
+
|
|
330
|
357
|
lkList :: TrieMap m => (forall b. k -> m b -> Maybe b)
|
|
331
|
358
|
-> [k] -> ListMap m a -> Maybe a
|
|
332
|
359
|
lkList _ [] = lm_nil
|
|
333
|
360
|
lkList lk (x:xs) = lm_cons >.> lk x >=> lkList lk xs
|
|
|
361
|
+{-# INLINABLE lkList #-} -- See Note [Making ListMap operations specialisable]
|
|
334
|
362
|
|
|
335
|
363
|
xtList :: TrieMap m => (forall b. k -> XT b -> m b -> m b)
|
|
336
|
364
|
-> [k] -> XT a -> ListMap m a -> ListMap m a
|
|
337
|
365
|
xtList _ [] f m = m { lm_nil = f (lm_nil m) }
|
|
338
|
366
|
xtList tr (x:xs) f m = m { lm_cons = lm_cons m |> tr x |>> xtList tr xs f }
|
|
|
367
|
+{-# INLINABLE xtList #-} -- See Note [Making ListMap operations specialisable]
|
|
339
|
368
|
|
|
340
|
369
|
fdList :: forall m a b. TrieMap m
|
|
341
|
370
|
=> (a -> b -> b) -> ListMap m a -> b -> b
|
|
342
|
371
|
fdList k m = foldMaybe k (lm_nil m)
|
|
343
|
372
|
. foldTM (fdList k) (lm_cons m)
|
|
|
373
|
+{-# INLINABLE fdList #-} -- See Note [Making ListMap operations specialisable]
|
|
344
|
374
|
|
|
345
|
375
|
ftList :: TrieMap m => (a -> Bool) -> ListMap m a -> ListMap m a
|
|
346
|
376
|
ftList f (LM { lm_nil = mnil, lm_cons = mcons })
|
|
347
|
377
|
= LM { lm_nil = filterMaybe f mnil, lm_cons = fmap (filterTM f) mcons }
|
|
|
378
|
+{-# INLINABLE ftList #-} -- See Note [Making ListMap operations specialisable]
|
|
348
|
379
|
|
|
349
|
380
|
mpList :: TrieMap m => (a -> Maybe b) -> ListMap m a -> ListMap m b
|
|
350
|
381
|
mpList f (LM { lm_nil = mnil, lm_cons = mcons })
|
|
351
|
382
|
= LM { lm_nil = mnil >>= f, lm_cons = fmap (mapMaybeTM f) mcons }
|
|
|
383
|
+{-# INLINABLE mpList #-} -- See Note [Making ListMap operations specialisable]
|
|
352
|
384
|
|
|
353
|
385
|
{-
|
|
354
|
386
|
************************************************************************
|