[GHC] #14013: Bad monads performance

GHC ghc-devs at haskell.org
Tue Jul 25 16:48:56 UTC 2017


#14013: Bad monads performance
-------------------------------------+-------------------------------------
        Reporter:  danilo2           |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  high              |            Milestone:
       Component:  Compiler          |              Version:  8.2.1-rc3
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by simonpj):

 I have not worked all of this out, but I have learned something.

 You have this INLINE pragma:
 {{{
 {-# INLINE mtlStateListParser_a #-}
 }}}
 It does nothing, because the function is recursive.  But alas, it harms
 things a lot.  Simply removing that INLINE pragma makes
 `mtlStateListParser_a` behave well in all settings, I think.  Can you
 confirm that?

 I believe that the reason things go bad is this. GHC does this
 transformation (always):
 {{{
       f = e |> co
 ===>
       f' = e
       f  = f' |> co
 }}}
 Reason: `f` can now be inlined at all use sites, and `co` may cancel.  But
 if the original `f` has an INLINE pragma we get
 {{{
       f = e |> co
         { INLINE = <inline rhs> }
 ===>
       f' = e
       f  = f' |> co
         { INLINE = <inline rhs> }
 }}}
 where the `{ INLINE = <inline rhs> }` is the (stable, user-written)
 inlining for `f`.   Now the point of the transformation is lost, becuase
 `f` won't be replaced at its use sites by `f' |> co`; the INLINE pragma is
 what gets inlined.

 Moreover, if `<inline rhs>` and `e` both mention `f`, then `f` becomes a
 loop breaker and we get mutual recusion between `f` and `f'`.  This what
 ultimately leads to the alternation between `(,)` and `(##)` you observed.
 Solution (I think) don't do this transformation if `f` has an INLINE
 pragma.  I'll try that.

-- 
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14013#comment:9>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list