Cannot recover (good) inlining behaviour from 7.0.2 in 7.4.1
(I'm sorry that this test case is so large.)
The attached module Code3.hs
is a highly simplified version of a generic implementation of enumeration, followed by its instantiation to a datatype of lists of integers. The goal is to drive the simplifier to fully specialise the generic version to an optimised version for lists, without any reference to the generic representation constructors.
With GHC 7.0.2, the (interesting part of the) attached module compiles to the following core code (my renaming):
enumNil :: [Code2.List]
[GblId, Caf=NoCafRefs]
enumNil =
GHC.Types.: @ Code2.List Code2.Nil (GHC.Types.[] @ Code2.List)
Rec {
lvl1_roO :: GHC.Types.Int -> [Code2.List]
[GblId, Arity=1]
lvl1_roO =
\ (x_XnO :: GHC.Types.Int) ->
GHC.Base.map
@ Code2.List
@ Code2.List
(\ (x1_XnN :: Code2.List) -> Code2.Cons x_XnO x1_XnN)
enumList
lvl2_roR :: [[Code2.List]]
[GblId]
lvl2_roR =
GHC.Base.map
@ GHC.Types.Int @ [Code2.List] lvl1_roO enumInt
enumCons :: [Code2.List]
[GblId]
enumCons = Code2.diag @ Code2.List lvl2_roR
enumList [Occ=LoopBreaker] :: [Code2.List]
[GblId, Str=DmdType]
enumList = Code2.||| @ Code2.List enumNil enumCons
end Rec }
This is exactly what is intended: no more generic representation stuff. GHC 7.4.1, however, doesn't quite achieve this, instead leaving us with the following:
enumNil :: [Code2.List]
[GblId, Caf=NoCafRefs]
enumNil =
GHC.Types.: @ Code2.List Code2.Nil (GHC.Types.[] @ Code2.List)
Rec {
a_rme :: [Code2.K1 Code2.List]
[GblId, Str=DmdType]
a_rme =
GHC.Base.map
@ Code2.List
@ (Code2.K1 Code2.List)
(Code2.K1 @ Code2.List)
enumList
lvl1_rmf :: GHC.Types.Int -> [Code2.List]
[GblId, Arity=1]
lvl1_rmf =
\ (x_Xmk :: GHC.Types.Int) ->
GHC.Base.map
@ (Code2.K1 Code2.List)
@ Code2.List
(\ (x1_Xn9 :: Code2.K1 Code2.List) ->
case x1_Xn9 of _ { Code2.K1 b_aaM -> Code2.Cons x_Xmk b_aaM })
a_rme
lvl2_rmg :: [[Code2.List]]
[GblId]
lvl2_rmg =
GHC.Base.map
@ GHC.Types.Int @ [Code2.List] lvl1_rmf enumInt
enumCons :: [Code2.List]
[GblId]
enumCons = Code2.diag @ Code2.List lvl2_rmg
enumList [Occ=LoopBreaker] :: [Code2.List]
[GblId, Str=DmdType]
enumList = Code2.||| @ Code2.List enumNil enumCons
end Rec }
The strange part is the interaction between the lvl1_rmf
and a_rme
functions: basically a_rme
maps K1
over a list, and lvl1_rmf
maps a function that takes this K1
away.
I have no idea why 7.4.1 leaves this residue around. I have played with different inline pragmas and rewrite rules, but so far have been unable to convince GHC 7.4.1 to just do what 7.0.2 did. Turning K1
into a newtype
doesn't help (we're left with a newtype coercion instead).
Trac metadata
Trac field | Value |
---|---|
Version | 7.4.1 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |