[GHC] #2289: Needless reboxing of values when returning from a tight loop

GHC ghc-devs at haskell.org
Sun Feb 21 01:02:28 UTC 2016


#2289: Needless reboxing of values when returning from a tight loop
-------------------------------------+-------------------------------------
        Reporter:  dons              |                Owner:
            Type:  bug               |               Status:  new
        Priority:  lowest            |            Milestone:
       Component:  Compiler          |              Version:  6.8.2
      Resolution:                    |             Keywords:  boxing,
                                     |  loops, performance
Operating System:  Unknown/Multiple  |         Architecture:
 Type of failure:  Runtime           |  Unknown/Multiple
  performance bug                    |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:  #2387,#1600       |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by twhitehead):

 Thanks for feedback.  I follow that `loop2` in itself is not strict in the
 accumulators `au` and `ad`.  It would seem GHC considers the context,
 however, as it did go ahead and create a version strict in `au` and `ad`
 (i.e., `main_$s$wloop2` is clearly specialized to take `au` and `ad` as
 unboxed `Int#`s).

 {{{
 #!haskell
 main_$s$wloop2 [Occ=LoopBreaker]
   :: Int# -> Int# -> Int# -> (# Int, Int #)
 }}}

 Possibly the only issue left here is indeed the nested CPR then?  At least
 it is all I can see really different from this single-return-value variant
 in which GHC wonderfully eliminates all boxing and unboxing.

 {{{
 #!haskell
 main :: IO ()
 main = case loop1 100 10 of a -> print a

 loop1 :: Int -> Int -> Int
 loop1 n a | n > 0     = loop1 (n-1) (-a)
           | otherwise = a
 }}}

 {{{
 #!haskell
 Rec {
 $wloop1 :: Int# -> Int# -> Int#
 $wloop1 =
   \ (ww_s3th :: Int#) (ww1_s3tl :: Int#) ->
     case tagToEnum# (># ww_s3th 0) of _ {
       False -> ww1_s3tl;
       True -> $wloop1 (-# ww_s3th 1) (negateInt# ww1_s3tl)
     }
 end Rec }
 }}}

 I'm also not sure I follow you on the only-one-specialization rule.  From
 looking at core dumps it seems GHC does do multiple specializations.  For
 example,

 1. adding an export of `loop2` causes a purely non-strict version to be
 generated and
 2. adding a `case loop2 100 (10,undefined) of (au,_) -> ...` causes a
 strict-only-in-the-first-argument version to be generated

 all in the same code and in addition to `main_$s$wloop2` above.  Perhaps
 things have been relaxed?

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


More information about the ghc-tickets mailing list