Inlining is the most important compiler optimisation pass as it enables most other optimisation opportunities. The pass is simple, saturated names are replaced with their definitions, the details are complicated. The compiler must make judgements as to whether inlining a function will lead to further optimisations, if not then it is easy to increase the code size needlessly.

Getting Started

Generics and Inlining

Inlining is essential to remove intermediate representations from generic programs. There are a number of papers about the topic.

Debugging the inliner

Firstly, remember that the inliner only fires with optimisations turns on (at least -O1). This will save you a lot of time wondering why nothing is happening!

There are several flags which are useful when working with the inliner.

Flag Usage
`--show-iface` Shows the contents of an interface file. Can be useful to check which unfoldings are being included.
`-dshow-passes` Shows the size of the program after each optimisation pass.
`-ddump-inlinings` Shows inlinings which take place
`-ddump-simpl` Dump the (core) output of the simplifer

Newcomer Tickets

Better inlining test in CoreUnfold
unfolding info as seen when building a module depends on flags in a previously-compiled module
Make Generic/Generic1 methods inlinable
Remove the `isInlinePragma prag` test

Relevant Tickets

There are lots of old relevant tickets related to inlining. Perfect for a keen newcomer!

Use Keyword = Inlining to ensure that a ticket ends up on these lists.

Avoid reconstructing dictionaries in recursive instance methods
Improve join point inlining
Improve inlining for local functions
Better inlining test in CoreUnfold
Allow both INLINE and INLINABLE for the same function
INLINABLE fails to specialize in presence of simple wrapper
Inlining depends on datatype size, even with INLINE pragmas
Cannot recover (good) inlining behaviour from 7.0.2 in 7.4.1
Specialise INLINE functions
Room for GHC runtime improvement >~5%, inlining related
Superclass methods are left unspecialized
make better/more robust loopbreaker choices
Alternate syntax for indicating when a function is "fully applied" for purposes of inlining
Bad choice of loop breaker with INLINABLE/INLINE
GHC does not inline cheap inner loop when used in two places
SPECIALIZE silently fails to apply
Transitivity of Auto-Specialization
7.8 optimizes attoparsec improperly
Massive blowup of code size on trivial program
Inlining regression/strangeness in 7.8
unfolding info as seen when building a module depends on flags in a previously-compiled module
Warnings about "INLINE binder is (non-rule) loop breaker"
GADTs not specialized properly
Frustrating behaviour of the INLINE pragma
GHC fails to inline and specialize a function
exponential blowup in inlining (without INLINE pragmas)
More self-explanatory pragmas for inlining phase control
user manual: INLINE's interaction with optimization levels is not clear
Make Generic/Generic1 methods inlinable
"Simplifier ticks exhausted" that resolves with fsimpl-tick-factor=200
Remove the `isInlinePragma prag` test
GHC panic: simplifier ticks exhausted
Cross-module specialisation of recursive functions
SPECIALIZE INLINE doesn't necessarily inline specializations of a recursive function
Space leak / quadratic behavior when inlining
Simple function not inlined within declaration marked NOINLINE

Relevant Wiki Pages

Last modified 4 months ago Last modified on Mar 27, 2017 10:18:10 AM

Attachments (3)

  • unroll0.hs (1.6 KB) - added by claus 8 years ago. trivial loop, INLINE loop PEEL 1 UNROLL 4, plus reassociation RULES
  • unroll1.hs (1.6 KB) - added by claus 8 years ago. loop over bulk-array op, INLINE loop PEEL 1 UNROLL 4 activates array fusion RULES
  • unroll2.hs (729 bytes) - added by claus 8 years ago. non-strict foldl, INLINE foldl PEEL 1 (+SAT) prevents stackoverflow

Download all attachments as: .zip