Simon Peyton Jones pushed to branch wip/spj-try-opt-coercion at Glasgow Haskell Compiler / GHC
Commits:
-
c72a1a15
by Simon Peyton Jones at 2026-01-02T17:37:33+00:00
-
bea0ee5a
by Simon Peyton Jones at 2026-01-04T23:46:18+00:00
12 changed files:
- compiler/GHC/Core/Coercion.hs
- compiler/GHC/Core/FVs.hs
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Opt/Simplify/Env.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Core/TyCo/Rep.hs
- compiler/GHC/Core/Utils.hs
- compiler/GHC/CoreToStg.hs
- compiler/GHC/CoreToStg/Prep.hs
- compiler/GHC/Driver/Config/Core/Lint.hs
- compiler/GHC/Iface/Tidy.hs
Changes:
| ... | ... | @@ -172,7 +172,6 @@ import qualified Data.Monoid as Monoid |
| 172 | 172 | import Data.List.NonEmpty ( NonEmpty (..) )
|
| 173 | 173 | import Control.DeepSeq
|
| 174 | 174 | |
| 175 | -import GHC.Exts
|
|
| 176 | 175 | |
| 177 | 176 | {-
|
| 178 | 177 | %************************************************************************
|
| ... | ... | @@ -2473,40 +2472,6 @@ seqCos :: [Coercion] -> () |
| 2473 | 2472 | seqCos [] = ()
|
| 2474 | 2473 | seqCos (co:cos) = seqCo co `seq` seqCos cos
|
| 2475 | 2474 | |
| 2476 | -coercionIsSmall :: Coercion -> Bool
|
|
| 2477 | --- This function should return False quickly on a big coercion
|
|
| 2478 | --- It should /not/ traverse the big coercion!
|
|
| 2479 | -coercionIsSmall co
|
|
| 2480 | - = not (isTrue# ((go co 100#) <# 0#))
|
|
| 2481 | - where
|
|
| 2482 | - go :: Coercion -> Int# -> Int#
|
|
| 2483 | - go _co n | isTrue# (n <# 0#) = n
|
|
| 2484 | - go (Refl {}) n = dec n
|
|
| 2485 | - go (GRefl _ _ mco) n = go_mco mco (dec n)
|
|
| 2486 | - go (TyConAppCo _ _ cos) n = go_cos cos (dec n)
|
|
| 2487 | - go (AxiomCo _ cos) n = go_cos cos (dec n)
|
|
| 2488 | - go (UnivCo _ _ _ _ cos) n = go_cos cos (dec n)
|
|
| 2489 | - go (AppCo co1 co2) n = go co1 (go co2 (dec n))
|
|
| 2490 | - go (CoVarCo {}) n = dec n
|
|
| 2491 | - go (HoleCo {}) n = dec n
|
|
| 2492 | - go (SymCo co) n = go co (dec n)
|
|
| 2493 | - go (KindCo co) n = go co (dec n)
|
|
| 2494 | - go (SubCo co) n = go co (dec n)
|
|
| 2495 | - go (TransCo co1 co2) n = go co1 (go co2 (dec n))
|
|
| 2496 | - go (SelCo _ co) n = go co (dec n)
|
|
| 2497 | - go (LRCo _ co) n = go co (dec n)
|
|
| 2498 | - go (InstCo co1 co2) n = go co1 (go co2 (dec n))
|
|
| 2499 | - go (ForAllCo _ _ _ kco co) n = go co (go_mco kco (dec n))
|
|
| 2500 | - go (FunCo _ _ _ mco aco rco) n = go mco (go aco (go rco (dec n)))
|
|
| 2501 | - |
|
| 2502 | - go_cos [] n = n
|
|
| 2503 | - go_cos (co:cos) n = go_cos cos (go co n)
|
|
| 2504 | - |
|
| 2505 | - go_mco MRefl n = dec n
|
|
| 2506 | - go_mco (MCo co) n = go co n
|
|
| 2507 | - |
|
| 2508 | - dec n = n -# 1#
|
|
| 2509 | - |
|
| 2510 | 2475 | {-
|
| 2511 | 2476 | %************************************************************************
|
| 2512 | 2477 | %* *
|
| ... | ... | @@ -29,12 +29,14 @@ module GHC.Core.FVs ( |
| 29 | 29 | idUnfoldingVars, idFreeVars, dIdFreeVars,
|
| 30 | 30 | bndrRuleAndUnfoldingVarsDSet,
|
| 31 | 31 | bndrRuleAndUnfoldingIds,
|
| 32 | - idFVs,
|
|
| 33 | - idRuleVars, stableUnfoldingVars,
|
|
| 32 | + idFVs, idRuleVars,
|
|
| 33 | + stableUnfoldingVars,
|
|
| 34 | + unfoldingFVs,
|
|
| 34 | 35 | ruleFreeVars, rulesFreeVars,
|
| 35 | 36 | rulesFreeVarsDSet, mkRuleInfo,
|
| 36 | 37 | ruleLhsFreeIds, ruleLhsFreeIdsList,
|
| 37 | 38 | ruleRhsFreeVars, rulesRhsFreeIds,
|
| 39 | + rulesFVs, RuleFVsFrom(..),
|
|
| 38 | 40 | |
| 39 | 41 | exprFVs, exprLocalFVs, addBndrFV, addBndrsFV,
|
| 40 | 42 | |
| ... | ... | @@ -645,17 +647,18 @@ idUnfoldingFVs id = stableUnfoldingFVs (realIdUnfolding id) `orElse` emptyFV |
| 645 | 647 | stableUnfoldingVars :: Unfolding -> Maybe VarSet
|
| 646 | 648 | stableUnfoldingVars unf = fvVarSet `fmap` stableUnfoldingFVs unf
|
| 647 | 649 | |
| 648 | -stableUnfoldingFVs :: Unfolding -> Maybe FV
|
|
| 649 | 650 | stableUnfoldingFVs unf
|
| 650 | - = case unf of
|
|
| 651 | - CoreUnfolding { uf_tmpl = rhs, uf_src = src }
|
|
| 652 | - | isStableSource src
|
|
| 653 | - -> Just (exprLocalFVs rhs)
|
|
| 654 | - DFunUnfolding { df_bndrs = bndrs, df_args = args }
|
|
| 655 | - -> Just (filterFV isLocalVar $ FV.delFVs (mkVarSet bndrs) $ exprsFVs args)
|
|
| 656 | - -- DFuns are top level, so no fvs from types of bndrs
|
|
| 657 | - _other -> Nothing
|
|
| 658 | - |
|
| 651 | + | isStableUnfolding unf = Just (unfoldingFVs unf)
|
|
| 652 | + | otherwise = Nothing
|
|
| 653 | + |
|
| 654 | +unfoldingFVs :: Unfolding -> FV
|
|
| 655 | +unfoldingFVs (CoreUnfolding { uf_tmpl = rhs })
|
|
| 656 | + = exprLocalFVs rhs
|
|
| 657 | +unfoldingFVs (DFunUnfolding { df_bndrs = bndrs, df_args = args })
|
|
| 658 | + = FV.delFVs (mkVarSet bndrs) $ exprsLocalFVs args
|
|
| 659 | + -- DFuns are top level, so no fvs from types of bndrs
|
|
| 660 | +unfoldingFVs _
|
|
| 661 | + = emptyFV
|
|
| 659 | 662 | |
| 660 | 663 | {-
|
| 661 | 664 | ************************************************************************
|
| ... | ... | @@ -82,7 +82,6 @@ import GHC.Types.Basic |
| 82 | 82 | import GHC.Types.Demand ( splitDmdSig, isDeadEndDiv )
|
| 83 | 83 | |
| 84 | 84 | import GHC.Builtin.Names
|
| 85 | -import GHC.Builtin.Types.Prim
|
|
| 86 | 85 | |
| 87 | 86 | import GHC.Data.Bag
|
| 88 | 87 | import GHC.Data.List.SetOps
|
| ... | ... | @@ -589,19 +588,20 @@ lintLetBind top_lvl rec_flag binder rhs rhs_ty |
| 589 | 588 | |
| 590 | 589 | -- Check the let-can-float invariant
|
| 591 | 590 | -- See Note [Core let-can-float invariant] in GHC.Core
|
| 592 | - ; checkL ( isJoinId binder
|
|
| 593 | - || mightBeLiftedType binder_ty
|
|
| 594 | - || (isNonRec rec_flag && exprOkForSpeculation rhs)
|
|
| 595 | - || isDataConWorkId binder || isDataConWrapId binder -- until #17521 is fixed
|
|
| 596 | - || exprIsTickedString rhs)
|
|
| 597 | - (badBndrTyMsg binder (text "unlifted"))
|
|
| 598 | - |
|
| 599 | - -- Check that if the binder is at the top level and has type Addr#,
|
|
| 600 | - -- that it is a string literal.
|
|
| 591 | + ; checkL ( isTopLevel top_lvl
|
|
| 592 | + || isJoinId binder
|
|
| 593 | + || mightBeLiftedType binder_ty
|
|
| 594 | + || (isNonRec rec_flag && exprOkForSpeculation rhs)) $
|
|
| 595 | + badBndrTyMsg binder (text "unlifted")
|
|
| 596 | + |
|
| 597 | + -- Check that if the binder is at the top level the binding
|
|
| 598 | + -- satisfies exprIsTopLevelBindable
|
|
| 601 | 599 | -- See Note [Core top-level string literals].
|
| 602 | - ; checkL (not (isTopLevel top_lvl && binder_ty `eqType` addrPrimTy)
|
|
| 603 | - || exprIsTickedString rhs)
|
|
| 604 | - (mkTopNonLitStrMsg binder)
|
|
| 600 | + ; checkL ( not (isTopLevel top_lvl)
|
|
| 601 | + || exprIsTopLevelBindable rhs binder_ty
|
|
| 602 | + || isDataConWorkId binder || isDataConWrapId binder -- until #17521 is fixed
|
|
| 603 | + ) $
|
|
| 604 | + mkTopNonLitStrMsg binder
|
|
| 605 | 605 | |
| 606 | 606 | ; flags <- getLintFlags
|
| 607 | 607 | |
| ... | ... | @@ -942,7 +942,7 @@ lintCoreExpr (Let (NonRec tv (Type ty)) body) |
| 942 | 942 | | isTyVar tv
|
| 943 | 943 | = -- See Note [Linting type lets]
|
| 944 | 944 | do { ty' <- lintTypeAndSubst ty
|
| 945 | - ; lintTyCoBndr tv $ \ tv' ->
|
|
| 945 | + ; lintTyVarBndr tv $ \ tv' ->
|
|
| 946 | 946 | do { addLoc (RhsOf tv) $ lintTyKind tv' ty'
|
| 947 | 947 | -- Now extend the substitution so we
|
| 948 | 948 | -- take advantage of it in the body
|
| ... | ... | @@ -1796,24 +1796,24 @@ lintBinders site (var:vars) linterF = lintBinder site var $ \var' -> |
| 1796 | 1796 | -- See Note [GHC Formalism]
|
| 1797 | 1797 | lintBinder :: HasDebugCallStack => BindingSite -> InVar -> (OutVar -> LintM a) -> LintM a
|
| 1798 | 1798 | lintBinder site var linterF
|
| 1799 | - | isTyCoVar var = lintTyCoBndr var linterF
|
|
| 1800 | - | otherwise = lintIdBndr NotTopLevel site var linterF
|
|
| 1799 | + | isTyVar var = lintTyVarBndr var linterF
|
|
| 1800 | + | otherwise = lintIdBndr NotTopLevel site var linterF
|
|
| 1801 | 1801 | |
| 1802 | -lintTyCoBndr :: HasDebugCallStack => TyCoVar -> (OutTyCoVar -> LintM a) -> LintM a
|
|
| 1803 | -lintTyCoBndr tcv thing_inside
|
|
| 1802 | +lintTyCoBndr :: HasDebugCallStack => InTyCoVar
|
|
| 1803 | + -> (OutTyCoVar -> LintM a) -> LintM a
|
|
| 1804 | +lintTyCoBndr var linterF
|
|
| 1805 | + | isTyVar var = lintTyVarBndr var linterF
|
|
| 1806 | + | otherwise = lintIdBndr NotTopLevel LambdaBind var linterF
|
|
| 1807 | + |
|
| 1808 | +lintTyVarBndr :: HasDebugCallStack => InTyVar -> (OutTyVar -> LintM a) -> LintM a
|
|
| 1809 | +lintTyVarBndr tcv thing_inside
|
|
| 1804 | 1810 | = do { tcv_type' <- lintTypeAndSubst (varType tcv)
|
| 1805 | 1811 | ; let tcv_kind' = typeKind tcv_type'
|
| 1806 | 1812 | |
| 1807 | - -- See (FORALL1) and (FORALL2) in GHC.Core.Type
|
|
| 1808 | - ; if (isTyVar tcv)
|
|
| 1809 | - then -- Check that in (forall (a:ki). blah) we have ki:Type
|
|
| 1810 | - lintL (isLiftedTypeKind tcv_kind') $
|
|
| 1813 | + -- See (FORALL1) in GHC.Core.Type
|
|
| 1814 | + ; lintL (isLiftedTypeKind tcv_kind') $
|
|
| 1811 | 1815 | hang (text "TyVar whose kind does not have kind Type:")
|
| 1812 | 1816 | 2 (ppr tcv <+> dcolon <+> ppr tcv_type' <+> dcolon <+> ppr tcv_kind')
|
| 1813 | - else -- Check that in (forall (cv::ty). blah),
|
|
| 1814 | - -- then ty looks like (t1 ~# t2)
|
|
| 1815 | - lintL (isCoVarType tcv_type') $
|
|
| 1816 | - text "CoVar with non-coercion type:" <+> pprTyVar tcv
|
|
| 1817 | 1817 | |
| 1818 | 1818 | ; addInScopeTyCoVar tcv tcv_type' thing_inside }
|
| 1819 | 1819 | |
| ... | ... | @@ -1858,19 +1858,21 @@ lintIdBndr top_lvl bind_site id thing_inside |
| 1858 | 1858 | checkL (not is_top_lvl && is_let_bind) $
|
| 1859 | 1859 | mkBadJoinBindMsg id
|
| 1860 | 1860 | |
| 1861 | - -- Check that the Id does not have type (t1 ~# t2) or (t1 ~R# t2);
|
|
| 1862 | - -- if so, it should be a CoVar, and checked by lintCoVarBndr
|
|
| 1863 | - ; lintL (not (isCoVarType id_ty))
|
|
| 1864 | - (text "Non-CoVar has coercion type" <+> ppr id <+> dcolon <+> ppr id_ty)
|
|
| 1861 | + -- Check that the Id is a CoVar <=> has type (t1 ~# t2) or (t1 ~R# t2);
|
|
| 1862 | + ; lintL (isCoVar id == isCoVarType id_ty) $
|
|
| 1863 | + hang (text "CoVar with non-coercion type or vice versa:")
|
|
| 1864 | + 2 (ppr id <+> dcolon <+> ppr id_ty)
|
|
| 1865 | 1865 | |
| 1866 | 1866 | -- Check that the lambda binder has no value or OtherCon unfolding.
|
| 1867 | 1867 | -- See #21496
|
| 1868 | 1868 | ; lintL (not (bind_site == LambdaBind && isEvaldUnfolding (idUnfolding id)))
|
| 1869 | - (text "Lambda binder with value or OtherCon unfolding.")
|
|
| 1869 | + (text "Lambda binder with value or OtherCon unfolding.")
|
|
| 1870 | 1870 | |
| 1871 | 1871 | ; out_ty <- addLoc (IdTy id) (lintValueType id_ty)
|
| 1872 | 1872 | |
| 1873 | - ; addInScopeId id out_ty thing_inside }
|
|
| 1873 | + ; if isCoVar id
|
|
| 1874 | + then addInScopeTyCoVar id out_ty thing_inside
|
|
| 1875 | + else addInScopeId id out_ty thing_inside }
|
|
| 1874 | 1876 | where
|
| 1875 | 1877 | id_ty = idType id
|
| 1876 | 1878 |
| ... | ... | @@ -934,6 +934,8 @@ addJoinFlts = appOL |
| 934 | 934 | mkRecFloats :: SimplFloats -> SimplFloats
|
| 935 | 935 | -- Flattens the floats into a single Rec group,
|
| 936 | 936 | -- They must either all be lifted LetFloats or all JoinFloats
|
| 937 | +--
|
|
| 938 | +-- ToDo: explain about CoVar floats
|
|
| 937 | 939 | mkRecFloats floats@(SimplFloats { sfLetFloats = LetFloats bs _ff
|
| 938 | 940 | , sfJoinFloats = jbs
|
| 939 | 941 | , sfInScope = in_scope })
|
| ... | ... | @@ -944,9 +946,24 @@ mkRecFloats floats@(SimplFloats { sfLetFloats = LetFloats bs _ff |
| 944 | 946 | where
|
| 945 | 947 | -- See Note [Bangs in the Simplifier]
|
| 946 | 948 | !floats' | isNilOL bs = emptyLetFloats
|
| 947 | - | otherwise = unitLetFloat (Rec (flattenBinds (fromOL bs)))
|
|
| 949 | + | otherwise = LetFloats (flatten_rec bs) FltLifted
|
|
| 948 | 950 | !jfloats' | isNilOL jbs = emptyJoinFloats
|
| 949 | - | otherwise = unitJoinFloat (Rec (flattenBinds (fromOL jbs)))
|
|
| 951 | + | otherwise = flatten_rec jbs
|
|
| 952 | + |
|
| 953 | + flatten_rec :: OrdList OutBind -> OrdList OutBind
|
|
| 954 | + -- Put CoVar bindings first (guaranteed non-recursive)
|
|
| 955 | + -- then one recursive value binding
|
|
| 956 | + flatten_rec bs = let !(covar_bs, prs) = foldrOL do_one (nilOL, []) bs
|
|
| 957 | + in covar_bs `snocOL` Rec prs
|
|
| 958 | + |
|
| 959 | + do_one :: OutBind -> (OrdList OutBind,[(OutId,OutExpr)])
|
|
| 960 | + -> (OrdList OutBind,[(OutId,OutExpr)])
|
|
| 961 | + do_one bind (cvbs, prs)
|
|
| 962 | + = case bind of
|
|
| 963 | + NonRec bndr rhs
|
|
| 964 | + | isCoVar bndr -> (bind `consOL` cvbs, prs)
|
|
| 965 | + | otherwise -> (cvbs, (bndr,rhs):prs)
|
|
| 966 | + Rec prs1 -> (cvbs, prs1 ++ prs)
|
|
| 950 | 967 | |
| 951 | 968 | wrapFloats :: SimplFloats -> OutExpr -> OutExpr
|
| 952 | 969 | -- Wrap the floats around the expression
|
| ... | ... | @@ -298,6 +298,7 @@ simplRecOrTopPair env bind_cxt old_bndr new_bndr rhs |
| 298 | 298 | (old_bndr,env) (new_bndr,env) (rhs,env)
|
| 299 | 299 | |
| 300 | 300 | simplTrace :: String -> SDoc -> SimplM a -> SimplM a
|
| 301 | +-- Spit out a trace with `-dverbose-core2core`
|
|
| 301 | 302 | simplTrace herald doc thing_inside = do
|
| 302 | 303 | logger <- getLogger
|
| 303 | 304 | if logHasDumpFlag logger Opt_D_verbose_core2core
|
| ... | ... | @@ -762,18 +763,15 @@ prepareRhs :: HasDebugCallStack |
| 762 | 763 | -- See Note [prepareRhs]
|
| 763 | 764 | prepareRhs env top_lvl occ rhs0
|
| 764 | 765 | | is_expandable = do { (flts,rhs) <- anfise rhs0
|
| 765 | - ; pprTrace "prepareRhs" (ppr rhs0 $$ text "new" <+> ppr rhs) $
|
|
| 766 | - return (flts, rhs) }
|
|
| 766 | + ; return (flts, rhs) }
|
|
| 767 | 767 | | otherwise = return (emptyLetFloats, rhs0)
|
| 768 | 768 | where
|
| 769 | - -- We can't use exprIsExpandable because the WHOLE POINT is that
|
|
| 770 | - -- we want to treat (K <big>) as expandable, because we are just
|
|
| 771 | - -- about "anfise" the <big> expression. exprIsExpandable would
|
|
| 772 | - -- just say no!
|
|
| 769 | + -- We can't use exprIsExpandable because the WHOLE POINT is that we want to
|
|
| 770 | + -- treat (K <big>) as expandable, because we are just about "anfise" the
|
|
| 771 | + -- <big> expression. exprIsExpandable would just say no!
|
|
| 773 | 772 | is_expandable = go rhs0 0
|
| 774 | 773 | where
|
| 775 | - go (Var fun) n_val_args = pprTrace "is_exp" (ppr fun <+> ppr n_val_args $$ ppr (isExpandableApp fun n_val_args)) $
|
|
| 776 | - isExpandableApp fun n_val_args
|
|
| 774 | + go (Var fun) n_val_args = isExpandableApp fun n_val_args
|
|
| 777 | 775 | go (App fun arg) n_val_args
|
| 778 | 776 | | isTypeArg arg = go fun n_val_args
|
| 779 | 777 | | otherwise = go fun (n_val_args + 1)
|
| ... | ... | @@ -2251,9 +2251,12 @@ new binding is abstracted. Several points worth noting |
| 2251 | 2251 | abstractFloats :: UnfoldingOpts -> TopLevelFlag -> [OutTyVar] -> SimplFloats
|
| 2252 | 2252 | -> OutExpr -> SimplM ([OutBind], OutExpr)
|
| 2253 | 2253 | abstractFloats uf_opts top_lvl main_tvs floats body
|
| 2254 | - = assert (notNull body_floats) $
|
|
| 2254 | + | assert (notNull body_floats) $
|
|
| 2255 | 2255 | assert (isNilOL (sfJoinFloats floats)) $
|
| 2256 | - do { let sccs = concatMap to_sccs body_floats
|
|
| 2256 | + any isCoVar (bindersOfBinds body_floats) -- ToDo: Explain this case
|
|
| 2257 | + = return ([], wrapFloats floats body)
|
|
| 2258 | + | otherwise
|
|
| 2259 | + = do { let sccs = concatMap to_sccs body_floats
|
|
| 2257 | 2260 | ; (subst, float_binds) <- mapAccumLM abstract empty_subst sccs
|
| 2258 | 2261 | ; return (float_binds, GHC.Core.Subst.substExpr subst body) }
|
| 2259 | 2262 | where
|
| 1 | +{-# LANGUAGE MagicHash #-}
|
|
| 1 | 2 | {-# OPTIONS_HADDOCK not-home #-}
|
| 2 | 3 | |
| 3 | 4 | {-
|
| ... | ... | @@ -63,7 +64,7 @@ module GHC.Core.TyCo.Rep ( |
| 63 | 64 | TyCoFolder(..), foldTyCo, noView,
|
| 64 | 65 | |
| 65 | 66 | -- * Sizes
|
| 66 | - typeSize, typesSize, coercionSize,
|
|
| 67 | + typeSize, typesSize, coercionSize, coercionIsSmall,
|
|
| 67 | 68 | |
| 68 | 69 | -- * Multiplicities
|
| 69 | 70 | Scaled(..), scaledMult, scaledThing, mapScaledType, Mult
|
| ... | ... | @@ -96,8 +97,8 @@ import GHC.Utils.Panic |
| 96 | 97 | import GHC.Utils.Binary
|
| 97 | 98 | |
| 98 | 99 | -- libraries
|
| 100 | +import GHC.Exts
|
|
| 99 | 101 | import qualified Data.Data as Data hiding ( TyCon )
|
| 100 | -import Data.Coerce
|
|
| 101 | 102 | import Data.IORef ( IORef ) -- for CoercionHole
|
| 102 | 103 | import Control.DeepSeq
|
| 103 | 104 | |
| ... | ... | @@ -2093,6 +2094,61 @@ mCoercionSize :: MCoercion -> Int |
| 2093 | 2094 | mCoercionSize MRefl = 0
|
| 2094 | 2095 | mCoercionSize (MCo co) = coercionSize co
|
| 2095 | 2096 | |
| 2097 | +coercionIsSmall :: Coercion -> Bool
|
|
| 2098 | +-- This function is called inside `exprIsTrivial` so it needs to be
|
|
| 2099 | +-- pretty efficient. It should return False quickly on a big coercion;
|
|
| 2100 | +-- it should /not/ traverse the big coercion!
|
|
| 2101 | +coercionIsSmall co
|
|
| 2102 | + = not (isTrue# ((coercion_is_small co 100#) <# 0#))
|
|
| 2103 | + |
|
| 2104 | +coercion_is_small :: Coercion -> Int# -> Int#
|
|
| 2105 | +coercion_is_small co n = go co n
|
|
| 2106 | + where
|
|
| 2107 | + go :: Coercion -> Int# -> Int#
|
|
| 2108 | + go _co n | isTrue# (n <# 0#) = n
|
|
| 2109 | + go (Refl ty) n = type_is_small ty n
|
|
| 2110 | + go (GRefl _ ty mco) n = type_is_small ty $ go_mco mco n
|
|
| 2111 | + go (TyConAppCo _ _ cos) n = go_cos cos $ dec n
|
|
| 2112 | + go (AxiomCo _ cos) n = go_cos cos $ dec n
|
|
| 2113 | + go (UnivCo _ _ _ _ cos) n = go_cos cos $ dec n
|
|
| 2114 | + go (AppCo co1 co2) n = go co1 $ go co2 $ dec n
|
|
| 2115 | + go (CoVarCo {}) n = dec n
|
|
| 2116 | + go (HoleCo {}) n = dec n
|
|
| 2117 | + go (SymCo co) n = go co $ dec n
|
|
| 2118 | + go (KindCo co) n = go co $ dec n
|
|
| 2119 | + go (SubCo co) n = go co $ dec n
|
|
| 2120 | + go (TransCo co1 co2) n = go co1 $ go co2 $ dec n
|
|
| 2121 | + go (SelCo _ co) n = go co $ dec n
|
|
| 2122 | + go (LRCo _ co) n = go co $ dec n
|
|
| 2123 | + go (InstCo co1 co2) n = go co1 $ go co2 $ dec n
|
|
| 2124 | + go (ForAllCo _ _ _ kco co) n = go co $ go_mco kco $ dec n
|
|
| 2125 | + go (FunCo _ _ _ mco aco rco) n = go mco $ go aco $ go rco $ dec n
|
|
| 2126 | + |
|
| 2127 | + go_cos [] n = n
|
|
| 2128 | + go_cos (co:cos) n = go_cos cos (go co n)
|
|
| 2129 | + |
|
| 2130 | + go_mco MRefl n = dec n
|
|
| 2131 | + go_mco (MCo co) n = go co n
|
|
| 2132 | + |
|
| 2133 | +type_is_small :: Type -> Int# -> Int#
|
|
| 2134 | +type_is_small ty n = go ty n
|
|
| 2135 | + where
|
|
| 2136 | + go _ty n | isTrue# (n <# 0#) = n
|
|
| 2137 | + go (TyVarTy {}) n = dec n
|
|
| 2138 | + go (LitTy {}) n = dec n
|
|
| 2139 | + go (AppTy t1 t2) n = go t1 $ go t2 $ dec n
|
|
| 2140 | + go (TyConApp _ tys) n = go_tys tys $ dec n
|
|
| 2141 | + go (ForAllTy _ ty) n = go ty $ dec n
|
|
| 2142 | + go (FunTy _ m a r) n = go m $ go a $ go r $ dec n
|
|
| 2143 | + go (CastTy ty co) n = go ty $ coercion_is_small co $ dec n
|
|
| 2144 | + go (CoercionTy co) n = coercion_is_small co n
|
|
| 2145 | + |
|
| 2146 | + go_tys [] n = n
|
|
| 2147 | + go_tys (ty:tys) n = go ty $ go_tys tys n
|
|
| 2148 | + |
|
| 2149 | +dec :: Int# -> Int#
|
|
| 2150 | +dec n = n -# 1#
|
|
| 2151 | + |
|
| 2096 | 2152 | {-
|
| 2097 | 2153 | ************************************************************************
|
| 2098 | 2154 | * *
|
| ... | ... | @@ -31,7 +31,7 @@ module GHC.Core.Utils ( |
| 31 | 31 | exprIsWorkFree, exprIsConLike,
|
| 32 | 32 | isCheapApp, isExpandableApp, isSaturatedConApp,
|
| 33 | 33 | exprIsTickedString, exprIsTickedString_maybe,
|
| 34 | - exprIsTopLevelBindable,
|
|
| 34 | + exprIsCoercion, exprIsTopLevelBindable,
|
|
| 35 | 35 | exprIsUnaryClassFun, isUnaryClassId,
|
| 36 | 36 | altsAreExhaustive, etaExpansionTick,
|
| 37 | 37 | |
| ... | ... | @@ -1331,8 +1331,7 @@ exprIsTrivial e = trivial_expr_fold |
| 1331 | 1331 | (const True) -- Literals
|
| 1332 | 1332 | (const True) -- Types
|
| 1333 | 1333 | coercionIsSmall -- Coercions
|
| 1334 | - (\ r co -> pprTrace "exprIsTrivial" (ppr (coercionIsSmall co) $$ ppr co) $
|
|
| 1335 | - r && coercionIsSmall co) -- Casts
|
|
| 1334 | + (\ r co -> r && coercionIsSmall co) -- Casts
|
|
| 1336 | 1335 | False e
|
| 1337 | 1336 | |
| 1338 | 1337 | {-
|
| ... | ... | @@ -599,8 +599,10 @@ getStgArgFromTrivialArg :: HasDebugCallStack => CoreArg -> StgArg |
| 599 | 599 | -- `case unsafeequalityProof of UnsafeRefl -> e` might intervene.
|
| 600 | 600 | -- Good thing we can just call `trivial_expr_fold` here.
|
| 601 | 601 | getStgArgFromTrivialArg e = trivial_expr_fold StgVarArg StgLitArg
|
| 602 | - panic panic panic panic e
|
|
| 602 | + panic panic get_cast panic e
|
|
| 603 | 603 | where
|
| 604 | + get_cast r _ = r
|
|
| 605 | + |
|
| 604 | 606 | panic :: forall a. a
|
| 605 | 607 | panic = pprPanic "getStgArgFromTrivialArg" (ppr e)
|
| 606 | 608 |
| ... | ... | @@ -2169,6 +2169,7 @@ data FloatInfoArgs |
| 2169 | 2169 | , fia_is_hnf :: Bool
|
| 2170 | 2170 | , fia_is_triv :: Bool
|
| 2171 | 2171 | , fia_is_string :: Bool
|
| 2172 | + , fia_is_coercion :: Bool
|
|
| 2172 | 2173 | , fia_is_dc_worker :: Bool
|
| 2173 | 2174 | , fia_ok_for_spec :: Bool
|
| 2174 | 2175 | }
|
| ... | ... | @@ -2181,14 +2182,17 @@ defFloatInfoArgs bndr rhs |
| 2181 | 2182 | , fia_is_hnf = exprIsHNF rhs
|
| 2182 | 2183 | , fia_is_triv = exprIsTrivial rhs
|
| 2183 | 2184 | , fia_is_string = exprIsTickedString rhs
|
| 2185 | + , fia_is_coercion = exprIsCoercion rhs
|
|
| 2184 | 2186 | , fia_is_dc_worker = isJust (isDataConId_maybe bndr) -- mkCaseFloat uses False
|
| 2185 | 2187 | , fia_ok_for_spec = False -- mkNonRecFloat uses exprOkForSpecEval
|
| 2186 | 2188 | }
|
| 2187 | 2189 | |
| 2188 | 2190 | decideFloatInfo :: FloatInfoArgs -> (BindInfo, FloatInfo)
|
| 2189 | 2191 | decideFloatInfo FIA{fia_levity=lev, fia_demand=dmd, fia_is_hnf=is_hnf,
|
| 2190 | - fia_is_triv=is_triv, fia_is_string=is_string,
|
|
| 2192 | + fia_is_triv=is_triv, fia_is_string=is_string, fia_is_coercion = is_coercion,
|
|
| 2191 | 2193 | fia_is_dc_worker=is_dc_worker, fia_ok_for_spec=ok_for_spec}
|
| 2194 | + -- NB: this function should line up with exprIsTopLevelBindable
|
|
| 2195 | + -- ToDo: explain a bit more
|
|
| 2192 | 2196 | | Lifted <- lev, is_hnf, not is_triv = (LetBound, TopLvlFloatable)
|
| 2193 | 2197 | -- is_lifted: We currently don't allow unlifted values at the
|
| 2194 | 2198 | -- top-level or inside letrecs
|
| ... | ... | @@ -2199,8 +2203,9 @@ decideFloatInfo FIA{fia_levity=lev, fia_demand=dmd, fia_is_hnf=is_hnf, |
| 2199 | 2203 | -- We need this special case for nullary unlifted DataCon
|
| 2200 | 2204 | -- workers/wrappers (top-level bindings) until #17521 is fixed
|
| 2201 | 2205 | | is_string = (CaseBound, TopLvlFloatable)
|
| 2206 | + | is_coercion = (LetBound, TopLvlFloatable)
|
|
| 2202 | 2207 | -- String literals are unboxed (so must be case-bound) and float to
|
| 2203 | - -- the top-level
|
|
| 2208 | + -- the top-level. Coercion are ok at top level too.
|
|
| 2204 | 2209 | | ok_for_spec = (CaseBound, case lev of Unlifted -> LazyContextFloatable
|
| 2205 | 2210 | Lifted -> TopLvlFloatable)
|
| 2206 | 2211 | -- See Note [Speculative evaluation]
|
| ... | ... | @@ -149,10 +149,12 @@ perPassFlags dflags pass |
| 149 | 149 | _ -> AllowAnywhere
|
| 150 | 150 | |
| 151 | 151 | -- See Note [Linting linearity]
|
| 152 | - check_linearity = gopt Opt_DoLinearCoreLinting dflags || (
|
|
| 153 | - case pass of
|
|
| 152 | + check_linearity = gopt Opt_DoLinearCoreLinting dflags
|
|
| 153 | + -- `-dlinear-core-lint`: check linearity in every pass
|
|
| 154 | + || -- Always check linearity just after desugaring
|
|
| 155 | + case pass of
|
|
| 154 | 156 | CoreDesugar -> True
|
| 155 | - _ -> False)
|
|
| 157 | + _ -> False
|
|
| 156 | 158 | |
| 157 | 159 | -- See Note [Checking for rubbish literals] in GHC.Core.Lint
|
| 158 | 160 | check_rubbish = case pass of
|
| ... | ... | @@ -58,6 +58,7 @@ import GHC.Core.Opt.OccurAnal ( occurAnalyseExpr ) |
| 58 | 58 | import GHC.Iface.Tidy.StaticPtrTable
|
| 59 | 59 | import GHC.Iface.Env
|
| 60 | 60 | |
| 61 | +import GHC.Utils.FV
|
|
| 61 | 62 | import GHC.Utils.Outputable
|
| 62 | 63 | import GHC.Utils.Misc( filterOut )
|
| 63 | 64 | import GHC.Utils.Panic
|
| ... | ... | @@ -89,7 +90,6 @@ import GHC.Unit.Module.Deps |
| 89 | 90 | |
| 90 | 91 | import GHC.Data.Maybe
|
| 91 | 92 | |
| 92 | -import Control.Monad
|
|
| 93 | 93 | import Data.Function
|
| 94 | 94 | import Data.List ( sortBy, mapAccumL )
|
| 95 | 95 | import qualified Data.Set as S
|
| ... | ... | @@ -826,71 +826,7 @@ See Note [Choosing external Ids] |
| 826 | 826 | -}
|
| 827 | 827 | |
| 828 | 828 | bndrFvsInOrder :: Bool -> Id -> [Id]
|
| 829 | -bndrFvsInOrder show_unfold id
|
|
| 830 | - = run (dffvLetBndr show_unfold id)
|
|
| 831 | - |
|
| 832 | -run :: DFFV () -> [Id]
|
|
| 833 | -run (DFFV m) = case m emptyVarSet (emptyVarSet, []) of
|
|
| 834 | - ((_,ids),_) -> ids
|
|
| 835 | - |
|
| 836 | -newtype DFFV a
|
|
| 837 | - = DFFV (VarSet -- Envt: non-top-level things that are in scope
|
|
| 838 | - -- we don't want to record these as free vars
|
|
| 839 | - -> (VarSet, [Var]) -- Input State: (set, list) of free vars so far
|
|
| 840 | - -> ((VarSet,[Var]),a)) -- Output state
|
|
| 841 | - deriving (Functor)
|
|
| 842 | - |
|
| 843 | -instance Applicative DFFV where
|
|
| 844 | - pure a = DFFV $ \_ st -> (st, a)
|
|
| 845 | - (<*>) = ap
|
|
| 846 | - |
|
| 847 | -instance Monad DFFV where
|
|
| 848 | - (DFFV m) >>= k = DFFV $ \env st ->
|
|
| 849 | - case m env st of
|
|
| 850 | - (st',a) -> case k a of
|
|
| 851 | - DFFV f -> f env st'
|
|
| 852 | - |
|
| 853 | -extendScope :: Var -> DFFV a -> DFFV a
|
|
| 854 | -extendScope v (DFFV f) = DFFV (\env st -> f (extendVarSet env v) st)
|
|
| 855 | - |
|
| 856 | -extendScopeList :: [Var] -> DFFV a -> DFFV a
|
|
| 857 | -extendScopeList vs (DFFV f) = DFFV (\env st -> f (extendVarSetList env vs) st)
|
|
| 858 | - |
|
| 859 | -insert :: Var -> DFFV ()
|
|
| 860 | -insert v = DFFV $ \ env (set, ids) ->
|
|
| 861 | - let keep_me = isLocalId v &&
|
|
| 862 | - not (v `elemVarSet` env) &&
|
|
| 863 | - not (v `elemVarSet` set)
|
|
| 864 | - in if keep_me
|
|
| 865 | - then ((extendVarSet set v, v:ids), ())
|
|
| 866 | - else ((set, ids), ())
|
|
| 867 | - |
|
| 868 | - |
|
| 869 | -dffvExpr :: CoreExpr -> DFFV ()
|
|
| 870 | -dffvExpr (Var v) = insert v
|
|
| 871 | -dffvExpr (App e1 e2) = dffvExpr e1 >> dffvExpr e2
|
|
| 872 | -dffvExpr (Lam v e) = extendScope v (dffvExpr e)
|
|
| 873 | -dffvExpr (Tick (Breakpoint _ _ ids) e) = mapM_ insert ids >> dffvExpr e
|
|
| 874 | -dffvExpr (Tick _other e) = dffvExpr e
|
|
| 875 | -dffvExpr (Cast e _) = dffvExpr e
|
|
| 876 | -dffvExpr (Let (NonRec x r) e) = dffvBind (x,r) >> extendScope x (dffvExpr e)
|
|
| 877 | -dffvExpr (Let (Rec prs) e) = extendScopeList (map fst prs) $
|
|
| 878 | - (mapM_ dffvBind prs >> dffvExpr e)
|
|
| 879 | -dffvExpr (Case e b _ as) = dffvExpr e >> extendScope b (mapM_ dffvAlt as)
|
|
| 880 | -dffvExpr _other = return ()
|
|
| 881 | - |
|
| 882 | -dffvAlt :: CoreAlt -> DFFV ()
|
|
| 883 | -dffvAlt (Alt _ xs r) = extendScopeList xs (dffvExpr r)
|
|
| 884 | - |
|
| 885 | -dffvBind :: (Id, CoreExpr) -> DFFV ()
|
|
| 886 | -dffvBind(x,r)
|
|
| 887 | - | not (isId x) = dffvExpr r
|
|
| 888 | - | otherwise = dffvLetBndr False x >> dffvExpr r
|
|
| 889 | - -- Pass False because we are doing the RHS right here
|
|
| 890 | - -- If you say True you'll get *exponential* behaviour!
|
|
| 891 | - |
|
| 892 | -dffvLetBndr :: Bool -> Id -> DFFV ()
|
|
| 893 | --- Gather the free vars of the RULES and unfolding of a binder
|
|
| 829 | +-- Gather the free vars of the type, RULES and unfolding of an Id bindeb
|
|
| 894 | 830 | -- We always get the free vars of a *stable* unfolding, but
|
| 895 | 831 | -- for a *vanilla* one (VanillaSrc), the flag controls what happens:
|
| 896 | 832 | -- True <=> get fvs of even a *vanilla* unfolding
|
| ... | ... | @@ -899,24 +835,21 @@ dffvLetBndr :: Bool -> Id -> DFFV () |
| 899 | 835 | -- we are taking the fvs of the RHS anyway
|
| 900 | 836 | -- For top-level bindings (call from addExternal, via bndrFvsInOrder)
|
| 901 | 837 | -- we say "True" if we are exposing that unfolding
|
| 902 | -dffvLetBndr vanilla_unfold id
|
|
| 903 | - = do { go_unf (realUnfoldingInfo idinfo)
|
|
| 904 | - ; mapM_ go_rule (ruleInfoRules (ruleInfo idinfo)) }
|
|
| 838 | +bndrFvsInOrder show_unfold id
|
|
| 839 | + = fvVarList $
|
|
| 840 | + filterFV isId $ -- Include CoVars, which can be top-level bound
|
|
| 841 | + tyCoFVsOfType (idType id) `unionFV`
|
|
| 842 | + unf_fvs `unionFV`
|
|
| 843 | + rules_fvs
|
|
| 905 | 844 | where
|
| 906 | 845 | idinfo = idInfo id
|
| 907 | 846 | |
| 908 | - go_unf (CoreUnfolding { uf_tmpl = rhs, uf_src = src })
|
|
| 909 | - | isStableSource src = dffvExpr rhs
|
|
| 910 | - | vanilla_unfold = dffvExpr rhs
|
|
| 911 | - | otherwise = return ()
|
|
| 912 | - |
|
| 913 | - go_unf (DFunUnfolding { df_bndrs = bndrs, df_args = args })
|
|
| 914 | - = extendScopeList bndrs $ mapM_ dffvExpr args
|
|
| 915 | - go_unf _ = return ()
|
|
| 847 | + unf_fvs :: FV
|
|
| 848 | + unf_fvs | show_unfold = unfoldingFVs (realUnfoldingInfo idinfo)
|
|
| 849 | + | otherwise = emptyFV
|
|
| 916 | 850 | |
| 917 | - go_rule (BuiltinRule {}) = return ()
|
|
| 918 | - go_rule (Rule { ru_bndrs = bndrs, ru_rhs = rhs })
|
|
| 919 | - = extendScopeList bndrs (dffvExpr rhs)
|
|
| 851 | + rules_fvs :: FV
|
|
| 852 | + rules_fvs = rulesFVs RhsOnly (ruleInfoRules (ruleInfo idinfo))
|
|
| 920 | 853 | |
| 921 | 854 | {-
|
| 922 | 855 | ************************************************************************
|