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 |