[GHC] #15519: Minor code refactoring leads to drastic performance degradation

GHC ghc-devs at haskell.org
Wed Aug 29 12:22:22 UTC 2018


#15519: Minor code refactoring leads to drastic performance degradation
-------------------------------------+-------------------------------------
        Reporter:  danilo2           |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  highest           |            Milestone:  8.8.1
       Component:  Compiler          |              Version:  8.4.3
      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):

 OK I have figured out `test2`.  Consider
 {{{
 f x p = case x of
           A y -> ..(f y p2)...
           B z -> map z something

 main = f (A (B isEven)) blah
 }}}
 `SpecConstr` will see the call `f (A (B isEven))` but, looking at `f`, it
 only see a single-level pattern-match on `x`, so it'll only do a single-
 level specialisation:
 {{{
 f_spec y p = ...(f y p2)...

 {-# RULE f (A y) p = f_spec y p #-}
 }}}
 This is good so far as it goes, but we are left with
 {{{
 f_spec y p = ...(f y p2)...
 main = f_spec (B isEven) something
 }}}
 which is not good (because we have not specialised on `B`.  Even if we ran
 `SpecConstr` a second time, it won't see any reason to specialise `f_spec`
 (since it does not directly scrutinise `y`), and neither will it see any
 reason to further specialise `f`.

 It would be much better to specialise on that full call in the first
 place, giving
 {{{
 f_spec1 p = ...(f (B isEven) p2)...

 {-# RULE f (A (B isEven)) p = f_spec1 p #-}
 }}}
 Now we have a call in the body of `f_spec1` that we can specialise, and
 `SpecConstr` does just that, giving
 {{{
 f_spec2 p = map isEven something

 {-# RULE f (B isEven) p = f_spec2 p #-}
 }}}
 And all is good. The final code is
 {{{
 f_spec2 p = map isEven something
 f_spec1 y p = ...(f_spec2 y p2)...
 main = f_spec1 blah
 }}}
 But specialising on the full call pattern risks over-specialising,
 duplicating code to no purpose, ''and'' making the specialisation less
 useful to other callers.

 I'm not sure what to do about this.

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


More information about the ghc-tickets mailing list