Worker/wrapper should zap OneShot annotations on worker args
Consider
import GHC.Exts
f :: Int -> Int -> Int -> Maybe Int
f x y z = (+) <$> g y z <*> g z y
where
g :: Int -> Int -> Maybe Int
g _ = oneShot $ \z -> Just (x + z)
{-# NOINLINE g #-}
g
is called multiple times, so it's top-level lambda is not one-shot. Its inner lambda, is though, through a use of oneShot
. This situation can happen when doing list fusion on left-folds.
But now notice that g
's first arg is absent. Indeed, that's easy for DmdAnal to see:
let {
g_sCS [InlPrag=NOINLINE, Dmd=SCS(C1(L))] :: Int -> Int -> Maybe Int
[LclId,
Arity=2,
Str=<A><ML> {awZ->M!P(L)},
Cpr=2,
Unf=Unf{Src=<vanilla>, TopLvl=False, Value=True, ConLike=True,
WorkFree=True, Expandable=True, Guidance=IF_ARGS [0 0] 40 10}]
g_sCS
= \ _ [Occ=Dead, Dmd=A] (v_B2 [Dmd=ML, OS=OneShot] :: Int) ->
GHC.Maybe.Just @Int (GHC.Num.$fNumInt_$c+ x_awZ v_B2) } in
So far, so good. Now worker/wrapper comes along and drops the first argument:
$wg_sCZ [InlPrag=NOINLINE] :: Int -> (# Int #)
[LclId, Arity=1, Str=<L>]
$wg_sCZ
= \ (v_sCW [OS=OneShot] :: Int) ->
case let {
ds_dB9 [Occ=Dead, Dmd=A] :: Int
[LclId]
ds_dB9
= GHC.Prim.Panic.absentError
@Int
"Arg: ds\n\
\Type: Int\n\
\In module `Lib'"# } in
let {
v_B2 [OS=OneShot] :: Int
[LclId]
v_B2 = v_sCW } in
GHC.Maybe.Just @Int (GHC.Num.$fNumInt_$c+ x_awZ v_B2)
of ww_sCX
{ __DEFAULT ->
case ww_sCX of wild_00 { Just ww_sD5 -> (# ww_sD5 #) }
} } in
But also note that it kept the OneShot
on the second argument! That's totally wrong and not at all in line with what demand analysis found out (which isn't actually relevant here because we drop demand signatures on workers).
I found this out because we were inlining under such a one-shot lambda and repeating otherwise shared work.
Conclusion: Zap OneShot
annotations on workers to prevent this.