
#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