Improve CPR analysis (but actually improve eta-expansion)
When a function returns a nested data structure, GHC should expose that fact to the caller. This can make a very big difference in inner loops. A good example is the following message (from GHC users http://www.haskell.org/pipermail/glasgow-haskell-users/2007-November/013454.html).
Compile the attached files thus:
ghc --make Unpacked.hs -O2 -cpp -DPOLY_SAME
and similarly with DPOLY_OTHER
. The POLY_OTHER
case does a lot more allocation because a key function isn't inlined.
$wa_r1Wb :: GHC.Prim.Addr#
-> GHC.Prim.State# GHC.Prim.RealWorld
-> (# GHC.Prim.State# GHC.Prim.RealWorld,
OtherP.C
GHC.Float.Double (OtherP.C GHC.Float.Double
(OtherP.C GHC.Float.Double ())) #)
[GlobalId]
[Arity 2
NoCafRefs
Str: DmdType LL]
$wa_r1Wb =
\ (ww_s1S5 :: GHC.Prim.Addr#) (w_s1S7 :: GHC.Prim.State# GHC.Prim.RealWorld) ->
case GHC.Prim.readDoubleOffAddr# @ GHC.Prim.RealWorld ww_s1S5 0 w_s1S7
of wild2_a1xI { (# s2_a1xK, x_a1xL #) ->
let {
ipv_XGd [Just L] :: GHC.Prim.Addr#
[Str: DmdType]
ipv_XGd = GHC.Prim.plusAddr# ww_s1S5 8 } in
case GHC.Prim.readDoubleOffAddr# @ GHC.Prim.RealWorld ipv_XGd 0 s2_a1xK
of wild21_X1yK { (# s21_X1yN, x1_X1yP #) ->
case GHC.Prim.readDoubleOffAddr#
@ GHC.Prim.RealWorld (GHC.Prim.plusAddr# ipv_XGd 8) 0 s21_X1yN
of wild22_X1yU { (# s22_X1yX, x2_X1yZ #) ->
(# s22_X1yX,
OtherP.C
@ GHC.Float.Double
@ (OtherP.C GHC.Float.Double (OtherP.C GHC.Float.Double ()))
(GHC.Float.D# x_a1xL)
(OtherP.C
@ GHC.Float.Double
@ (OtherP.C GHC.Float.Double ())
(GHC.Float.D# x1_X1yP)
(OtherP.C @ GHC.Float.Double @ ()
(GHC.Float.D# x2_X1yZ) GHC.Base.())) #)
} } }