summaryrefslogtreecommitdiff
path: root/compiler/GHC/Core/Utils.hs
diff options
context:
space:
mode:
authorSebastian Graf <sebastian.graf@kit.edu>2022-02-17 18:11:24 +0100
committerSebastian Graf <sebastian.graf@kit.edu>2022-05-03 20:11:51 +0200
commit15ffe2b02e927d9cc2cc0f97dddee38decea5f56 (patch)
tree904bd87b75e510d58b3dfdf437f5b469b6f6ccc9 /compiler/GHC/Core/Utils.hs
parent4a7809284354025d07221f0aeca10a7992d23677 (diff)
downloadhaskell-wip/T21081.tar.gz
Assume at least one evaluation for nested SubDemands (#21081, #21133)wip/T21081
See the new `Note [SubDemand denotes at least one evaluation]`. A demand `n :* sd` on a let binder `x=e` now means > "`x` was evaluated `n` times and in any program trace it is evaluated, `e` is > evaluated deeply in sub-demand `sd`." The "any time it is evaluated" premise is what this patch adds. As a result, we get better nested strictness. For example (T21081) ```hs f :: (Bool, Bool) -> (Bool, Bool) f pr = (case pr of (a,b) -> a /= b, True) -- before: <MP(L,L)> -- after: <MP(SL,SL)> g :: Int -> (Bool, Bool) g x = let y = let z = odd x in (z,z) in f y ``` The change in demand signature "before" to "after" allows us to case-bind `z` here. Similarly good things happen for the `sd` in call sub-demands `Cn(sd)`, which allows for more eta-reduction (which is only sound with `-fno-pedantic-bottoms`, albeit). We also fix #21085, a surprising inconsistency with `Poly` to `Call` sub-demand expansion. In an attempt to fix a regression caused by less inlining due to eta-reduction in T15426, I eta-expanded the definition of `elemIndex` and `elemIndices`, thus fixing #21345 on the go. The main point of this patch is that it fixes #21081 and #21133. Annoyingly, I discovered that more precise demand signatures for join points can transform a program into a lazier program if that join point gets floated to the top-level, see #21392. There is no simple fix at the moment, but !5349 might. Thus, we accept a ~5% regression in `MultiLayerModulesTH_OneShot`, where #21392 bites us in `addListToUniqDSet`. T21392 reliably reproduces the issue. Surprisingly, ghc/alloc perf on Windows improves much more than on other jobs, by 0.4% in the geometric mean and by 2% in T16875. Metric Increase: MultiLayerModulesTH_OneShot Metric Decrease: T16875
Diffstat (limited to 'compiler/GHC/Core/Utils.hs')
-rw-r--r--compiler/GHC/Core/Utils.hs13
1 files changed, 10 insertions, 3 deletions
diff --git a/compiler/GHC/Core/Utils.hs b/compiler/GHC/Core/Utils.hs
index eea81d1502..b4c736bcdc 100644
--- a/compiler/GHC/Core/Utils.hs
+++ b/compiler/GHC/Core/Utils.hs
@@ -2409,13 +2409,20 @@ case where `e` is trivial):
like `g (\x y z. e x y z)` to `g e`, because that diverges when
`e = \x y. bot`.
- Could we relax to "At least *one call in the same trace* is with n args"?
+ Could we relax to "*At least one call in the same trace* is with n args"?
+ (NB: Strictness analysis can only answer this relaxed question, not the
+ original formulation.)
Consider what happens for
``g2 c = c True `seq` c False 42``
- Here, `g2` will call `c` with 2 two arguments (if there is a call at all).
- But it is unsafe to eta-reduce the arg in `g2 (\x y. e x y)` to `g2 e`
+ Here, `g2` will call `c` with 2 arguments (if there is a call at all).
+ But it is unsound to eta-reduce the arg in `g2 (\x y. e x y)` to `g2 e`
when `e = \x. if x then bot else id`, because the latter will diverge when
the former would not.
+ On the other hand, with `-fno-pendantic-bottoms` , we will have eta-expanded
+ the definition of `e` and then eta-reduction is sound
+ (see Note [Dealing with bottom]).
+ Consequence: We have to check that `-fpedantic-bottoms` is off; otherwise
+ eta-reduction based on demands is in fact unsound.
See Note [Eta reduction based on evaluation context] for the implementation
details. This criterion is tested extensively in T21261.