Opened 3 years ago

Last modified 7 months ago

#7114 new bug

Cannot recover (good) inlining behaviour from 7.0.2 in 7.4.1

Reported by: dreixel Owned by:
Priority: normal Milestone: 7.12.1
Component: Compiler Version: 7.4.1
Keywords: Cc: nfrisby
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Revisions:

Description

(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).

Attachments (1)

Code3.hs (2.7 KB) - added by dreixel 3 years ago.

Download all attachments as: .zip

Change History (6)

Changed 3 years ago by dreixel

comment:1 Changed 3 years ago by nfrisby

  • Cc nfrisby added

comment:2 Changed 3 years ago by igloo

  • difficulty set to Unknown
  • Milestone set to 7.8.1

Thanks for the report

comment:3 Changed 15 months ago by thoughtpolice

  • Milestone changed from 7.8.3 to 7.10.1

Moving to 7.10.1.

comment:4 Changed 8 months ago by thomie

This issue is not resolved yet. Relevant part of the output of ghc-7.9.20141121 -fforce-recomp -ddump-simpl -O1 Code3.hs still has the same structure (to reproduce, search for last Rec in the output):

 lvl_r1aH :: [List]
 [GblId, Caf=NoCafRefs, Str=DmdType]
 lvl_r1aH = GHC.Types.: @ List Code2.Nil (GHC.Types.[] @ List)
 
 Rec {
 Code2.$senum'5 :: [K1 List]
 [GblId,
  Str=DmdType,
  Unf=Unf{Src=<vanilla>, TopLvl=True, Value=False, ConLike=False,
          WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 30 0}]
 Code2.$senum'5 =
   map @ List @ (K1 List) (Code2.K1 @ List) Code2.$fGEnumList_$cgenum
 
 lvl1_r1aI :: Int -> [List]
 [GblId, Arity=1, Str=DmdType]
 lvl1_r1aI =
   \ (x_XNx :: Int) ->
     map
       @ (K1 List)
       @ List
       (\ (x1_XOq :: K1 List) ->
          case x1_XOq of _ [Occ=Dead] { K1 b_axA -> Code2.Cons x_XNx b_axA })
       Code2.$senum'5
 
 lvl2_r1aJ :: [[List]]
 [GblId, Str=DmdType]
 lvl2_r1aJ = map @ Int @ [List] lvl1_r1aI Code2.$fGEnumInt_$cgenum
 
 lvl3_r1aK :: [List]
 [GblId, Str=DmdType]
 lvl3_r1aK = diag @ List lvl2_r1aJ
 
 Code2.$fGEnumList_$cgenum [Occ=LoopBreaker] :: [List]
 [GblId, Str=DmdType]
 Code2.$fGEnumList_$cgenum = ||| @ List lvl_r1aH lvl3_r1aK
 end Rec }

Last edited 8 months ago by thomie (previous) (diff)

comment:5 Changed 7 months ago by thoughtpolice

  • Milestone changed from 7.10.1 to 7.12.1

Moving to 7.12.1 milestone; if you feel this is an error and should be addressed sooner, please move it back to the 7.10.1 milestone.

Note: See TracTickets for help on using tickets.