DmdAnal: Annotate some top-level bindings with demands (#18894)
It's useful to annotate a non-exported top-level function like g
in
module Lib (h) where
g :: Int -> Int -> (Int,Int)
g m 1 = (m, 0)
g m n = (2 * m, 2 `div` n)
{-# NOINLINE g #-}
h :: Int -> Int
h 1 = 0
h m
| odd m = snd (g m 2)
| otherwise = uncurry (+) (g 2 m)
with its demand UCU(CS(P(1P(U),SP(U))
, which tells us that whenever g
was
called, the second component of the returned pair was evaluated strictly.
Since #18903 (closed) we do so for local functions, where we can see all calls.
For top-level functions, we can assume that all exported functions are
demanded according to topDmd
and thus get sound demands for
non-exported top-level functions.
The demand on g
is crucial information for Nested CPR, which may the
go on and unbox g
for the second pair component. That is true even if
that pair component may diverge, as is the case for the call site g 13 0
, which throws a div-by-zero exception.
We only track bindings of function type in order not to risk huge compile-time
regressions, see isInterestingTopLevelFn
.
Fixes #18894 (closed).