[GHC] #13873: Adding a SPECIALIZE at a callsite in Main.hs is causing a regression
GHC
ghc-devs at haskell.org
Sat Jul 1 21:55:34 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):
I looked at this.
Firstly, 8.2.1 is much faster than 8.0.2. So I looked at the core for both
versions.
The key function is `wcJH` which in 8.0.2 calls `$winsertWith` with a
dictionary argument `$fPrimMonadST`.
In 8.2.1, this function does get specialised (see `$s$winsertWith`) which
accounts for the difference.
When the specialisation happens, the type of the specialised function is
{{{#!hs
$w$sinsertWith :: MutVar# (PrimState (ST RealWorld)) (HashTable_
(PrimState (ST RealWorld)) ByteString v)
-> v -> v -> v
-> ByteString
-> v
-> State# RealWorld
-> (# State# RealWorld, () #)
}}}
The specialisation produced by the specialise pragma is instead,
{{{#!hs
$w$sinsertWith :: MutVar# (PrimState (ST s)) (HashTable_ (PrimState (ST
s)) ByteString v)
-> v -> v -> v
-> ByteString
-> v
-> State# s
-> (# State# s, () #)
}}}
as such the `s` parameter is not specialised to `RealWorld`. Changing the
specialise pragma to
{{{#!hs
{-# SPECIALIZE J.insertWith::(Hashable k,Eq k)
=> J.HashTable RealWorld k v
-> (v->v->v) -> k -> v
-> ST RealWorld () #-}
}}}
makes the performance the same.
Digging much deeper, deep in the definition of the specialised insertWith
function there is a call to `checkResize`. Without the pragma,
this is specialised but with the pragma, it is not specialised and passed
three dictionary arguments. Fixing `s` in the specialise pragma to
`RealWorld`. also causes `checkResize` to be specialised which is why the
performance improves.
So it seems that the specialisation is not as good with the manual pragma
as GHC is specialising more than the pragma in order to also remove a type
argument. This means that other functions called by `insertWith` can also
be specialised, if we do not specialise on `s` as well then their type
will mention this type argument `s` which means that calls to this
function are removed by `dumpBindUDs` at the top level.
GHC itself will not remove the type argument `s` as we only specialise on
dictionary arguments - it does seem like we might be able to do better
here. If we were to further specialise `insertWith` in order to also
remove the type argument then it would cause `checkResize` to specialise
as well.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13873#comment:3>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list