summaryrefslogtreecommitdiff
path: root/compiler/GHC/Core/Utils.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/Utils.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/Utils.hs')
-rw-r--r--compiler/GHC/Core/Utils.hs33
1 files changed, 29 insertions, 4 deletions
diff --git a/compiler/GHC/Core/Utils.hs b/compiler/GHC/Core/Utils.hs
index a67955ad2b..fcffaa553a 100644
--- a/compiler/GHC/Core/Utils.hs
+++ b/compiler/GHC/Core/Utils.hs
@@ -40,8 +40,8 @@ module GHC.Core.Utils (
cheapEqExpr, cheapEqExpr', eqExpr,
diffExpr, diffBinds,
- -- * Eta reduction
- tryEtaReduce,
+ -- * Lambdas and eta reduction
+ tryEtaReduce, zapLamBndrs,
-- * Manipulating data constructors and types
exprToType, exprToCoercion_maybe,
@@ -99,7 +99,7 @@ import GHC.Utils.Panic
import GHC.Data.FastString
import GHC.Data.Maybe
import GHC.Data.List.SetOps( minusList )
-import GHC.Types.Basic ( Arity )
+import GHC.Types.Basic ( Arity, FullArgCount )
import GHC.Utils.Misc
import GHC.Data.Pair
import Data.ByteString ( ByteString )
@@ -2521,9 +2521,34 @@ to the rule that
we can eta-reduce \x. f x ===> f
This turned up in #7542.
+-}
+{- *********************************************************************
+* *
+ Zapping lambda binders
+* *
+********************************************************************* -}
-************************************************************************
+zapLamBndrs :: FullArgCount -> [Var] -> [Var]
+-- If (\xyz. t) appears under-applied to only two arguments,
+-- we must zap the occ-info on x,y, because they appear under the \x
+-- See Note [Occurrence analysis for lambda binders] in GHc.Core.Opt.OccurAnal
+--
+-- NB: both `arg_count` and `bndrs` include both type and value args/bndrs
+zapLamBndrs arg_count bndrs
+ | no_need_to_zap = bndrs
+ | otherwise = zap_em arg_count bndrs
+ where
+ no_need_to_zap = all isOneShotBndr (drop arg_count bndrs)
+
+ zap_em :: FullArgCount -> [Var] -> [Var]
+ zap_em 0 bs = bs
+ zap_em _ [] = []
+ zap_em n (b:bs) | isTyVar b = b : zap_em (n-1) bs
+ | otherwise = zapLamIdInfo b : zap_em (n-1) bs
+
+
+{- *********************************************************************
* *
\subsection{Determining non-updatable right-hand-sides}
* *