Version 4 (modified by nomeata, 15 months ago) (diff) |
---|

## 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