[Git][ghc/ghc][wip/T23159] Make exprIsConApp_maybe a bit cleverer

Simon Peyton Jones (@simonpj) gitlab at gitlab.haskell.org
Mon Mar 27 21:08:39 UTC 2023



Simon Peyton Jones pushed to branch wip/T23159 at Glasgow Haskell Compiler / GHC


Commits:
c1f755c4 by Simon Peyton Jones at 2023-03-27T22:09:41+01:00
Make exprIsConApp_maybe a bit cleverer

Addresses #23159.

See Note Note [Exploit occ-info in exprIsConApp_maybe]
in GHC.Core.SimpleOpt.

Compile times go down very slightly, but always go down,
never up.  Good!

Metrics: compile_time/bytes allocated
------------------------------------------------
 CoOpt_Singletons(normal)   -1.8%
           T15703(normal)   -1.2% GOOD

                geo. mean   -0.1%
                minimum     -1.8%
                maximum     +0.0%

Metric Decrease:
    CoOpt_Singletons
    T15703

- - - - -


1 changed file:

- compiler/GHC/Core/SimpleOpt.hs


Changes:

=====================================
compiler/GHC/Core/SimpleOpt.hs
=====================================
@@ -497,13 +497,20 @@ simple_bind_pair env@(SOE { soe_inl = inl_env, soe_subst = subst })
        | otherwise                = True
 
         -- Unconditionally safe to inline
-    safe_to_inline :: OccInfo -> Bool
-    safe_to_inline IAmALoopBreaker{}                  = False
-    safe_to_inline IAmDead                            = True
-    safe_to_inline OneOcc{ occ_in_lam = NotInsideLam
-                         , occ_n_br = 1 }             = True
-    safe_to_inline OneOcc{}                           = False
-    safe_to_inline ManyOccs{}                         = False
+safe_to_inline :: OccInfo -> Bool
+safe_to_inline IAmALoopBreaker{}                  = False
+safe_to_inline IAmDead                            = True
+safe_to_inline OneOcc{ occ_in_lam = NotInsideLam
+                     , occ_n_br = 1 }             = True
+safe_to_inline OneOcc{}                           = False
+safe_to_inline ManyOccs{}                         = False
+
+do_beta_by_substitution :: Id -> CoreExpr -> Bool
+-- True <=> you can inline (bndr = rhs) by substitution
+-- See Note [Exploit occ-info in exprIsConApp_maybe]
+do_beta_by_substitution bndr rhs
+  = exprIsTrivial rhs                   -- Can duplicate
+    || safe_to_inline (idOccInfo bndr)  -- Occurs at most once
 
 -------------------
 simple_out_bind :: TopLevelFlag
@@ -1078,6 +1085,45 @@ will happen the next time either.
 
 See test T16254, which checks the behavior of newtypes.
 
+Note [Exploit occ-info in exprIsConApp_maybe]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Suppose (#23159) we have a simple data constructor wrapper like this (this one
+might have come from a data family instance):
+   $WK x y = K x y |> co
+Now suppose the simplifier sees
+   case ($WK e1 e2) |> co2 of
+      K p q ->  case q of ...
+
+`exprIsConApp_maybe` expands the wrapper on the fly
+(see Note [beta-reduction in exprIsConApp_maybe]). It effectively expands
+that ($WK e1 e2) to
+   let x = e1; y = e2 in K x y |> co
+
+So the Simplifier might end up producing this:
+   let x = e1; y = e2
+   in case x of ...
+
+But suppose `q` was used just once in the body of the `K p q` alternative; we
+don't want to wait a whole Simplifier iteration to inline that `x`.  (e1 might
+be another constructor for example.)  This would happen if `exprIsConApp_maybe`
+we created a let for every (non-trivial) argument.  So let's not do that when
+the binder is used just once!
+
+Instead, take advantage of the occurrence-info on `x` and `y` in the unfolding
+of `$WK`.  Since in `$WK` both `x` and `y` occur once, we want to effectively
+expand `($WK e1 e2)` to `(K e1 e2 |> co)`.  Hence in
+`do_beta_by_substitution` we say "yes" if
+
+  (a) the RHS is trivial (so we can duplicate it);
+      see call to `exprIsTrivial`
+or
+  (b) the binder occurs at most once (so there is no worry about duplication);
+      see call to `safe_to_inline`.
+
+To see this in action, look at testsuite/tests/perf/compiler/T15703.  The
+initial Simlifier run takes 5 iterations without (b), but only 3 when we add
+(b).
+
 Note [Don't float join points]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 exprIsConApp_maybe should succeed on
@@ -1228,7 +1274,7 @@ exprIsConApp_maybe ise@(ISE in_scope id_unf) expr
        = go subst floats fun (CC (subst_expr subst arg : args) co)
 
     go subst floats (Lam bndr body) (CC (arg:args) co)
-       | exprIsTrivial arg          -- Don't duplicate stuff!
+       | do_beta_by_substitution bndr arg
        = go (extend subst bndr arg) floats body (CC args co)
        | otherwise
        = let (subst', bndr') = subst_bndr subst bndr



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

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/c1f755c4bebec04b8942f36c1f2a2a1772dbe28b
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/20230327/5ff4d7fe/attachment-0001.html>


More information about the ghc-commits mailing list