[Git][ghc/ghc][master] Introduce UniqueSet and use it to replace 'UniqSet Unique'

Marge Bot (@marge-bot) gitlab at gitlab.haskell.org
Fri May 31 19:53:37 UTC 2024



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


Commits:
5f1afdf7 by Sylvain Henry at 2024-05-31T15:52:52-04:00
Introduce UniqueSet and use it to replace 'UniqSet Unique'

'UniqSet Unique' represents a set of uniques as a 'Map Unique Unique',
which is wasting space (associated key/value are always the same).

Fix #23572 and #23605

- - - - -


13 changed files:

- compiler/GHC/Builtin/Types.hs
- compiler/GHC/Cmm/LRegSet.hs
- compiler/GHC/Cmm/Liveness.hs
- compiler/GHC/Cmm/Sink.hs
- compiler/GHC/CmmToAsm/Wasm/Asm.hs
- compiler/GHC/CmmToAsm/Wasm/FromCmm.hs
- compiler/GHC/CmmToAsm/Wasm/Types.hs
- compiler/GHC/CmmToAsm/X86/Instr.hs
- compiler/GHC/Core/DataCon.hs
- compiler/GHC/Core/TyCon.hs
- compiler/GHC/Data/Word64Set/Internal.hs
- compiler/GHC/HsToCore/Pmc/Solver.hs
- compiler/GHC/Types/Unique/Set.hs


Changes:

=====================================
compiler/GHC/Builtin/Types.hs
=====================================
@@ -1040,13 +1040,13 @@ cTupleTyConName a = tyConName (cTupleTyCon a)
 cTupleTyConNames :: [Name]
 cTupleTyConNames = map cTupleTyConName (0 : [2..mAX_CTUPLE_SIZE])
 
-cTupleTyConKeys :: UniqSet Unique
-cTupleTyConKeys = mkUniqSet $ map getUnique cTupleTyConNames
+cTupleTyConKeys :: UniqueSet
+cTupleTyConKeys = fromListUniqueSet $ map getUnique cTupleTyConNames
 
 isCTupleTyConName :: Name -> Bool
 isCTupleTyConName n
  = assertPpr (isExternalName n) (ppr n) $
-   getUnique n `elementOfUniqSet` cTupleTyConKeys
+   getUnique n `memberUniqueSet` cTupleTyConKeys
 
 -- | If the given name is that of a constraint tuple, return its arity.
 cTupleTyConNameArity_maybe :: Name -> Maybe Arity


=====================================
compiler/GHC/Cmm/LRegSet.hs
=====================================
@@ -3,7 +3,6 @@
 
 module GHC.Cmm.LRegSet (
     LRegSet,
-    LRegKey,
 
     emptyLRegSet,
     nullLRegSet,
@@ -13,42 +12,52 @@ module GHC.Cmm.LRegSet (
     deleteFromLRegSet,
     sizeLRegSet,
 
-    plusLRegSet,
+    unionLRegSet,
+    unionsLRegSet,
     elemsLRegSet
   ) where
 
 import GHC.Prelude
 import GHC.Types.Unique
+import GHC.Types.Unique.Set
 import GHC.Cmm.Expr
-import GHC.Word
-
-import GHC.Data.Word64Set as Word64Set
 
 -- Compact sets for membership tests of local variables.
 
-type LRegSet = Word64Set.Word64Set
-type LRegKey = Word64
+type LRegSet = UniqueSet
 
+{-# INLINE emptyLRegSet #-}
 emptyLRegSet :: LRegSet
-emptyLRegSet = Word64Set.empty
+emptyLRegSet = emptyUniqueSet
 
+{-# INLINE nullLRegSet #-}
 nullLRegSet :: LRegSet -> Bool
-nullLRegSet = Word64Set.null
+nullLRegSet = nullUniqueSet
 
+{-# INLINE insertLRegSet #-}
 insertLRegSet :: LocalReg -> LRegSet -> LRegSet
-insertLRegSet l = Word64Set.insert (getKey (getUnique l))
+insertLRegSet l = insertUniqueSet (getUnique l)
 
+{-# INLINE elemLRegSet #-}
 elemLRegSet :: LocalReg -> LRegSet -> Bool
-elemLRegSet l = Word64Set.member (getKey (getUnique l))
+elemLRegSet l = memberUniqueSet (getUnique l)
 
+{-# INLINE deleteFromLRegSet #-}
 deleteFromLRegSet :: LRegSet -> LocalReg -> LRegSet
-deleteFromLRegSet set reg = Word64Set.delete (getKey . getUnique $ reg) set
+deleteFromLRegSet set reg = deleteUniqueSet (getUnique reg) set
+
+{-# INLINE sizeLRegSet #-}
+sizeLRegSet :: LRegSet -> Int
+sizeLRegSet = sizeUniqueSet
 
-sizeLRegSet :: Word64Set -> Int
-sizeLRegSet = Word64Set.size
+{-# INLINE unionLRegSet #-}
+unionLRegSet :: LRegSet -> LRegSet -> LRegSet
+unionLRegSet = unionUniqueSet
 
-plusLRegSet :: Word64Set -> Word64Set -> Word64Set
-plusLRegSet = Word64Set.union
+{-# INLINE unionsLRegSet #-}
+unionsLRegSet :: [LRegSet] -> LRegSet
+unionsLRegSet = unionsUniqueSet
 
-elemsLRegSet :: Word64Set -> [Word64]
-elemsLRegSet = Word64Set.toList
+{-# INLINE elemsLRegSet #-}
+elemsLRegSet :: LRegSet -> [Unique]
+elemsLRegSet = elemsUniqueSet


=====================================
compiler/GHC/Cmm/Liveness.hs
=====================================
@@ -26,8 +26,6 @@ import GHC.Data.Maybe
 import GHC.Utils.Outputable
 import GHC.Utils.Panic
 
-import GHC.Types.Unique
-
 -----------------------------------------------------------------------------
 -- Calculating what variables are live on entry to a basic block
 -----------------------------------------------------------------------------
@@ -112,7 +110,7 @@ liveLatticeL :: DataflowLattice LRegSet
 liveLatticeL = DataflowLattice emptyLRegSet add
   where
     add (OldFact old) (NewFact new) =
-        let !join = plusLRegSet old new
+        let !join = unionLRegSet old new
         in changedIf (sizeLRegSet join > sizeLRegSet old) join
 
 
@@ -132,7 +130,7 @@ noLiveOnEntryL bid in_fact x =
     where
         -- We convert the int's to uniques so that the printing matches that
         -- of registers.
-        reg_uniques = map mkUniqueGrimily $ elemsLRegSet in_fact
+        reg_uniques = elemsLRegSet in_fact
 
 
 


=====================================
compiler/GHC/Cmm/Sink.hs
=====================================
@@ -23,7 +23,6 @@ import GHC.Types.Unique.FM
 import GHC.Types.Unique.Supply
 import GHC.Cmm.Config
 
-import qualified GHC.Data.Word64Set as Word64Set
 import Data.List (partition)
 import Data.Maybe
 
@@ -186,8 +185,8 @@ cmmSink cfg graph = ofBlockList (g_entry graph) <$> sink mapEmpty blocks
               live_sets' | should_drop = live_sets
                         | otherwise   = map upd live_sets
 
-              upd set | r `elemLRegSet` set = set `Word64Set.union` live_rhs
-                      | otherwise          = set
+              upd set | r `elemLRegSet` set = set `unionLRegSet` live_rhs
+                      | otherwise           = set
 
               live_rhs = foldRegsUsed platform (flip insertLRegSet) emptyLRegSet rhs
 
@@ -208,7 +207,7 @@ cmmSink cfg graph = ofBlockList (g_entry graph) <$> sink mapEmpty blocks
       -- Annotate the middle nodes with the registers live *after*
       -- the node.  This will help us decide whether we can inline
       -- an assignment in the current node or not.
-      live = Word64Set.unions (map getLive succs)
+      live = unionsLRegSet (map getLive succs)
       live_middle = gen_killL platform last live
       ann_middles = annotate platform live_middle (blockToList middle)
 
@@ -216,7 +215,7 @@ cmmSink cfg graph = ofBlockList (g_entry graph) <$> sink mapEmpty blocks
       -- one predecessor), so identify the join points and the set
       -- of registers live in them.
       (joins, nonjoins) = partition (`mapMember` join_pts) succs
-      live_in_joins = Word64Set.unions (map getLive joins)
+      live_in_joins = unionsLRegSet (map getLive joins)
 
       -- We do not want to sink an assignment into multiple branches,
       -- so identify the set of registers live in multiple successors.


=====================================
compiler/GHC/CmmToAsm/Wasm/Asm.hs
=====================================
@@ -15,7 +15,6 @@ import Data.ByteString.Builder
 import qualified Data.ByteString.Char8 as BS8
 import Data.Coerce
 import Data.Foldable
-import qualified GHC.Data.Word64Set as WS
 import Data.Maybe
 import Data.Semigroup
 import GHC.Cmm
@@ -30,6 +29,7 @@ import GHC.Settings.Config (cProjectVersion)
 import GHC.Types.Basic
 import GHC.Types.Unique
 import GHC.Types.Unique.Map
+import GHC.Types.Unique.Set
 import GHC.Utils.Monad.State.Strict
 import GHC.Utils.Outputable hiding ((<>))
 import GHC.Utils.Panic (panic)
@@ -183,9 +183,9 @@ asmTellSectionHeader :: Builder -> WasmAsmM ()
 asmTellSectionHeader k = asmTellTabLine $ ".section " <> k <> ",\"\",@"
 
 asmTellDataSection ::
-  WasmTypeTag w -> WS.Word64Set -> SymName -> DataSection -> WasmAsmM ()
+  WasmTypeTag w -> UniqueSet -> SymName -> DataSection -> WasmAsmM ()
 asmTellDataSection ty_word def_syms sym DataSection {..} = do
-  when (getKey (getUnique sym) `WS.member` def_syms) $ asmTellDefSym sym
+  when (getUnique sym `memberUniqueSet` def_syms) $ asmTellDefSym sym
   asmTellSectionHeader sec_name
   asmTellAlign dataSectionAlignment
   asmTellTabLine asm_size
@@ -422,12 +422,12 @@ asmTellWasmControl ty_word c = case c of
 
 asmTellFunc ::
   WasmTypeTag w ->
-  WS.Word64Set ->
+  UniqueSet ->
   SymName ->
   (([SomeWasmType], [SomeWasmType]), FuncBody w) ->
   WasmAsmM ()
 asmTellFunc ty_word def_syms sym (func_ty, FuncBody {..}) = do
-  when (getKey (getUnique sym) `WS.member` def_syms) $ asmTellDefSym sym
+  when (getUnique sym `memberUniqueSet` def_syms) $ asmTellDefSym sym
   asmTellSectionHeader $ ".text." <> asm_sym
   asmTellLine $ asm_sym <> ":"
   asmTellFuncType sym func_ty


=====================================
compiler/GHC/CmmToAsm/Wasm/FromCmm.hs
=====================================
@@ -26,7 +26,6 @@ import Control.Monad
 import qualified Data.ByteString as BS
 import Data.Foldable
 import Data.Functor
-import qualified GHC.Data.Word64Set as WS
 import Data.Semigroup
 import Data.String
 import Data.Traversable
@@ -48,6 +47,7 @@ import GHC.Types.ForeignCall
 import GHC.Types.Unique
 import GHC.Types.Unique.FM
 import GHC.Types.Unique.Map
+import GHC.Types.Unique.Set
 import GHC.Types.Unique.Supply
 import GHC.Utils.Outputable hiding ((<>))
 import GHC.Utils.Panic
@@ -1600,8 +1600,8 @@ onTopSym lbl = case sym_vis of
   SymDefault -> wasmModifyM $ \s ->
     s
       { defaultSyms =
-          WS.insert
-            (getKey $ getUnique sym)
+          insertUniqueSet
+            (getUnique sym)
             $ defaultSyms s
       }
   _ -> pure ()


=====================================
compiler/GHC/CmmToAsm/Wasm/Types.hs
=====================================
@@ -52,7 +52,6 @@ import Control.Applicative
 import Data.ByteString (ByteString)
 import Data.Coerce
 import Data.Functor
-import qualified GHC.Data.Word64Set as WS
 import Data.Kind
 import Data.String
 import Data.Type.Equality
@@ -66,6 +65,7 @@ import GHC.Types.Basic
 import GHC.Types.Unique
 import GHC.Types.Unique.FM
 import GHC.Types.Unique.Map
+import GHC.Types.Unique.Set
 import GHC.Types.Unique.Supply
 import GHC.Utils.Monad.State.Strict
 import GHC.Utils.Outputable hiding ((<>))
@@ -197,7 +197,7 @@ data DataSection = DataSection
 type SymMap = UniqMap SymName
 
 -- | No need to remember the symbols.
-type SymSet = WS.Word64Set
+type SymSet = UniqueSet
 
 type GlobalInfo = (SymName, SomeWasmType)
 
@@ -427,7 +427,7 @@ initialWasmCodeGenState platform us =
   WasmCodeGenState
     { wasmPlatform =
         platform,
-      defaultSyms = WS.empty,
+      defaultSyms = emptyUniqueSet,
       funcTypes = emptyUniqMap,
       funcBodies =
         emptyUniqMap,


=====================================
compiler/GHC/CmmToAsm/X86/Instr.hs
=====================================
@@ -1083,7 +1083,7 @@ shortcutStatics fn (align, CmmStaticsRaw lbl statics)
 
 shortcutLabel :: (BlockId -> Maybe JumpDest) -> CLabel -> CLabel
 shortcutLabel fn lab
-  | Just blkId <- maybeLocalBlockLabel lab = shortBlockId fn emptyUniqSet blkId
+  | Just blkId <- maybeLocalBlockLabel lab = shortBlockId fn emptyUniqueSet blkId
   | otherwise                              = lab
 
 shortcutStatic :: (BlockId -> Maybe JumpDest) -> CmmStatic -> CmmStatic
@@ -1098,15 +1098,15 @@ shortcutStatic _ other_static
 
 shortBlockId
         :: (BlockId -> Maybe JumpDest)
-        -> UniqSet Unique
+        -> UniqueSet
         -> BlockId
         -> CLabel
 
 shortBlockId fn seen blockid =
-  case (elementOfUniqSet uq seen, fn blockid) of
+  case (memberUniqueSet uq seen, fn blockid) of
     (True, _)    -> blockLbl blockid
     (_, Nothing) -> blockLbl blockid
-    (_, Just (DestBlockId blockid'))  -> shortBlockId fn (addOneToUniqSet seen uq) blockid'
+    (_, Just (DestBlockId blockid'))  -> shortBlockId fn (insertUniqueSet uq seen) blockid'
     (_, Just (DestImm (ImmCLbl lbl))) -> lbl
     (_, _other) -> panic "shortBlockId"
   where uq = getUnique blockid


=====================================
compiler/GHC/Core/DataCon.hs
=====================================
@@ -1248,12 +1248,12 @@ freshNames avoids
     , let uniq = mkAlphaTyVarUnique n
           occ = mkTyVarOccFS (mkFastString ('x' : show n))
 
-    , not (uniq `elementOfUniqSet` avoid_uniqs)
+    , not (uniq `memberUniqueSet` avoid_uniqs)
     , not (occ `elemOccSet` avoid_occs) ]
 
   where
-    avoid_uniqs :: UniqSet Unique
-    avoid_uniqs = mkUniqSet (map getUnique avoids)
+    avoid_uniqs :: UniqueSet
+    avoid_uniqs = fromListUniqueSet (map getUnique avoids)
 
     avoid_occs :: OccSet
     avoid_occs = mkOccSet (map getOccName avoids)


=====================================
compiler/GHC/Core/TyCon.hs
=====================================
@@ -2331,12 +2331,12 @@ isKindName = isKindUniquable
 
 -- | The workhorse for 'isKindTyCon' and 'isKindName'.
 isKindUniquable :: Uniquable a => a -> Bool
-isKindUniquable thing = getUnique thing `elementOfUniqSet` kindTyConKeys
+isKindUniquable thing = getUnique thing `memberUniqueSet` kindTyConKeys
 
 -- | These TyCons should be allowed at the kind level, even without
 -- -XDataKinds.
-kindTyConKeys :: UniqSet Unique
-kindTyConKeys = unionManyUniqSets
+kindTyConKeys :: UniqueSet
+kindTyConKeys = fromListUniqueSet $
   -- Make sure to keep this in sync with the following:
   --
   -- - The Overview section in docs/users_guide/exts/data_kinds.rst in the GHC
@@ -2344,10 +2344,10 @@ kindTyConKeys = unionManyUniqSets
   --
   -- - The typecheck/should_compile/T22141f.hs test case, which ensures that all
   --   of these can successfully be used without DataKinds.
-  ( mkUniqSet [ liftedTypeKindTyConKey, liftedRepTyConKey, constraintKindTyConKey, tYPETyConKey, cONSTRAINTTyConKey ]
-  : map (mkUniqSet . tycon_with_datacons) [ runtimeRepTyCon, levityTyCon
-                                          , multiplicityTyCon
-                                          , vecCountTyCon, vecElemTyCon ] )
+  [ liftedTypeKindTyConKey, liftedRepTyConKey, constraintKindTyConKey, tYPETyConKey, cONSTRAINTTyConKey ]
+  ++ concatMap tycon_with_datacons [ runtimeRepTyCon, levityTyCon
+                                   , multiplicityTyCon
+                                   , vecCountTyCon, vecElemTyCon ]
   where
     tycon_with_datacons tc = getUnique tc : map getUnique (tyConDataCons tc)
 


=====================================
compiler/GHC/Data/Word64Set/Internal.hs
=====================================
@@ -205,7 +205,6 @@ import Text.Read
 import qualified GHC.Exts
 #endif
 
-import qualified Data.Foldable as Foldable
 import Data.Functor.Identity (Identity(..))
 
 infixl 9 \\{-This comment teaches CPP correct behaviour -}
@@ -519,10 +518,10 @@ alterF f k s = fmap choose (f member_)
   Union
 --------------------------------------------------------------------}
 -- | The union of a list of sets.
-unions :: Foldable f => f Word64Set -> Word64Set
-unions xs
-  = Foldable.foldl' union empty xs
 
+{-# INLINABLE unions #-}
+unions :: [Word64Set] -> Word64Set
+unions = List.foldl' union empty
 
 -- | \(O(n+m)\). The union of two sets.
 union :: Word64Set -> Word64Set -> Word64Set
@@ -1183,9 +1182,9 @@ foldlFB = foldl
 
 
 -- | \(O(n \min(n,W))\). Create a set from a list of integers.
+{-# INLINABLE fromList #-}
 fromList :: [Key] -> Word64Set
-fromList xs
-  = Foldable.foldl' ins empty xs
+fromList = List.foldl' ins empty
   where
     ins t x  = insert x t
 


=====================================
compiler/GHC/HsToCore/Pmc/Solver.hs
=====================================
@@ -1466,11 +1466,11 @@ dataConMightBeUnliftedFieldTys =
   filter mightBeUnliftedType . map scaledThing . dataConOrigArgTys
 
 isTyConTriviallyInhabited :: TyCon -> Bool
-isTyConTriviallyInhabited tc = elementOfUniqSet (getUnique tc) triviallyInhabitedTyConKeys
+isTyConTriviallyInhabited tc = memberUniqueSet (getUnique tc) triviallyInhabitedTyConKeys
 
 -- | All these types are trivially inhabited
-triviallyInhabitedTyConKeys :: UniqSet Unique
-triviallyInhabitedTyConKeys = mkUniqSet [
+triviallyInhabitedTyConKeys :: UniqueSet
+triviallyInhabitedTyConKeys = fromListUniqueSet [
     charTyConKey, doubleTyConKey, floatTyConKey,
     intTyConKey, int8TyConKey, int16TyConKey, int32TyConKey, int64TyConKey,
     intPrimTyConKey, int8PrimTyConKey, int16PrimTyConKey, int32PrimTyConKey, int64PrimTyConKey,


=====================================
compiler/GHC/Types/Unique/Set.hs
=====================================
@@ -44,6 +44,26 @@ module GHC.Types.Unique.Set (
         nonDetEltsUniqSet,
         nonDetKeysUniqSet,
         nonDetStrictFoldUniqSet,
+
+        -- UniqueSet
+        UniqueSet(..),
+        nullUniqueSet,
+        sizeUniqueSet,
+        memberUniqueSet,
+        emptyUniqueSet,
+        singletonUniqueSet,
+        insertUniqueSet,
+        deleteUniqueSet,
+        differenceUniqueSet,
+        unionUniqueSet,
+        unionsUniqueSet,
+        intersectionUniqueSet,
+        isSubsetOfUniqueSet,
+        filterUniqueSet,
+        foldlUniqueSet,
+        foldrUniqueSet,
+        elemsUniqueSet,
+        fromListUniqueSet,
     ) where
 
 import GHC.Prelude
@@ -56,6 +76,7 @@ import GHC.Utils.Outputable
 import Data.Data
 import qualified Data.Semigroup as Semi
 import Control.DeepSeq
+import qualified GHC.Data.Word64Set as S
 
 -- Note [UniqSet invariant]
 -- ~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -64,6 +85,7 @@ import Control.DeepSeq
 -- It means that to implement mapUniqSet you have to update
 -- both the keys and the values.
 
+-- | Set of Uniquable values
 newtype UniqSet a = UniqSet {getUniqSet' :: UniqFM a a}
                   deriving (Data, Semi.Semigroup, Monoid)
 
@@ -205,6 +227,83 @@ pprUniqSet :: (a -> SDoc) -> UniqSet a -> SDoc
 -- pretty-printing.
 pprUniqSet f = braces . pprWithCommas f . nonDetEltsUniqSet
 
-
 forceUniqSet :: (a -> ()) -> UniqSet a -> ()
 forceUniqSet f (UniqSet fm) = seqEltsUFM f fm
+
+--------------------------------------------------------
+-- UniqueSet
+--------------------------------------------------------
+
+-- | Set of Unique values
+--
+-- Similar to 'UniqSet Unique' but with a more compact representation.
+newtype UniqueSet = US { unUniqueSet :: S.Word64Set }
+  deriving (Eq, Ord, Show, Semigroup, Monoid)
+
+{-# INLINE nullUniqueSet #-}
+nullUniqueSet :: UniqueSet -> Bool
+nullUniqueSet (US s) = S.null s
+
+{-# INLINE sizeUniqueSet #-}
+sizeUniqueSet :: UniqueSet -> Int
+sizeUniqueSet (US s) = S.size s
+
+{-# INLINE memberUniqueSet #-}
+memberUniqueSet :: Unique -> UniqueSet -> Bool
+memberUniqueSet k (US s) = S.member (getKey k) s
+
+{-# INLINE emptyUniqueSet #-}
+emptyUniqueSet :: UniqueSet
+emptyUniqueSet = US S.empty
+
+{-# INLINE singletonUniqueSet #-}
+singletonUniqueSet :: Unique -> UniqueSet
+singletonUniqueSet k = US (S.singleton (getKey k))
+
+{-# INLINE insertUniqueSet #-}
+insertUniqueSet :: Unique -> UniqueSet -> UniqueSet
+insertUniqueSet k (US s) = US (S.insert (getKey k) s)
+
+{-# INLINE deleteUniqueSet #-}
+deleteUniqueSet :: Unique -> UniqueSet -> UniqueSet
+deleteUniqueSet k (US s) = US (S.delete (getKey k) s)
+
+{-# INLINE unionUniqueSet #-}
+unionUniqueSet :: UniqueSet -> UniqueSet -> UniqueSet
+unionUniqueSet (US x) (US y) = US (S.union x y)
+
+{-# INLINE unionsUniqueSet #-}
+unionsUniqueSet :: [UniqueSet] -> UniqueSet
+unionsUniqueSet xs = US (S.unions (map unUniqueSet xs))
+
+{-# INLINE differenceUniqueSet #-}
+differenceUniqueSet :: UniqueSet -> UniqueSet -> UniqueSet
+differenceUniqueSet (US x) (US y) = US (S.difference x y)
+
+{-# INLINE intersectionUniqueSet #-}
+intersectionUniqueSet :: UniqueSet -> UniqueSet -> UniqueSet
+intersectionUniqueSet (US x) (US y) = US (S.intersection x y)
+
+{-# INLINE isSubsetOfUniqueSet #-}
+isSubsetOfUniqueSet :: UniqueSet -> UniqueSet -> Bool
+isSubsetOfUniqueSet (US x) (US y) = S.isSubsetOf x y
+
+{-# INLINE filterUniqueSet #-}
+filterUniqueSet :: (Unique -> Bool) -> UniqueSet -> UniqueSet
+filterUniqueSet f (US s) = US (S.filter (f . mkUniqueGrimily) s)
+
+{-# INLINE foldlUniqueSet #-}
+foldlUniqueSet :: (a -> Unique -> a) -> a -> UniqueSet -> a
+foldlUniqueSet k z (US s) = S.foldl' (\a b -> k a (mkUniqueGrimily b)) z s
+
+{-# INLINE foldrUniqueSet #-}
+foldrUniqueSet :: (Unique -> b -> b) -> b -> UniqueSet -> b
+foldrUniqueSet k z (US s) = S.foldr (k . mkUniqueGrimily) z s
+
+{-# INLINE elemsUniqueSet #-}
+elemsUniqueSet :: UniqueSet -> [Unique]
+elemsUniqueSet (US s) = map mkUniqueGrimily (S.elems s)
+
+{-# INLINE fromListUniqueSet #-}
+fromListUniqueSet :: [Unique] -> UniqueSet
+fromListUniqueSet ks = US (S.fromList (map getKey ks))



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/5f1afdf73ab7857c41a923a1435ffa081bf099fe

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/5f1afdf73ab7857c41a923a1435ffa081bf099fe
You're receiving this email because of your account on gitlab.haskell.org.


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


More information about the ghc-commits mailing list