Skip to content

Compiler is unable to INLINE as well as the programmer can manually

The test case is in this repo on the inlining-issue branch: https://github.com/harendra-kumar/ghc-perf/tree/inlining-issue.

Performance with manually inlining a function is more than 10% faster compared to factoring out code and using INLINE pragma.

stack bench for compiler inlined code

time                 46.71 ms   (45.53 ms .. 47.79 ms)

stack bench --flag ghc-perf:manual for manually inlined code

time                 39.46 ms   (38.92 ms .. 39.94 ms)

Here is the relevant code:

{-# INLINE bindWith #-}
bindWith
    :: (forall c. AsyncT m c -> AsyncT m c -> AsyncT m c)
    -> AsyncT m a
    -> (a -> AsyncT m b)
    -> AsyncT m b
bindWith k (AsyncT m) f = AsyncT $ \_ stp yld ->
    let run x = (runAsyncT x) Nothing stp yld
        yield a _ Nothing  = run $ f a
        yield a _ (Just r) = run $ f a `k` (bindWith k r f)
    in m Nothing stp yield

instance Monad m => Monad (AsyncT m) where
    return a = AsyncT $ \ctx _ yld -> yld a ctx Nothing

#ifdef MANUAL_INLINE
    AsyncT m >>= f = AsyncT $ \_ stp yld ->
        let run x = (runAsyncT x) Nothing stp yld
            yield a _ Nothing  = run $ f a
            yield a _ (Just r) = run $ f a <> (r >>= f)
        in m Nothing stp yield
#else
    (>>=) = bindWith (<>)
#endif

I have seen this many times.

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