== wave4main ==
Baseline: [0e2fd3/ghc], Tested: nested-cpr (without nesting inside sum-types, without join-point detection).
Found a 11% increase in allocation, around `9000000` bytes.
The most obvious change in ticky-ticky-number are:
* `FUNCTION ENTRIES` and `ENTERS` increasing by ~100000
* `RETURNS` doubling from 140745 to 280795
* `ALLOC_FUN_ctr` and `ALLOC_FUN_gds` almost doubling, by ~18000 resp. 9000000
So we are allocating more function closures. First guess: Join point property destroyed somewhere.
The ticky output shows a `$wgo{v s60k} (main:Main)` appearing that was not there before, with `140016` enters and `23522688` allocations. This appears in `$wtabulate`, and indeed corresponds to a `go1` that is a join-point before. So what is happening? We are changing
{{{
go1 [Occ=LoopBreaker]
:: GHC.Prim.Int#
-> GHC.Prim.State# s
-> (# GHC.Prim.State# s, GHC.Arr.Array GHC.Types.Int x #)
}}}
to
{{{
$wgo [Occ=LoopBreaker]
:: GHC.Prim.Int#
-> GHC.Prim.State# s
-> (# GHC.Prim.State# s,
GHC.Prim.Int#,
GHC.Prim.Int#,
GHC.Prim.Int#,
GHC.Prim.Array# x #)
}}}
`go1` is recursive, but tail-recursive, so the worker and wrapper indeed cancel for the recursive call. But where it is being used, we simply apply the `Array` constructor to the second component. So nothing is gained, but a join-point is lost.
My attempt below to detect join points does not help: The CPR information for `go1` is the same as for `let go1 = rhs in body`, as `body` is just `go1 ww ipv`.
The problem is that this is being passed as an argument to a function (in this case `runSTRep`), and there is not much that can be done about this at this point.
== Summary with simple expressions ==
Original code:
{{{
f a x = case a of
True -> case foo of b -> foo $
let go 0 = (1,(2,3))
go n = go (n-1)
in go b
False -> undefined
}}}
which after CPR transformation yields, where `$go` is no longer a join-point for the argument to `snd`.
{{{
f a x = case a of
True -> case foo of b -> foo $
let $wgo 0 = (# 1, 2, 3 #)
$wgo n = go (n-1)
in case $wgo b of (# a, b, c #) -> (a, (b,c))
False -> undefined
}}}