Simon Peyton Jones pushed to branch wip/T23109 at Glasgow Haskell Compiler / GHC
Commits:
-
2c0b59c5
by Simon Peyton Jones at 2025-07-02T16:32:44+01:00
3 changed files:
Changes:
... | ... | @@ -1506,6 +1506,10 @@ There are a number of wrinkles |
1506 | 1506 | guide inlining) treats (MkUC e) as the same size as `e`, and similarly
|
1507 | 1507 | (op d).
|
1508 | 1508 | |
1509 | + - `GHC.Core.Unfold.inlineBoringOK` where we want to ensure that we
|
|
1510 | + always-inline (MkUC op), even into a boring context. See (IB6)
|
|
1511 | + in Note [inlineBoringOk]
|
|
1512 | + |
|
1509 | 1513 | (UCM5) `GHC.Core.Unfold.Make.mkDFunUnfolding` builds a `DFunUnfolding` for
|
1510 | 1514 | non-unary classes, but just an /ordinary/ unfolding for unary classes.
|
1511 | 1515 | instance Num a => Num [a] where { .. } -- (I1)
|
... | ... | @@ -278,6 +278,14 @@ inlining a saturated call is no bigger than `body`. Some wrinkles: |
278 | 278 | whose body is, in some sense, just as small as (g x y z).
|
279 | 279 | But `inlineBoringOk` doesn't attempt anything fancy; it just looks
|
280 | 280 | for a function call with trivial arguments, Keep it simple.
|
281 | + |
|
282 | +(IB6) If we have an unfolding (K op) where K is a unary-class data constructor,
|
|
283 | + we want to inline it! So that we get calls (f op), which in turn can see (in
|
|
284 | + STG land) that `op` is already evaluated and properly tagged. (If `op` isn't
|
|
285 | + trivial we will have baled out before we get to the Var case.) This made
|
|
286 | + a big difference in benchmarks for the `effectful` library; details in !10479.
|
|
287 | + |
|
288 | + See Note [Unary class magic] in GHC/Core/TyCon.
|
|
281 | 289 | -}
|
282 | 290 | |
283 | 291 | inlineBoringOk :: CoreExpr -> Bool
|
... | ... | @@ -291,6 +299,7 @@ inlineBoringOk e |
291 | 299 | is_fun = isValFun e
|
292 | 300 | |
293 | 301 | go :: Int -> CoreExpr -> Bool
|
302 | + -- credit = #(value lambdas) = #(value args)
|
|
294 | 303 | go credit (Lam x e) | isRuntimeVar x = go (credit+1) e
|
295 | 304 | | otherwise = go credit e -- See (IB3)
|
296 | 305 | |
... | ... | @@ -309,13 +318,15 @@ inlineBoringOk e |
309 | 318 | go credit (Tick _ e) = go credit e -- dubious
|
310 | 319 | go credit (Cast e _) = go credit e -- See (IB3)
|
311 | 320 | |
321 | + -- Lit: we assume credit >= 0; literals aren't functions
|
|
312 | 322 | go _ (Lit l) = litIsTrivial l && boringCxtOk
|
313 | 323 | |
314 | - -- We assume credit >= 0; literals aren't functions
|
|
315 | 324 | go credit (Var v) | isDataConWorkId v, is_fun = boringCxtOk -- See (IB2)
|
325 | + | isUnaryClassId v = boringCxtOk -- See (IB6)
|
|
316 | 326 | | credit >= 0 = boringCxtOk
|
317 | 327 | | otherwise = boringCxtNotOk
|
318 | - go _ _ = boringCxtNotOk
|
|
328 | + |
|
329 | + go _ _ = boringCxtNotOk
|
|
319 | 330 | |
320 | 331 | isValFun :: CoreExpr -> Bool
|
321 | 332 | -- True of functions with at least
|
... | ... | @@ -836,19 +836,20 @@ myCollectArgs expr res_ty |
836 | 836 | where
|
837 | 837 | go h@(Var f) as ts
|
838 | 838 | | isUnaryClassId f, (the_arg:as') <- dropWhile isTypeArg as
|
839 | - = go the_arg as' ts
|
|
839 | + = go the_arg as' ts
|
|
840 | 840 | -- See (UCM1) in Note [Unary class magic] in GHC.Core.TyCon
|
841 | 841 | -- isUnaryClassId includes both the class op and the data-con
|
842 | - | otherwise = (h, as, ts)
|
|
843 | 842 | |
844 | - go (App f a) as ts = go f (a:as) ts
|
|
845 | - go (Cast e _) as ts = go e as ts
|
|
843 | + | otherwise
|
|
844 | + = (h, as, ts)
|
|
846 | 845 | |
847 | - go (Tick t e) as ts = assertPpr (not (tickishIsCode t) || all isTypeArg as)
|
|
848 | - (ppr e $$ ppr as $$ ppr ts) $
|
|
849 | - -- See Note [Ticks in applications]
|
|
850 | - -- ticks can appear in type apps
|
|
851 | - go e as (coreToStgTick res_ty t : ts)
|
|
846 | + go (App f a) as ts = go f (a:as) ts
|
|
847 | + go (Cast e _) as ts = go e as ts
|
|
848 | + go (Tick t e) as ts = assertPpr (not (tickishIsCode t) || all isTypeArg as)
|
|
849 | + (ppr e $$ ppr as $$ ppr ts) $
|
|
850 | + -- See Note [Ticks in applications]
|
|
851 | + -- ticks can appear in type apps
|
|
852 | + go e as (coreToStgTick res_ty t : ts)
|
|
852 | 853 | |
853 | 854 | go (Case e b _ alts) as ts -- Just like in exprIsTrivial!
|
854 | 855 | -- Otherwise we fall over in case we encounter
|
... | ... | @@ -859,10 +860,11 @@ myCollectArgs expr res_ty |
859 | 860 | | Just rhs <- isUnsafeEqualityCase e b alts
|
860 | 861 | = go rhs as ts -- Discards unsafeCoerce in App heads
|
861 | 862 | |
862 | - go (Lam b e) as ts
|
|
863 | - | isTyVar b = go e (drop 1 as) ts -- Note [Collect args]
|
|
863 | + go (Lam b e) as ts
|
|
864 | + | isTyVar b
|
|
865 | + = go e (drop 1 as) ts -- Note [Collect args]
|
|
864 | 866 | |
865 | - go e as ts = (e, as, ts)
|
|
867 | + go e as ts = (e, as, ts)
|
|
866 | 868 | |
867 | 869 | {- Note [Collect args]
|
868 | 870 | ~~~~~~~~~~~~~~~~~~~~~~
|