[Git][ghc/ghc][wip/spj-try-opt-coercion] 2 commits: Wibble
Simon Peyton Jones pushed to branch wip/spj-try-opt-coercion at Glasgow Haskell Compiler / GHC Commits: 82a09545 by Simon Peyton Jones at 2025-12-31T16:20:30+00:00 Wibble - - - - - 8d188235 by Simon Peyton Jones at 2025-12-31T16:20:42+00:00 Try harder to keep the substitution empty See Note [Keeping the substitution empty] - - - - - 3 changed files: - compiler/GHC/Core/Opt/Simplify/Iteration.hs - compiler/GHC/Core/Subst.hs - compiler/GHC/Core/TyCo/Subst.hs Changes: ===================================== compiler/GHC/Core/Opt/Simplify/Iteration.hs ===================================== @@ -1657,7 +1657,6 @@ simplCast env body co0 cont0 addCoerce co1 (CastIt { sc_co = co2, sc_cont = cont }) -- See Note [Optimising reflexivity] = addCoerce (mkTransCo co1 co2) cont -- False: (mkTransCo co1 co2) is not fully optimised - -- See Note [Avoid re-simplifying coercions] addCoerce co (ApplyToTy { sc_arg_ty = arg_ty, sc_cont = tail }) | Just (arg_ty', m_co') <- pushCoTyArg co arg_ty ===================================== compiler/GHC/Core/Subst.hs ===================================== @@ -380,8 +380,10 @@ substIdBndr _doc rec_subst subst@(Subst in_scope env tvs cvs) old_id old_ty = idType old_id old_w = idMult old_id - no_type_change = (isEmptyVarEnv tvs && isEmptyVarEnv cvs) || + no_type_change = isEmptyTCvSubst subst || (noFreeVarsOfType old_ty && noFreeVarsOfType old_w) + -- isEmptyTCvSubst: see Note [Keeping the substitution empty] + -- in GHC.Core.TyCo.Subst -- new_id has the right IdInfo -- The lazy-set is because we're in a loop here, with ===================================== compiler/GHC/Core/TyCo/Subst.hs ===================================== @@ -960,7 +960,8 @@ substTyVarBndrUsing subst_fn subst@(Subst in_scope idenv tenv cenv) old_var -- Assertion check that we are not capturing something in the substitution old_ki = tyVarKind old_var - no_kind_change = noFreeVarsOfType old_ki -- verify that kind is closed + no_kind_change = isEmptyTCvSubst subst || noFreeVarsOfType old_ki + -- isEmptyTCvSubst: see Note [Keeping the substitution empty] no_change = no_kind_change && (new_var == old_var) -- no_change means that the new_var is identical in -- all respects to the old_var (same unique, same kind) @@ -988,7 +989,8 @@ substCoVarBndrUsing subst_fn subst@(Subst in_scope idenv tenv cenv) old_var (Subst (in_scope `extendInScopeSet` new_var) idenv tenv new_cenv, new_var) where new_co = mkCoVarCo new_var - no_kind_change = noFreeVarsOfTypes [t1, t2] + no_kind_change = isEmptyTCvSubst subst || noFreeVarsOfTypes [t1, t2] + -- isEmptyTCvSubst: see Note [Keeping the substitution empty] no_change = new_var == old_var && no_kind_change new_cenv | no_change = delVarEnv cenv old_var @@ -1034,3 +1036,22 @@ substTyCoBndr subst (Anon ty af) = (subst, Anon (substScaledTy subst ty substTyCoBndr subst (Named (Bndr tv vis)) = (subst', Named (Bndr tv' vis)) where (subst', tv') = substVarBndr subst tv + +{- Note [Keeping the substitution empty] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +A very common situation is where we run over a term doing no cloning, +no substitution, nothing. In that case the TCvSubst till be empty, and +it is /very/ valuable to /keep/ it empty: + +* It's wasted effort to build up an identity substitution mapping + [x:->x, y:->y]. + +* When we come to a binder, if the incoming substitution is empty, + we can avoid substituting its type; and that in turn may mean that + the binder itself does not change and we don't need to extend the + substitution. + +* In the Simplifier we substitute over both types and coercions. + If the substitution is empty, this is a no-op -- but only if it + is empty! +-} View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/86d4cd861572e6a901098a7fc6ea77d... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/86d4cd861572e6a901098a7fc6ea77d... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
Simon Peyton Jones (@simonpj)