diff --git a/compiler/GHC/CoreToStg/Prep.hs b/compiler/GHC/CoreToStg/Prep.hs index 0b8da3fea6276c5eb269d03af0ba707e46f9b9dd..7add9fd9bfb4d08276f767e44a99c6250ba3ee77 100644 --- a/compiler/GHC/CoreToStg/Prep.hs +++ b/compiler/GHC/CoreToStg/Prep.hs @@ -2354,45 +2354,49 @@ we are optimizing away 'lazy' (see Note [lazyId magic], and also 'cpeRhsE'.) Then, we could have started with: let x :: () - x = lazy @ () y + x = lazy @() y -which is a perfectly fine, non-trivial thunk, but then CorePrep will -drop 'lazy', giving us 'x = y' which is trivial and impermissible. -The solution is CorePrep to have a miniature inlining pass which deals -with cases like this. We can then drop the let-binding altogether. +which is a perfectly fine, non-trivial thunk, but then CorePrep will drop +'lazy', giving us 'x = y' which is trivial and impermissible. The solution is +CorePrep to have a miniature inlining pass which deals with cases like this. +We can then drop the let-binding altogether. -Why does the removal of 'lazy' have to occur in CorePrep? -The gory details are in Note [lazyId magic] in GHC.Types.Id.Make, but the -main reason is that lazy must appear in unfoldings (optimizer -output) and it must prevent call-by-value for catch# (which -is implemented by CorePrep.) +Why does the removal of 'lazy' have to occur in CorePrep? The gory details +are in Note [lazyId magic] in GHC.Types.Id.Make, but the main reason is that +lazy must appear in unfoldings (optimizer output) and it must prevent +call-by-value for catch# (which is implemented by CorePrep.) -An alternate strategy for solving this problem is to have the -inliner treat 'lazy e' as a trivial expression if 'e' is trivial. -We decided not to adopt this solution to keep the definition -of 'exprIsTrivial' simple. +An alternate strategy for solving this problem is to have the inliner treat +'lazy e' as a trivial expression if 'e' is trivial. We decided not to adopt +this solution to keep the definition of 'exprIsTrivial' simple. There is ONE caveat however: for top-level bindings we have to preserve the binding so that we float the (hacky) non-recursive binding for data constructors; see Note [Data constructor workers]. -Note [CorePrep inlines trivial CoreExpr not Id] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -TODO -Why does cpe_env need to be an IdEnv CoreExpr, as opposed to an -IdEnv Id? Naively, we might conjecture that trivial updatable thunks -as per Note [Inlining in CorePrep] always have the form -'lazy @ SomeType gbl_id'. But this is not true: the following is -perfectly reasonable Core: +Note [CorePrepEnv: cpe_subst] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +CorePrepEnv carries a substitution `Subst` in the `cpe_subst1 field, +for these reasons: - let x :: () - x = lazy @ (forall a. a) y @ Bool +1. To support cloning of local Ids so that they are + all unique (see Note [Cloning in CorePrep]) + +2. To support beta-reduction of runRW, see Note [runRW magic] and + Note [runRW arg]. + +3. To let us inline trivial RHSs of non top-level let-bindings, + see Note [lazyId magic], Note [Inlining in CorePrep] (#12076) -When we inline 'x' after eliminating 'lazy', we need to replace -occurrences of 'x' with 'y @ bool', not just 'y'. Situations like -this can easily arise with higher-rank types; thus, cpe_env must -map to CoreExprs, not Ids. + Note that, if (y::forall a. a->a), we could get + x = lazy @(forall a.a) y @Bool + so after eliminating `lazy`, we need to replace occurrences of `x` with + `y @Bool`, not just `y`. Situations like this can easily arise with + higher-rank types; thus, `cpe_subst` must map to CoreExprs, not Ids, which + oc course it does +4. The TyCoVar part of the substitution is used only for + Note [Cloning CoVars and TyVars] -} data CorePrepConfig = CorePrepConfig @@ -2418,23 +2422,9 @@ data CorePrepEnv -- the case where a function we think should bottom -- unexpectedly returns. - , cpe_subst :: Subst - -- ^ The IdEnv part of the substitution is used for three operations: - -- - -- 1. To support cloning of local Ids so that they are - -- all unique (see Note [Cloning in CorePrep]) - -- - -- 2. To support beta-reduction of runRW, see - -- Note [runRW magic] and Note [runRW arg]. - -- - -- 3. To let us inline trivial RHSs of non top-level let-bindings, - -- see Note [lazyId magic], Note [Inlining in CorePrep] - -- and Note [CorePrep inlines trivial CoreExpr not Id] (#12076) - -- - -- The TyCoVar part of the substitution is used only for - -- Note [Cloning CoVars and TyVars] + , cpe_subst :: Subst -- ^ See Note [CorePrepEnv: cpe_subst] - , cpe_rec_ids :: UnVarSet -- Faster OutIdSet; See Note [Speculative evaluation] + , cpe_rec_ids :: UnVarSet -- Faster OutIdSet; See Note [Speculative evaluation] } mkInitialCorePrepEnv :: CorePrepConfig -> CorePrepEnv