[GHC] #14239: Let -fspecialise-aggressively respect NOINLINE (or NOSPECIALISABLE?)
GHC
ghc-devs at haskell.org
Thu Sep 21 10:51:06 UTC 2017
#14239: Let -fspecialise-aggressively respect NOINLINE (or NOSPECIALISABLE?)
-------------------------------------+-------------------------------------
Reporter: MikolajKonarski | Owner: (none)
Type: feature request | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 8.2.1
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 MikolajKonarski):
I think there are many way to interpret the negative flags. I can easily
think about two: by trigger (passes) and by mechanism (micro-decisions).
Let me explain by sketching the semantics of NOSPECIALISABLE pragma. For
simplicity I assume GHC works by making separate passes over code, e.g.,
inlining pass and specialising pass. I think this is a good mental model
for a programmer, as opposed to a tangled mess of iterated optimization
micro-decisions, even if the latter is much closer to reality.
NOSPECIALISABLE by trigger: when GHC is looking for functions to
specialise, ignore the function. The inlining pass may independently
decide to inline it.
NOSPECIALISABLE by mechanism: in the specialisation pass, if the function
meets the criteria for specialisation *and* specialisation-by-inlining,
inline it, otherwise ignore it, never create a specialised copy. The
inlining pass is free to make its own decisions, in particular, criteria
for inlining may be different than for specialisation-by-inlining.
For my use case, for simplicity of the mental model, I'd prefer by-trigger
semantics, because I want the NOSPECIALISABLE to just mark an exception to
the `-fspecialise-aggressively` option and I understand such global
default-changing options to affect passes --- decisions whether a
functions should be transformed at all, not micro-decisions how to best
transform it (e.g., whether to specialize it by copy or by inlining). If
one wants to risk forcing particular micro-decisions, there are other GHC
flags to use, e.g., the thresholds for inlining and other fine-tuning, but
the results are hard to predict and context-sensitive, so I'd keep them
separate.
Examples of the by-trigger semantics, SPECIALISABLE+NOINLINE is free to
perform specialisation-by-inlining, because NOINLINE just says to ignore
the function during the inlining pass (but not during the specialising
pass). INLINE+NOSPECIALISABLE is not equivalent to INLINE, I guess,
because a recursive function can't be inlined, but might be specialized by
copy.
The by-trigger semantics probably doesn't match the reality of GHC code
and the current semantics of NOINLINE. For the trigger semantics there
would need to be separate code that checks whether a function should be
considered for inlining and a separate code that checks if a function we
are specializing should instead be inlined. The NOINLINE pragma would only
be inspected in the former. This also implies NOINLINE should not inhibit
exposing of unfoldings.
The by-trigger semantics in full:
* NOINLINE: please do not consider this function when deciding which
functions to inline (even if it fits the criteria). But GHC is free to
specialise it, even inlining it in the process.
* NOSPECIALISABLE: please do not specialise this function (even if it
would otherwise be easy to do so).
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14239#comment:5>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list