Skip to content

GitLab

  • Menu
Projects Groups Snippets
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
  • GHC GHC
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 4,869
    • Issues 4,869
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 456
    • Merge requests 456
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
    • Test Cases
  • Deployments
    • Deployments
    • Releases
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Glasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #7283
Closed
Open
Created Sep 30, 2012 by rl@cse.unsw.edu.au@trac-rl

Specialise INLINE functions

Quick summary: At the moment, INLINE means inline a function if it is fully applied and '''don't use its unfolding** otherwise. I think we might want to change this to INLINE a function if it is fully applied and **treat it as to INLINABLE''' otherwise.

Here is a small example:

module T where

f :: Num a => a -> a
{-# INLINE [1] f #-}
f = \x -> x+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1

g :: Num a => a -> a
{-# INLINE [1] g #-}
g x = x+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2

h :: Num a => a -> a
{-# INLINABLE [1] h #-}
h x = x+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3

apply :: (a -> b) -> a -> b
{-# NOINLINE apply #-}
apply f x = f x
module U where

import T

ff :: Int -> Int -> Int
ff x y = apply f x + apply f y

gg :: Int -> Int -> Int
gg x y = apply g x + apply g y

hh :: Int -> Int -> Int
hh x y = apply h x + apply h y

With -O2 -fno-cse (CSE does optimise this example but doesn't solve the problem of intermediate code bloat), GHC produces the following:

  • The RHS of f is duplicated since it is inlined twice - bad.
  • g is neither inlined nor specialised since it isn't fully applied - bad.
  • h is specialised but its RHS isn't duplicated - good.

But of course, h isn't guaranteed to be inlined even if it is fully applied which, in the real-world examples I have in mind, is bad.

I think INLINE [n] f should mean that:

  1. f will always be inlined if it is fully applied,
  2. f will be specialised when possible,
  3. specialisations of f will also be INLINE [n].

I don't think it's possible to achieve this effect at the moment. If we treated INLINE [n] as INLINABLE [n] until the function is fully applied, we would get exactly this, though, except for 3 which probably isn't too hard to implement.

Now, if I understand correctly, INLINABLE also means that GHC is free to inline the function if it wants but the function isn't treated as cheap. I think it would be fine if we did this for unsaturated INLINE functions rather than not inlining them under any circumstances. The original motivation for only inlining when fully applied was code bloat in DPH. But IIRC that only happened because INLINE functions were always cheap and so GHC was very keen to inline them even when they weren't saturated which wouldn't be the case with my proposal. We would have to check how this affects DPH and related libraries, though.

Trac metadata
Trac field Value
Version 7.7
Type FeatureRequest
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking