[GHC] #13873: Adding a SPECIALIZE at a callsite in Main.hs is causing a regression

GHC ghc-devs at haskell.org
Mon Jul 3 14:47:26 UTC 2017


#13873: Adding a SPECIALIZE at a callsite in Main.hs is causing a regression
-------------------------------------+-------------------------------------
        Reporter:  jberryman         |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:  8.2.2
       Component:  Compiler          |              Version:  8.2.1-rc2
      Resolution:                    |             Keywords:  Specialise
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 mpickering):

 That's right Simon.

 How this happens is that the `SPECIALISE` pragma creates a rule which
 looks like

 {{{

 "SPEC insertWith"
     forall (@ k)
            (@ s)
            (@ v)
            ($dHashable :: Hashable k)
            ($dEq :: Eq k)
            ($dPrimMonad :: PrimMonad (ST s)).
       insertWith @ k @ (ST s) @ v $dHashable $dEq $dPrimMonad
 = $sinsertWith @ k @ s @ v $dHashable $dEq

 }}}

 which fires at quite an early stage in optimisation. Then any function in
 `$sinsertWith` which mentions `s` won't be specialised as it is lambda
 bound.


 If you remove the pragma you just get one specialisation rule which
 probably arises after a lot of inlining has happened.

 {{{
 "SPEC/Main insert @ ByteString @ (ST RealWorld) _"
     forall (@ v)
            ($dPrimMonad :: PrimMonad (ST RealWorld))
            ($dEq :: Eq ByteString)
            ($dHashable :: Hashable ByteString).
       insert @ ByteString
              @ (ST RealWorld)
              @ v
              $dHashable
              $dEq
              $dPrimMonad
 = $scheckResize_$sinsert @ v
 }}}

 and if you fix `s = RealWorld` with the specialisation pragma then both
 occur.

 {{{

 "SPEC insertWith"
     forall (@ k)
            (@ v)
            ($dHashable :: Hashable k)
            ($dEq :: Eq k)
            ($dPrimMonad :: PrimMonad (ST RealWorld)).
       insertWith @ k @ (ST RealWorld) @ v $dHashable $dEq $dPrimMonad
       = $sinsertWith @ k @ v $dHashable $dEq
 "SPEC/Main insert @ ByteString @ (ST RealWorld) _"
     forall (@ v)
            ($dPrimMonad :: PrimMonad (ST RealWorld))
            ($dEq :: Eq ByteString)
            ($dHashable :: Hashable ByteString).
       insert @ ByteString
              @ (ST RealWorld)
              @ v
              $dHashable
              $dEq
              $dPrimMonad
 = $scheckResize_$sinsert @ v
 }}}

 Seeing as you also ask for the type of `g`, it is defined in another
 module as is marked `INLINABLE`.

 {{{
 checkResize::(Hashable k,Eq k,PrimMonad m)
            => HashTable_ (PrimState m) k v
 -> m (Maybe (HashTable (PrimState m) k v))
 }}}

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


More information about the ghc-tickets mailing list