Interleave usage and strictness demands
As outlined in #18903 (closed), interleaving usage and strictness demands not only means a more compact demand representation, but also allows us to express demands that we weren't easily able to express before.
Call demands are relative in the sense that a call demand Cn(cd)
on g
says "g
is called n
times. Whenever g
is called, the
result is used according to cd
". Example from #18903 (closed):
h :: Int -> Int
h m =
let g :: Int -> (Int,Int)
g 1 = (m, 0)
g n = (2 * n, 2 `div` n)
{-# NOINLINE g #-}
in case m of
1 -> 0
2 -> snd (g m)
_ -> uncurry (+) (g m)
Without the interleaved representation, we would just get L
for the
strictness demand on g
. Now we are able to express that whenever
g
is called, its second component is used strictly in denoting g
by 1C1((1(U),S(U)))
. This would allow a subsequent Nested CPR to unbox the
division, for example.
Now other advances in expressiveness like #18885 (closed) are possible.
Fixes #18903 (closed).