Demand: Nested strict product demands (#18885)
Controversial follow-up of !4371 (closed).
Fixing #18903 (closed) gives us enough expressiveness to tackle #18885 (closed), where we have
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 (closed).
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