summaryrefslogtreecommitdiff
path: root/compiler/GHC/Core/Opt
diff options
context:
space:
mode:
authorSebastian Graf <sebastian.graf@kit.edu>2020-10-30 17:20:37 +0100
committerSebastian Graf <sebastian.graf@kit.edu>2020-11-20 09:48:01 +0100
commitc90df9e3b0d7551e2de1e1571ad358e91f625ccc (patch)
tree17387b83d903a5495eaa5d55431e6b807e079326 /compiler/GHC/Core/Opt
parent802e9180dd9a9a88c4e8869f0de1048e1edd6343 (diff)
downloadhaskell-wip/T18885.tar.gz
Demand: Nested strict product demands (#18885)wip/T18885
Fixing #18903 gives us enough expressiveness to tackle #18885, where we have ```hs f :: Int -> Int f y = let x | expensive y == 1 = (expensive (y+1), expensive (y+2)) | otherwise = (expensive (y+3), expensive (y+4)) in case () of _ | expensive (y+5) == 42 -> fst x _ | expensive (y+6) == 41 -> fst x + snd x _ | otherwise -> 0 ``` Here, we used to give `x` demand `1P(1P(U),1P(U))`. The outer `1` is because `x` is used lazily and the inner `1`s are redundant with that fact. That leaves some expressiveness on the table. After this change, we infer `1P(SP(U),1P(U))`, meaning that *whenever we evaluate `x`*, we evaluate its first component strictly, effectively making strictness product demands apply *relatively*. Usage product demands still apply absolutely, though. More details on how we could exploit the new language in `Note [Absent sub-demands]`. Fixes #18885. There's a single remaining regression in `T9630`, which increases +16% in residency but decreases slightly in total allocations. I checked the heap profile, which doesn't suggest any obvious regressions. Ticky doesn't point to the reason either, because total allocations actually improved. I think it's OK to just accept it. Metric Increase: T9630
Diffstat (limited to 'compiler/GHC/Core/Opt')
-rw-r--r--compiler/GHC/Core/Opt/DmdAnal.hs12
1 files changed, 7 insertions, 5 deletions
diff --git a/compiler/GHC/Core/Opt/DmdAnal.hs b/compiler/GHC/Core/Opt/DmdAnal.hs
index 4869fb1fa9..ae8aab18a8 100644
--- a/compiler/GHC/Core/Opt/DmdAnal.hs
+++ b/compiler/GHC/Core/Opt/DmdAnal.hs
@@ -233,9 +233,10 @@ dmdAnal' env dmd (Case scrut case_bndr ty [(alt, bndrs, rhs)])
(rhs_ty, rhs') = dmdAnal env dmd rhs
(alt_ty1, dmds) = findBndrsDmds env rhs_ty bndrs
(alt_ty2, case_bndr_dmd) = findBndrDmd env False alt_ty1 case_bndr
- -- Evaluation cardinality on the case binder is irrelevant and a no-op.
- -- What matters is its nested sub-demand!
- (_ :* case_bndr_sd) = case_bndr_dmd
+ -- The peelDmd below will lazify the relative sub-demands if the
+ -- case_bndr_dmd had lazy evaluation cardinality.
+ -- See Note [Absent sub-demand] in GHC.Types.Demand
+ case_bndr_sd = peelDmd case_bndr_dmd
-- Compute demand on the scrutinee
(bndrs', scrut_sd)
| DataAlt _ <- alt
@@ -388,9 +389,10 @@ dmdAnalSumAlt :: AnalEnv -> SubDemand -> Id -> Alt Var -> (DmdType, Alt Var)
dmdAnalSumAlt env dmd case_bndr (con,bndrs,rhs)
| (rhs_ty, rhs') <- dmdAnal env dmd rhs
, (alt_ty, dmds) <- findBndrsDmds env rhs_ty bndrs
- , let (_ :* case_bndr_sd) = findIdDemand alt_ty case_bndr
+ , let case_bndr_dmd = findIdDemand alt_ty case_bndr
-- See Note [Demand on scrutinee of a product case]
- id_dmds = addCaseBndrDmd case_bndr_sd dmds
+ -- See Note [Absent sub-demand] in GHC.Types.Demand
+ id_dmds = addCaseBndrDmd (peelDmd case_bndr_dmd) dmds
= (alt_ty, (con, setBndrsDemandInfo bndrs id_dmds, rhs'))
{-