Andreas Klebinger pushed to branch wip/andreask/occ_anal_tuning at Glasgow Haskell Compiler / GHC
Commits:
-
2076be78
by Andreas Klebinger at 2025-10-08T09:13:36+02:00
4 changed files:
- compiler/GHC/Core/Opt/OccurAnal.hs
- compiler/GHC/Data/Graph/UnVar.hs
- compiler/GHC/Types/Unique/FM.hs
- compiler/GHC/Types/Var/Env.hs
Changes:
| ... | ... | @@ -9,6 +9,8 @@ |
| 9 | 9 | -- many /other/ arguments the function has. Inconsistent unboxing is very
|
| 10 | 10 | -- bad for performance, so I increased the limit to allow it to unbox
|
| 11 | 11 | -- consistently.
|
| 12 | +-- AK: Seems we no longer unbox OccEnv now anyway so it might be redundant.
|
|
| 13 | + |
|
| 12 | 14 | |
| 13 | 15 | {-
|
| 14 | 16 | (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
|
| ... | ... | @@ -62,6 +64,7 @@ import GHC.Utils.Misc |
| 62 | 64 | |
| 63 | 65 | import GHC.Builtin.Names( runRWKey )
|
| 64 | 66 | import GHC.Unit.Module( Module )
|
| 67 | +import GHC.Data.Graph.UnVar as UnVar
|
|
| 65 | 68 | |
| 66 | 69 | import Data.List (mapAccumL)
|
| 67 | 70 | import Data.List.NonEmpty (NonEmpty (..))
|
| ... | ... | @@ -984,7 +987,7 @@ occAnalBind !env lvl ire (NonRec bndr rhs) thing_inside combine |
| 984 | 987 | = -- Analyse the RHS and /then/ the body
|
| 985 | 988 | let -- Analyse the rhs first, generating rhs_uds
|
| 986 | 989 | !(rhs_uds_s, bndr', rhs') = occAnalNonRecRhs env lvl ire mb_join bndr rhs
|
| 987 | - rhs_uds = foldr1 orUDs rhs_uds_s -- NB: orUDs. See (W4) of
|
|
| 990 | + rhs_uds = foldl1' orUDs rhs_uds_s -- NB: orUDs. See (W4) of
|
|
| 988 | 991 | -- Note [Occurrence analysis for join points]
|
| 989 | 992 | |
| 990 | 993 | -- Now analyse the body, adding the join point
|
| ... | ... | @@ -3610,6 +3613,7 @@ localTailCallInfo :: LocalOcc -> TailCallInfo |
| 3610 | 3613 | localTailCallInfo (OneOccL { lo_tail = tci }) = tci
|
| 3611 | 3614 | localTailCallInfo (ManyOccL tci) = tci
|
| 3612 | 3615 | |
| 3616 | +-- type ZappedSet = UnVar.UnVarSet -- Values are ignored
|
|
| 3613 | 3617 | type ZappedSet = OccInfoEnv -- Values are ignored
|
| 3614 | 3618 | |
| 3615 | 3619 | data UsageDetails
|
| ... | ... | @@ -3650,8 +3654,8 @@ data WithTailUsageDetails a = WTUD !TailUsageDetails !a |
| 3650 | 3654 | -------------------
|
| 3651 | 3655 | -- UsageDetails API
|
| 3652 | 3656 | |
| 3653 | -andUDs, orUDs
|
|
| 3654 | - :: UsageDetails -> UsageDetails -> UsageDetails
|
|
| 3657 | +andUDs:: UsageDetails -> UsageDetails -> UsageDetails
|
|
| 3658 | +orUDs :: UsageDetails -> UsageDetails -> UsageDetails
|
|
| 3655 | 3659 | andUDs = combineUsageDetailsWith andLocalOcc
|
| 3656 | 3660 | orUDs = combineUsageDetailsWith orLocalOcc
|
| 3657 | 3661 | |
| ... | ... | @@ -3760,16 +3764,20 @@ restrictFreeVars bndrs fvs = restrictUniqSetToUFM bndrs fvs |
| 3760 | 3764 | combineUsageDetailsWith :: (LocalOcc -> LocalOcc -> LocalOcc)
|
| 3761 | 3765 | -> UsageDetails -> UsageDetails -> UsageDetails
|
| 3762 | 3766 | {-# INLINE combineUsageDetailsWith #-}
|
| 3767 | +{-# SCC combineUsageDetailsWith #-}
|
|
| 3763 | 3768 | combineUsageDetailsWith plus_occ_info
|
| 3764 | 3769 | uds1@(UD { ud_env = env1, ud_z_many = z_many1, ud_z_in_lam = z_in_lam1, ud_z_tail = z_tail1 })
|
| 3765 | 3770 | uds2@(UD { ud_env = env2, ud_z_many = z_many2, ud_z_in_lam = z_in_lam2, ud_z_tail = z_tail2 })
|
| 3766 | 3771 | | isEmptyVarEnv env1 = uds2
|
| 3767 | 3772 | | isEmptyVarEnv env2 = uds1
|
| 3768 | 3773 | | otherwise
|
| 3769 | - = UD { ud_env = plusVarEnv_C plus_occ_info env1 env2
|
|
| 3770 | - , ud_z_many = plusVarEnv z_many1 z_many2
|
|
| 3771 | - , ud_z_in_lam = plusVarEnv z_in_lam1 z_in_lam2
|
|
| 3772 | - , ud_z_tail = plusVarEnv z_tail1 z_tail2 }
|
|
| 3774 | + -- Typically we end up forcing those values later anyway. So we can avoid storking thunks retaining
|
|
| 3775 | + -- the original LocalOcc by using a strict combination function here. The fields themselves are already
|
|
| 3776 | + -- strict so no need to force those explicitly.
|
|
| 3777 | + = UD { ud_env = {-# SCC ud_env #-} strictPlusVarEnv_C plus_occ_info env1 env2
|
|
| 3778 | + , ud_z_many = {-# SCC ud_z_many #-} strictPlusVarEnv z_many1 z_many2
|
|
| 3779 | + , ud_z_in_lam = {-# SCC ud_z_in_lam #-} strictPlusVarEnv z_in_lam1 z_in_lam2
|
|
| 3780 | + , ud_z_tail = {-# SCC ud_z_tail #-} strictPlusVarEnv z_tail1 z_tail2 }
|
|
| 3773 | 3781 | |
| 3774 | 3782 | lookupLetOccInfo :: UsageDetails -> Id -> OccInfo
|
| 3775 | 3783 | -- Don't use locally-generated occ_info for exported (visible-elsewhere)
|
| ... | ... | @@ -17,8 +17,8 @@ equal to g, but twice as expensive and large. |
| 17 | 17 | module GHC.Data.Graph.UnVar
|
| 18 | 18 | ( UnVarSet
|
| 19 | 19 | , emptyUnVarSet, mkUnVarSet, unionUnVarSet, unionUnVarSets
|
| 20 | - , extendUnVarSet, extendUnVarSetList, delUnVarSet, delUnVarSetList
|
|
| 21 | - , elemUnVarSet, isEmptyUnVarSet
|
|
| 20 | + , extendUnVarSet, extendUnVarSet_Directly, extendUnVarSetList, delUnVarSet, delUnVarSetList
|
|
| 21 | + , elemUnVarSet, elemUnVarSet_Directly, isEmptyUnVarSet
|
|
| 22 | 22 | , UnVarGraph
|
| 23 | 23 | , emptyUnVarGraph
|
| 24 | 24 | , unionUnVarGraph, unionUnVarGraphs
|
| ... | ... | @@ -60,6 +60,9 @@ emptyUnVarSet = UnVarSet S.empty |
| 60 | 60 | elemUnVarSet :: Var -> UnVarSet -> Bool
|
| 61 | 61 | elemUnVarSet v (UnVarSet s) = k v `S.member` s
|
| 62 | 62 | |
| 63 | +{-# INLINE elemUnVarSet_Directly #-}
|
|
| 64 | +elemUnVarSet_Directly :: Uniquable key => key -> UnVarSet -> Bool
|
|
| 65 | +elemUnVarSet_Directly v (UnVarSet s) = (getKey $ getUnique v) `S.member` s
|
|
| 63 | 66 | |
| 64 | 67 | isEmptyUnVarSet :: UnVarSet -> Bool
|
| 65 | 68 | isEmptyUnVarSet (UnVarSet s) = S.null s
|
| ... | ... | @@ -82,6 +85,10 @@ mkUnVarSet vs = UnVarSet $ S.fromList $ map k vs |
| 82 | 85 | extendUnVarSet :: Var -> UnVarSet -> UnVarSet
|
| 83 | 86 | extendUnVarSet v (UnVarSet s) = UnVarSet $ S.insert (k v) s
|
| 84 | 87 | |
| 88 | +{-# INLINE extendUnVarSet_Directly #-}
|
|
| 89 | +extendUnVarSet_Directly :: Uniquable key => key -> UnVarSet -> UnVarSet
|
|
| 90 | +extendUnVarSet_Directly u (UnVarSet s) = UnVarSet $ S.insert (getKey $ getUnique u) s
|
|
| 91 | + |
|
| 85 | 92 | extendUnVarSetList :: [Var] -> UnVarSet -> UnVarSet
|
| 86 | 93 | extendUnVarSetList vs s = s `unionUnVarSet` mkUnVarSet vs
|
| 87 | 94 |
| ... | ... | @@ -51,7 +51,9 @@ module GHC.Types.Unique.FM ( |
| 51 | 51 | delListFromUFM,
|
| 52 | 52 | delListFromUFM_Directly,
|
| 53 | 53 | plusUFM,
|
| 54 | + strictPlusUFM,
|
|
| 54 | 55 | plusUFM_C,
|
| 56 | + strictPlusUFM_C,
|
|
| 55 | 57 | plusUFM_CD,
|
| 56 | 58 | plusUFM_CD2,
|
| 57 | 59 | mergeUFM,
|
| ... | ... | @@ -251,16 +253,24 @@ delListFromUFM_Directly = foldl' delFromUFM_Directly |
| 251 | 253 | delFromUFM_Directly :: UniqFM key elt -> Unique -> UniqFM key elt
|
| 252 | 254 | delFromUFM_Directly (UFM m) u = UFM (M.delete (getKey u) m)
|
| 253 | 255 | |
| 254 | --- Bindings in right argument shadow those in the left
|
|
| 256 | +-- | Bindings in right argument shadow those in the left.
|
|
| 257 | +--
|
|
| 258 | +-- Unlike containers this union is right-biased for historic reasons.
|
|
| 255 | 259 | plusUFM :: UniqFM key elt -> UniqFM key elt -> UniqFM key elt
|
| 256 | --- M.union is left-biased, plusUFM should be right-biased.
|
|
| 257 | 260 | plusUFM (UFM x) (UFM y) = UFM (M.union y x)
|
| 258 | 261 | -- Note (M.union y x), with arguments flipped
|
| 259 | 262 | -- M.union is left-biased, plusUFM should be right-biased.
|
| 260 | 263 | |
| 264 | +-- | Right biased
|
|
| 265 | +strictPlusUFM :: UniqFM key elt -> UniqFM key elt -> UniqFM key elt
|
|
| 266 | +strictPlusUFM (UFM x) (UFM y) = UFM (MS.union y x)
|
|
| 267 | + |
|
| 261 | 268 | plusUFM_C :: (elt -> elt -> elt) -> UniqFM key elt -> UniqFM key elt -> UniqFM key elt
|
| 262 | 269 | plusUFM_C f (UFM x) (UFM y) = UFM (M.unionWith f x y)
|
| 263 | 270 | |
| 271 | +strictPlusUFM_C :: (elt -> elt -> elt) -> UniqFM key elt -> UniqFM key elt -> UniqFM key elt
|
|
| 272 | +strictPlusUFM_C f (UFM x) (UFM y) = UFM (MS.unionWith f x y)
|
|
| 273 | + |
|
| 264 | 274 | -- | `plusUFM_CD f m1 d1 m2 d2` merges the maps using `f` as the
|
| 265 | 275 | -- combinding function and `d1` resp. `d2` as the default value if
|
| 266 | 276 | -- there is no entry in `m1` reps. `m2`. The domain is the union of
|
| ... | ... | @@ -12,7 +12,8 @@ module GHC.Types.Var.Env ( |
| 12 | 12 | elemVarEnv, disjointVarEnv, anyVarEnv,
|
| 13 | 13 | extendVarEnv, extendVarEnv_C, extendVarEnv_Acc,
|
| 14 | 14 | extendVarEnvList,
|
| 15 | - plusVarEnv, plusVarEnv_C, plusVarEnv_CD, plusMaybeVarEnv_C,
|
|
| 15 | + strictPlusVarEnv, plusVarEnv, plusVarEnv_C, strictPlusVarEnv_C,
|
|
| 16 | + plusVarEnv_CD, plusMaybeVarEnv_C,
|
|
| 16 | 17 | plusVarEnvList, alterVarEnv,
|
| 17 | 18 | delVarEnvList, delVarEnv,
|
| 18 | 19 | minusVarEnv,
|
| ... | ... | @@ -511,6 +512,7 @@ extendVarEnv :: VarEnv a -> Var -> a -> VarEnv a |
| 511 | 512 | extendVarEnv_C :: (a->a->a) -> VarEnv a -> Var -> a -> VarEnv a
|
| 512 | 513 | extendVarEnv_Acc :: (a->b->b) -> (a->b) -> VarEnv b -> Var -> a -> VarEnv b
|
| 513 | 514 | plusVarEnv :: VarEnv a -> VarEnv a -> VarEnv a
|
| 515 | +strictPlusVarEnv :: VarEnv a -> VarEnv a -> VarEnv a
|
|
| 514 | 516 | plusVarEnvList :: [VarEnv a] -> VarEnv a
|
| 515 | 517 | extendVarEnvList :: VarEnv a -> [(Var, a)] -> VarEnv a
|
| 516 | 518 | varEnvDomain :: VarEnv elt -> UnVarSet
|
| ... | ... | @@ -522,6 +524,7 @@ delVarEnvList :: Foldable f => VarEnv a -> f Var -> VarEnv a |
| 522 | 524 | delVarEnv :: VarEnv a -> Var -> VarEnv a
|
| 523 | 525 | minusVarEnv :: VarEnv a -> VarEnv b -> VarEnv a
|
| 524 | 526 | plusVarEnv_C :: (a -> a -> a) -> VarEnv a -> VarEnv a -> VarEnv a
|
| 527 | +strictPlusVarEnv_C :: (a -> a -> a) -> VarEnv a -> VarEnv a -> VarEnv a
|
|
| 525 | 528 | plusVarEnv_CD :: (a -> a -> a) -> VarEnv a -> a -> VarEnv a -> a -> VarEnv a
|
| 526 | 529 | plusMaybeVarEnv_C :: (a -> a -> Maybe a) -> VarEnv a -> VarEnv a -> VarEnv a
|
| 527 | 530 | mapVarEnv :: (a -> b) -> VarEnv a -> VarEnv b
|
| ... | ... | @@ -548,6 +551,7 @@ extendVarEnv_C = addToUFM_C |
| 548 | 551 | extendVarEnv_Acc = addToUFM_Acc
|
| 549 | 552 | extendVarEnvList = addListToUFM
|
| 550 | 553 | plusVarEnv_C = plusUFM_C
|
| 554 | +strictPlusVarEnv_C = strictPlusUFM_C
|
|
| 551 | 555 | plusVarEnv_CD = plusUFM_CD
|
| 552 | 556 | plusMaybeVarEnv_C = plusMaybeUFM_C
|
| 553 | 557 | delVarEnvList = delListFromUFM
|
| ... | ... | @@ -556,6 +560,7 @@ delVarEnvList = delListFromUFM |
| 556 | 560 | delVarEnv = delFromUFM
|
| 557 | 561 | minusVarEnv = minusUFM
|
| 558 | 562 | plusVarEnv = plusUFM
|
| 563 | +strictPlusVarEnv = strictPlusUFM
|
|
| 559 | 564 | plusVarEnvList = plusUFMList
|
| 560 | 565 | -- lookupVarEnv is very hot (in part due to being called by substTyVar),
|
| 561 | 566 | -- if it's not inlined than the mere allocation of the Just constructor causes
|