summaryrefslogtreecommitdiff
path: root/compiler/GHC/Core/SimpleOpt.hs
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2021-02-11 09:47:42 +0000
committerSimon Peyton Jones <simonpj@microsoft.com>2021-02-12 17:59:40 +0000
commitcedcdd27742acfee17196cef155bac17ca7b6a83 (patch)
tree9ea409c268da18dab2184350eeb24a8754cff063 /compiler/GHC/Core/SimpleOpt.hs
parent40983d2331fe34c0af6925db7588d5ac6a19ae36 (diff)
downloadhaskell-wip/T19347.tar.gz
Fix over-eager inlining in SimpleOptwip/T19347
In GHC.Core.SimpleOpt, I found that its inlining could duplicate an arbitary redex inside a lambda! Consider (\xyz. x+y). The occurrence-analysis treats the lamdda as a group, and says that both x and y occur once, even though the occur under the lambda-z. See Note [Occurrence analysis for lambda binders] in OccurAnal. When the lambda is under-applied in a call, the Simplifier is careful to zap the occ-info on x,y, because they appear under the \z. (See the call to zapLamBndrs in simplExprF1.) But SimpleOpt missed this test, resulting in #19347. So this patch * commons up the binder-zapping in GHC.Core.Utils.zapLamBndrs. * Calls this new function from GHC.Core.Opt.Simplify * Adds a call to zapLamBndrs to GHC.Core.SimpleOpt.simple_app This change makes test T12990 regress somewhat, but it was always very delicate, so I'm going to put up with that. In this voyage I also discovered a small, rather unrelated infelicity in the Simplifier: * In GHC.Core.Opt.Simplify.simplNonRecX we should apply isStrictId to the OutId not the InId. See Note [Dark corner with levity polymorphism] It may never "bite", because SimpleOpt should have inlined all the levity-polymorphic compulsory inlnings already, but somehow it bit me at one point and it's generally a more solid thing to do. Fixing the main bug increases runtime allocation in test perf/should_run/T12990, for (acceptable) reasons explained in a comement on Metric Increase: T12990
Diffstat (limited to 'compiler/GHC/Core/SimpleOpt.hs')
-rw-r--r--compiler/GHC/Core/SimpleOpt.hs17
1 files changed, 14 insertions, 3 deletions
diff --git a/compiler/GHC/Core/SimpleOpt.hs b/compiler/GHC/Core/SimpleOpt.hs
index bf9602bdaf..81bbc9247e 100644
--- a/compiler/GHC/Core/SimpleOpt.hs
+++ b/compiler/GHC/Core/SimpleOpt.hs
@@ -333,10 +333,21 @@ simple_app env (Var v) as
simple_app env (App e1 e2) as
= simple_app env e1 ((env, e2) : as)
-simple_app env (Lam b e) (a:as)
- = wrapLet mb_pr (simple_app env' e as)
+simple_app env e@(Lam {}) as@(_:_)
+ | (bndrs, body) <- collectBinders e
+ , let zapped_bndrs = zapLamBndrs (length as) bndrs
+ -- Be careful to zap the lambda binders if necessary
+ -- c.f. the Lam caes of simplExprF1 in GHC.Core.Opt.Simplify
+ -- Lacking this zap caused #19347, when we had a redex
+ -- (\ a b. K a b) e1 e2
+ -- where (as it happens) the eta-expanded K is produced by
+ -- Note [Linear fields generalization] in GHC.Tc.Gen.Head
+ = do_beta env zapped_bndrs body as
where
- (env', mb_pr) = simple_bind_pair env b Nothing a NotTopLevel
+ do_beta env (b:bs) body (a:as)
+ | (env', mb_pr) <- simple_bind_pair env b Nothing a NotTopLevel
+ = wrapLet mb_pr $ do_beta env' bs body as
+ do_beta env bs body as = simple_app env (mkLams bs body) as
simple_app env (Tick t e) as
-- Okay to do "(Tick t e) x ==> Tick t (e x)"?