[GHC] #14827: Recognize when inlining would create a join point

GHC ghc-devs at haskell.org
Wed Feb 21 01:48:21 UTC 2018


#14827: Recognize when inlining would create a join point
-------------------------------------+-------------------------------------
        Reporter:  ersetzen          |                Owner:  (none)
            Type:  feature request   |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              Version:  8.2.2
      Resolution:                    |             Keywords:  JoinPoints
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 ersetzen):

 Turns out there was an issue that's really easy to miss with liberate-case
 turned on:

 {{{
 useSite :: Int -> Int
 useSite i = 10 * (delayedInline i)

 delayedInline :: Int -> Int
 delayedInline i = inline i
 {-# INLINE [1] delayedInline #-}

 inline :: Int -> Int
 inline nlen = loop 0
   where
     shouldFloat i
       | i > 100  = i
       | otherwise = shouldFloat (i+1)
     loop i
         | i > 5 = 0
         | otherwise = loop (i + skip)
         where !skip = shouldFloat nlen
 {-# INLINE inline #-}
 }}}

 First inline is optimized as expected and shouldFloat is floated out. Then
 delayedInline is inlined with the original code and in that copy
 shouldFloat remains in loop:

 {{{
 -- RHS size: {terms: 24, types: 9, coercions: 0, joins: 1/1}
 inline
 inline
   = \ nlen_a1u2 ->
       case nlen_a1u2 of { I# ww_s31T ->
       case $wshouldFloat_s31Y ww_s31T of ww_s31X { __DEFAULT ->
       joinrec {
         $wloop_s328
         $wloop_s328 ww_s326
           = case tagToEnum# (># ww_s326 5#) of {
               False -> jump $wloop_s328 (+# ww_s326 ww_s31X);
               True -> lvl_s2ZH
             }; } in
       jump $wloop_s328 0#
       }
       }

 -- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
 delayedInline
 delayedInline = inline

 -- RHS size: {terms: 37, types: 14, coercions: 0, joins: 2/3}
 useSite
 useSite
   = \ w_s32l ->
       case w_s32l of { I# ww_s32o ->
       joinrec {
         $wloop_s32k
         $wloop_s32k ww_s32i
           = let {
               lvl_s33v
               lvl_s33v = tagToEnum# (># ww_s32i 5#) } in
             joinrec {
               $wshouldFloat_s32e
               $wshouldFloat_s32e ww_s32c
                 = case tagToEnum# (># ww_s32c 100#) of {
                     False -> jump $wshouldFloat_s32e (+# ww_s32c 1#);
                     True ->
                       case lvl_s33v of {
                         False -> jump $wloop_s32k (+# ww_s32i ww_s32c);
                         True -> lvl_s2ZH
                       }
                   }; } in
             jump $wshouldFloat_s32e ww_s32o; } in
       jump $wloop_s32k 0#
       }

 }}}

 Branch and Head ghci run with 1x performance for me i.e. bad.

-- 
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14827#comment:9>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list