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
  • #18374
Closed
Open
Created Jun 22, 2020 by Ben Gamari@bgamari🐢Maintainer

GHC doesn't inline small type class method marked as INLINE with profiling enabled

Originally opened by @arybczak

Summary

When profiling is enabled, GHC doesn't inline small type class methods which prevents further optimizations and specialization from happening.

Steps to reproduce

When the following module:

module Main where

import Optics.Core

data T = T { _t1 :: Int
           , _t2 :: Int
           }

t1 :: Lens' T Int
t1 = lensVL $ \f s -> (\n -> s { _t1 = n}) <$> f (_t1 s)
{-# INLINE t1 #-}

t2 :: Lens' T Int
t2 = lensVL $ \f s -> (\n -> s { _t2 = n}) <$> f (_t2 s)
{-# INLINE t2 #-}

t_val :: T
t_val = T 1 2
{-# NOINLINE t_val #-}

main :: IO ()
main = putStrLn . show $ view t1 t_val + view t2 t_val

is compiled with profiling enabled, here's how core of main looks:

main1
  = case ((($fStrongForget_$clinear main_l1) (id `cast` <Co:41>))
          `cast` <Co:42>)
           t_val
    of
    { I# x_a2c8 ->
    case ((($fStrongForget_$clinear main_l2) (id `cast` <Co:41>))
          `cast` <Co:42>)
           t_val
    of
    { I# y_a2cb ->
    case $wshowSignedInt 0# (+# x_a2c8 y_a2cb) [] of
    { (# ww5_a277, ww6_a278 #) ->
    : ww5_a277 ww6_a278
    }
    }
    }

So linear doesn't get inlined even though it's a small function that is even explicitly marked INLINE.

This prevents further optimizations from happening and leaves optics-related code in semi-optimized state, making looking at cost centers unreliable (see well-typed/optics#324).

When profiling is disabled, everything inlines and optimizes away as expected:

main1 
  = case t_val of { T ds_d25F ds1_d25G ->
    case ds_d25F of { I# x_a2c7 ->
    case ds1_d25G of { I# y_a2ca ->
    case $wshowSignedInt 0# (+# x_a2c7 y_a2ca) [] of
    { (# ww5_a276, ww6_a277 #) ->
    : ww5_a276 ww6_a277
    }
    }
    }
    }

I'm attaching archive with cabal project that contains above module for easy reproduction: prof_test.tar.gz

Profiling build was tested with profiling: True in cabal.project.local.

Expected behavior

GHC should inline class methods marked as INLINE when profiling is enabled.

Environment

  • GHC version used: 8.10.1

Optional:

  • Operating System: Arch Linux
  • System Architecture: x86_64
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking