[Git][ghc/ghc][wip/T23923-mikolaj-take-2] Fix the horrid perf bug in coVarsOfType

Simon Peyton Jones (@simonpj) gitlab at gitlab.haskell.org
Tue Mar 26 11:29:24 UTC 2024



Simon Peyton Jones pushed to branch wip/T23923-mikolaj-take-2 at Glasgow Haskell Compiler / GHC


Commits:
10f2d937 by Simon Peyton Jones at 2024-03-26T11:28:25+00:00
Fix the horrid perf bug in coVarsOfType

See #24591

- - - - -


1 changed file:

- compiler/GHC/Core/TyCo/Rep.hs


Changes:

=====================================
compiler/GHC/Core/TyCo/Rep.hs
=====================================
@@ -1826,6 +1826,38 @@ Here deep_fvs and deep_tcf are mutually recursive, unlike fvs and tcf.
 But, amazingly, we get good code here too. GHC is careful not to mark
 TyCoFolder data constructor for deep_tcf as a loop breaker, so the
 record selections still cancel.  And eta expansion still happens too.
+
+Note [Use explicit recursion in foldTyCo]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In foldTyCo you'll see things like:
+    go_tys _   []     = mempty
+    go_tys env (t:ts) = go_ty env t `mappend` go_tys env ts
+where we use /explicit recursion/.  You might wonder about using foldr instead:
+    go_tys env = foldl (\t acc -> go_ty env t `mappend` acc) mempty
+Or maybe or foldl', or foldr.
+
+But don't do that for two reasons (see #24591)
+
+* We sometimes instantiate `a` to (Endo VarSet). Remembering
+     newtype Endo a = Endo (a->a)
+  after inlining `foldTyCo` bodily, the explicit recursion looks like
+    go_tys _   []     = \acc -> acc
+    go_tys env (t:ts) = \acc -> go_ty env t (go_tys env ts acc)
+  The strictness analyser has no problem spotting that this function is
+  strict in `acc`, provided `go_ty` is.
+
+  But in the foldl form that is /much/ less obvious, and the strictness
+  analyser fails utterly.  Result: lots and lots of thunks get built.  In
+  !12037, Mikolaj found that GHC allocated allocated /six times/ as much heap
+  on test perf/compiler/T9198 as a result of this single problem!
+
+* Second, while I think that using `foldr` would be fine (simple experiments in
+  #24591 suggest as much), it builds a local loop (with env free) and I'm not 100%
+  confident it'll be lambda lifted in the end. It seems more direct just to write
+  the code we want.
+
+  On the other hand in `go_cvs` we might hope that the `foldr` will fuse with the
+  `dVarSetElems` so I have used `foldr`.
 -}
 
 data TyCoFolder env a
@@ -1864,12 +1896,11 @@ foldTyCo (TyCoFolder { tcf_view       = view
       = let !env' = tycobinder env tv vis  -- Avoid building a thunk here
         in go_ty env (varType tv) `mappend` go_ty env' inner
 
-    -- Explicit recursion because using foldr builds a local
-    -- loop (with env free) and I'm not confident it'll be
-    -- lambda lifted in the end
+    -- See Note [Use explicit recursion in foldTyCo]
     go_tys _   []     = mempty
     go_tys env (t:ts) = go_ty env t `mappend` go_tys env ts
 
+    -- See Note [Use explicit recursion in foldTyCo]
     go_cos _   []     = mempty
     go_cos env (c:cs) = go_co env c `mappend` go_cos env cs
 
@@ -1905,7 +1936,9 @@ foldTyCo (TyCoFolder { tcf_view       = view
     go_prov env (ProofIrrelProv co) = go_co env co
     go_prov _   (PluginProv _ cvs)  = go_cvs env cvs
 
-    go_cvs env cvs = foldl' (\ !acc cv -> acc `mappend` covar env cv) mempty (dVarSetElems cvs)
+    -- See Note [Use explicit recursion in foldTyCo]
+    go_cvs env cvs = foldr (add_one env) mempty (dVarSetElems cvs)
+    add_one env cv acc = covar env cv `mappend` acc
 
 -- | A view function that looks through nothing.
 noView :: Type -> Maybe Type



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/10f2d937bcb3f44a5fd5d258a8d46270ace6b29c

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/10f2d937bcb3f44a5fd5d258a8d46270ace6b29c
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20240326/3dcccced/attachment-0001.html>


More information about the ghc-commits mailing list