[GHC] #14941: Switching direct type family application to EqPred (~) prevents inlining in code using vector (10x slowdown)

GHC ghc-devs at haskell.org
Thu Jul 5 01:02:15 UTC 2018


#14941: Switching direct type family application to EqPred (~) prevents inlining in
code using vector (10x slowdown)
-------------------------------------+-------------------------------------
        Reporter:  nh2               |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              Version:  8.2.2
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
 Type of failure:  Runtime           |  Unknown/Multiple
  performance bug                    |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by nh2):

 This seems to be unrelated to type families and only a problem with `~` in
 general, because:

 I now also found a case where using `(val ~ Int) =>` produces slower code
 than subsituting `val` with `Int` syntactically, or using `SPECIALISE`.

 {{{
 myfun :: forall val . (Eq val, Show val, val ~ Int) => Mytype1 val ->
 Mytype2 val -> Mytype3 -> Mytype4 -> Mytype5 -> Mytype6 -> IO ()
 }}}

 is slow, but

 {{{
 {-# SPECIALIZE myfun :: Mytype1 Int -> Mytype2 Int -> Mytype3 -> Mytype4
 -> Mytype5 -> Mytype6 -> IO () #-}

 myfun :: forall val . (Eq val, Show val, val ~ Int) => Mytype1 val ->
 Mytype2 val -> Mytype3 -> Mytype4 -> Mytype5 -> Mytype6 -> IO ()
 }}}

 is fast (in my case, a 30% performance difference).

 Diffing the output of `-ddump-simpl -ddump-to-file -dsuppress-idinfo
 -dsuppress-coercions -dsuppress-module-prefixes -dsuppress-uniques` shows
 how the call looks different from a module that calls `myfun`:

 `val ~ Int` version:

 {{{
 $d~~ :: (Int :: *) ~~ (Int :: *)
 $d~~ = Eq# @ * @ * @ Int @ Int @~ ...

 ...
                        $wmyfun
                          @ Int
                          $fEqInt
                          ($d~~ `cast` ...)
                          y
                          wild
                          mything1
                          ipv7
                          mything2
                          ww1
                          w9)
 ...
 }}}

 `SPECIALISE`d `val ~ Int` version:

 {{{
                        myfun
                          y
                          wild
                          mything1
                          ipv7
                          mything2
                          ww1
 }}}

 I would have expect that after the simplifier has run, GHC would have used
 all information it has to produce the best core (e.g. use the fact that it
 knows `val ~ Int` even without `SPECIALISE`), but it did not.

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


More information about the ghc-tickets mailing list