WorkWrap: `certainlyWillInline` bindings have non-WW'd unfoldings
In #19727 (closed) we have a situation that is quite similar to
small :: Int -> Int
small x = go 0 x
where
go z 0 = z * x
go z y = go (z+y) (y-1)
Here, small
satisfies certainlyWillInline
. Thus, we give it a stable unfolding in WW. But in that stable unfolding, the local go
function should better have been WW'd! Yet, we see
small :: Int -> Int
[GblId,
Arity=1,
Str=<1P(SL)>,
Cpr=1,
Unf=Unf{Src=InlineStable, TopLvl=True, Value=True, ConLike=True,
WorkFree=True, Expandable=True,
Guidance=ALWAYS_IF(arity=1,unsat_ok=True,boring_ok=False)
Tmpl= \ (x_auy :: Int) ->
joinrec {
go_sKU [Occ=LoopBreakerT[2]] :: Int -> Int -> Int
[LclId[JoinId(2)], Arity=2, Str=<L><L>, Unf=OtherCon []]
go_sKU (z_auA [Occ=Once2!] :: Int) (ds_dKl [Occ=Once1!] :: Int)
= case ds_dKl of { GHC.Types.I# ds1_dKm [Occ=Once1!] ->
case ds1_dKm of ds2_X3 {
__DEFAULT ->
jump go_sKU
(case z_auA of { GHC.Types.I# x1_aKu [Occ=Once1] ->
GHC.Types.I# (GHC.Prim.+# x1_aKu ds2_X3)
})
(GHC.Types.I# (GHC.Prim.-# ds2_X3 1#));
0# -> GHC.Num.$fNumInt_$c* z_auA x_auy
}
}; } in
jump go_sKU Lib.small1 x_auy}]
small
= \ (x_auy :: Int) ->
case x_auy of { GHC.Types.I# ww_sL3 ->
join {
exit_X4 [Dmd=SCS(L)] :: GHC.Prim.Int# -> Int
[LclId[JoinId(1)], Arity=1, Str=<L>]
exit_X4 (ww1_sKZ [OS=OneShot] :: GHC.Prim.Int#)
= GHC.Types.I# (GHC.Prim.*# ww1_sKZ ww_sL3) } in
joinrec {
$wgo_sL6 [InlPrag=[2], Occ=LoopBreaker, Dmd=SCS(C1(L))]
:: GHC.Prim.Int# -> GHC.Prim.Int# -> Int
[LclId[JoinId(2)], Arity=2, Str=<L><1L>, Unf=OtherCon []]
$wgo_sL6 (ww1_sKZ :: GHC.Prim.Int#) (ww2_X5 :: GHC.Prim.Int#)
= case ww2_X5 of ds_X3 {
__DEFAULT ->
jump $wgo_sL6 (GHC.Prim.+# ww1_sKZ ds_X3) (GHC.Prim.-# ds_X3 1#);
0# -> jump exit_X4 ww1_sKZ
}; } in
jump $wgo_sL6 0# ww_sL3
}
That's because the call to certainlyWillInline
, which is called from splitFun
, operates on the unfolding pre-WW. We should update the unfolding here, in wwBind
:
wwBind :: WwOpts
-> CoreBind
-> UniqSM [CoreBind] -- returns a WwBinding intermediate form;
-- the caller will convert to Expr/Binding,
-- as appropriate.
wwBind ww_opts (NonRec binder rhs) = do
new_rhs <- wwExpr ww_opts rhs
new_pairs <- tryWW ww_opts NonRecursive binder new_rhs
return [NonRec b e | (b,e) <- new_pairs]
Note the new_rhs
passed to tryWW
(which calls splitFun
), but the lack of updating on binder
.