[GHC] #11272: Overloaded state-monadic function is not specialised
GHC
ghc-devs at haskell.org
Thu Dec 8 01:42:37 UTC 2016
#11272: Overloaded state-monadic function is not specialised
-------------------------------------+-------------------------------------
Reporter: NickSmallbone | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 7.10.3
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 nfrisby):
If I add the `INLINABLE overloaded` pragma in `A` and place a `SPECIALIZE
overloaded :: Int -> Int -> State () ()` pragma in `B`, then the desired
specialization ultimately happens (with GHC 7.10.2). I mention this as a
possible workaround for people stuck on this bug.
Forcing the `overloaded` wrapper to be specialized creates a "SPEC" rule
whose RHS gets gently simplified enough before the Specialise pass such
that GHC then notices the specializable call to the `$woverloaded` worker.
Since that worker inherits the original `INLINABLE` pragma (see #6056),
GHC automatically specializes the worker. The specialized worker
eventually ends up in the RHS of `specialised`.
This approach was not obvious to me because I hadn't yet realized that
forcibly specializing a w/w wrapper function tends to cause the worker to
be automatically specialized. Two shortcomings come immediately to mind.
1. I get the `SPECIALISE pragma on INLINE function probably won't fire:
‘overloaded’` warning, even though the rule does fire.
1. In my experience, `SPECIALIZE` pragmas are often rejected with "LHS too
complicated to desugar" (e.g. #10555), so you may need to use
`GHC.Exts.inline` instead.
* Note that `inline` crucially causes the w/w wrapper to be inlined
before the Specialise pass (during `Phase = InitialPhase [Gentle]`),
whereas the w/w wrapper's `INLINE[0]` activation delays its natural
inlining until after the Specialise pass.
* This is awkward: we only want to inline `overloaded` '''if it was
replaced by a w/w wrapper'''! A "safer" but more troublesome alternative
is to have `inline overloaded` somewhere else in the module, but then you
must ensure that it's exported from this module, else GHC will cull it and
the SPEC rule before the rule can usefully affect `specialise`. This risks
binary bloat, but it also prevents `inline` from ever accidentally
inlining `overloaded` into the genuine code.
It's remarkable that the w/w transform creates the cast that prevents the
wrapper from being automatically specialized (that cast floats to the top
of the unfolding, which blocks specialization; see `Note [Specialisation
shape]` in `Specialise.hs`). The demand analyzer and w/w transform in this
example see through the `State` type synonym, `StateT` newtype, and
`Identity` newtype all the way to the `s -> (# a, s #)` worker type -- the
`Specialise` pass does not yet have the complementary X-ray vision to see
through the corresponding cast to the desired lambdas in the wrapper's
unfolding.
(#9509 is also specialization-blocked-by-a-cast-atop-the-unfolding, but I
think the cast in that case comes from an actual bug.)
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11272#comment:2>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list