Demand analyser should unpack tuple dictionaries
Consider
{-# OPTIONS_GHC -O -fdicts-strict #-}
module Foo where
type PairDict a = (Eq a, Show a)
foo :: PairDict a => a -> a -> String
foo x y | x==y = show x
| otherwise = show y
At the moment, with -O
we generate this:
foo :: forall a. PairDict a => a -> a -> String
[GblId,
Str=<SP(SP(1C(1,C(1,L)),A),SP(A,1C(1,L),A))><L><L>,
Unf=Unf{Src=<vanilla>, TopLvl=True]
foo
= \ (@a_aPr)
($d(%,%)_aPs :: PairDict a_aPr)
(eta_B0 :: a_aPr)
(eta1_B1 :: a_aPr) ->
case ==
@a_aPr
(GHC.Classes.$p0(%,%) @(Eq a_aPr) @(Show a_aPr) $d(%,%)_aPs)
eta_B0
eta1_B1
of {
False ->
show
@a_aPr
(GHC.Classes.$p1(%,%) @(Eq a_aPr) @(Show a_aPr) $d(%,%)_aPs)
eta1_B1;
True ->
show
@a_aPr
(GHC.Classes.$p1(%,%) @(Eq a_aPr) @(Show a_aPr) $d(%,%)_aPs)
eta_B0
}
Notice that we are strict in the pair dictionary, but we do not unpack it. Why not? Because of Note [Do not unbox class dictionaries]
in GHC.Core.Opt.DmdAnal.
But for tuple dictionaries it would be better to unpack. Then we'd get
$wfoo :: (Eq a, Show a) => blah
and we might well be able to specialise it for particular Eq
or Show
dictionaries. The above Note
doesn't apply.
Actually for "equality classes" like
bar :: (a ~ b) => blah
we would also be better off unboxing. Not much point in specialising bar
for two particular types. All we do is make a copy of bar
's RHS with a particular coercion. Unlike notmrla class methods, that does not unlock any new optimisation opportunities in the specialised RHS.
TL;DR: narrow Note [Do not unbox class dictionaries]
to ignore tuple classes and equality classes.