summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Klebinger <klebinger.andreas@gmx.at>2021-05-10 16:00:24 +0200
committerMarge Bot <ben+marge-bot@smart-cactus.org>2021-05-12 14:49:23 -0400
commit55223780a286e10b128acdb89d64d9e59a5becf1 (patch)
tree45400700e6e91bfce74c236b5b8be5898b8e2189
parentf0b73ddd8bdb663ab70043e9424a99d2454cdf77 (diff)
downloadhaskell-55223780a286e10b128acdb89d64d9e59a5becf1.tar.gz
W/W: Always zap useless idInfos.
tryWW used to always returns an Id with a zapped: * DmdEnv * Used Once info except in the case where the ID was guaranteed to be inlined. We now also zap the info in that case. Fixes #19818.
-rw-r--r--compiler/GHC/Core/Opt/WorkWrap.hs30
1 files changed, 28 insertions, 2 deletions
diff --git a/compiler/GHC/Core/Opt/WorkWrap.hs b/compiler/GHC/Core/Opt/WorkWrap.hs
index 34198bad88..65f07703b2 100644
--- a/compiler/GHC/Core/Opt/WorkWrap.hs
+++ b/compiler/GHC/Core/Opt/WorkWrap.hs
@@ -495,12 +495,12 @@ tryWW dflags fam_envs is_rec fn_id rhs
-- See Note [Worker/wrapper for NOINLINE functions]
| Just stable_unf <- certainlyWillInline uf_opts fn_info
- = return [ (fn_id `setIdUnfolding` stable_unf, rhs) ]
+ = return [ (new_fn_id `setIdUnfolding` stable_unf, rhs) ]
-- See Note [Don't w/w INLINE things]
-- See Note [Don't w/w inline small non-loop-breaker things]
| isRecordSelector fn_id -- See Note [No worker/wrapper for record selectors]
- = return [ (fn_id, rhs ) ]
+ = return [ (new_fn_id, rhs ) ]
| is_fun && is_eta_exp
= splitFun dflags fam_envs new_fn_id fn_info wrap_dmds div cpr rhs
@@ -572,6 +572,32 @@ want to _keep_ the info for the code generator).
We do not do it in the demand analyser for the same reasons outlined in
Note [Zapping DmdEnv after Demand Analyzer] above.
+For example, consider
+ let y = factorial v in
+ let x = y in
+ x + x
+
+Demand analysis will conclude, correctly, that `y` is demanded once. But if we inline `x` we get
+ let y = factorial v in
+ y + y
+
+Similarly for
+ f y = let x = y in x+x
+where we will put a used-once demand on y, and hence also in f's demand signature.
+
+And recursively
+ f y = case y of (p,q) -> let p2 = p in p2+p2
+ Here we'll get a used-once demand on p; but that is not robust to inlining p2.
+
+Conclusion: "demanded once" info is fragile.
+* We want it after the final immediately-before-code-gen demand analysis, so we can identify single-entry thunks.
+* But we don't want it otherwise because it is not robust.
+
+Conclusion: kill it during worker/wrapper, using `zapUsedOnceInfo`. Both the *demand signature* of
+the binder, and the *demand-info* of the binder. Moreover, do so recursively.
+
+(NB THE pre-code-gen demand analysis is not followed by worker/wrapper.)
+
Note [Don't eta expand in w/w]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A binding where the manifestArity of the RHS is less than idArity of the binder