#7114: Cannot recover (good) inlining behaviour from 7.0.2 in 7.4.1 ------------------------------+--------------------------------------------- Reporter: dreixel | Owner: Type: bug | Status: new Priority: normal | Component: Compiler Version: 7.4.1 | Keywords: Os: Unknown/Multiple | Architecture: Unknown/Multiple Failure: None/Unknown | Testcase: Blockedby: | Blocking: Related: | ------------------------------+--------------------------------------------- (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). -- Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/7114> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler _______________________________________________ Glasgow-haskell-bugs mailing list Glasgow-haskell-bugs@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs