[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