Multi-method classes are inlined/specialized better than single-method classes for strict types
Instances of single-method class are optimized better than instances of multi-method classes. Attached is a small example,
class Square a where
square :: a -> a
and a simple data type
data Pair a = Pair !a !a
instance Num a => Square (Pair a) where
square (Pair a b) = Pair (a*a) (b*b)
and a specialized function
squarepd :: Pair Double -> Pair Double
squarepd = pair
Compiled as is, squarepd will turn into this
Test.squarepd :: Test.Pair GHC.Float.Double -> Test.Pair GHC.Float.Double
[GlobalId]
[Arity 1
NoCafRefs
Str: DmdType U(U(L)U(L))m]
Test.squarepd =
\ (eta_sgh :: Test.Pair GHC.Float.Double) ->
case eta_sgh of wild_B1 { Test.Pair a_a60 b_a61 ->
case a_a60 of wild1_agE { GHC.Float.D# x_agG ->
case b_a61 of wild2_Xh2 { GHC.Float.D# x1_Xh7 ->
Test.Pair
@ GHC.Float.Double
(GHC.Float.D# (GHC.Prim.*## x_agG x_agG))
(GHC.Float.D# (GHC.Prim.*## x1_Xh7 x1_Xh7))
}}}
Now if you add another method to class Square (anything at all), this happens
Test.squarepd :: Test.Pair GHC.Float.Double -> Test.Pair GHC.Float.Double
[GlobalId]
[Arity 1
NoCafRefs
Str: DmdType U(U(L)U(L))m]
Test.squarepd =
__inline_me (\ (ds_dgv :: Test.Pair GHC.Float.Double) ->
case ds_dgv of wild_Xi { Test.Pair a_a5Y b_a5Z ->
Test.$WPair
@ GHC.Float.Double
(GHC.Float.timesDouble a_a5Y a_a5Y)
(GHC.Float.timesDouble b_a5Z b_a5Z)
})
Which also what you get when you remove the strictness annotations from 'Pair'.
Trac metadata
| Trac field | Value |
|---|---|
| Version | 6.8.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | Unknown |