[GHC] #1600: Optimisation: CPR the results of IO

GHC ghc-devs at haskell.org
Mon Feb 27 05:44:28 UTC 2017


#1600: Optimisation: CPR the results of IO
-------------------------------------+-------------------------------------
        Reporter:  simonmar          |                Owner:  (none)
            Type:  task              |               Status:  new
        Priority:  lowest            |            Milestone:
       Component:  Compiler          |              Version:  6.6.1
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
 Type of failure:  Runtime           |  Unknown/Multiple
  performance bug                    |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:  #8598             |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by akio):

 > There are two changes in that commit:

 Actually the only change is the latter one. The former change is already
 in HEAD, as of 2be364ac8c.

 > Making data con wrapper have ug_boring_ok = boringCxtOk. I'm not sure I
 buy this in full. In Note [Inline data constructor wrappers aggresively]
 there's a claim that we get better nested-CPR info.

 I don't think the improvement has anything to do with nested CPR, because
 I'm testing this change in isolation, without any other changes from the
 nested CPR branch.

 The big difference in nofib comes from the `GHC.Integer.Types` module in
 `integer-gmp`. This module has this definition:

 {{{#!hs
 data Integer  = S#                !Int#
                 -- ^ iff value in @[minBound::'Int', maxBound::'Int']@
 range
               | Jp# {-# UNPACK #-} !BigNat
                 -- ^ iff value in @]maxBound::'Int', +inf[@ range
               | Jn# {-# UNPACK #-} !BigNat
                 -- ^ iff value in @]-inf, minBound::'Int'[@ range
 }}}

 Note the redundant bang in the `S#` constructor. This causes a wrapper for
 this constructor to be created:

 {{{#!hs
 GHC.Integer.Type.$WS# =
   \ (dt [Occ=Once] :: Int#) ->
     case dt of dt { __DEFAULT -> GHC.Integer.Type.S# dt }
 }}}

 And this wrapper remains un-inlined in various places like:

 {{{#!hs
 quotRemInteger =
   \ (n :: Integer) (ds :: Integer) ->
     join {
       fail1 [Dmd=<L,1*C1(U(U,U))>] :: Void# -> (# Integer, Integer #)
       [LclId[JoinId(1)], Arity=1, Str=<L,A>, Unf=OtherCon []]
       fail1 _ [Occ=Dead, OS=OneShot] =
         case n of n1 { __DEFAULT ->
         join {
           fail2 [Dmd=<L,1*C1(U(U,U))>] :: Void# -> (# Integer, Integer #)
           [LclId[JoinId(1)], Arity=1, Str=<L,A>, Unf=OtherCon []]
           fail2 _ [Occ=Dead, OS=OneShot] =
             case n1 of wild {
               S# ds3 ->
                 case ds3 of ds4 {
                   __DEFAULT ->
                     case ds of {
                       S# d# ->
                         case quotRemInt# ds4 d# of { (# ipv, ipv1 #) ->
                         (# GHC.Integer.Type.$WS# ipv,
 GHC.Integer.Type.$WS# ipv1 #)
 ...
 }}}

 leading to unnecessary allocation of thunks. It should be possible to fix
 this problem by doing one of the following:

 1. Inline constructor wrappers like `$WS#` aggressively, at least when
 it's fully applied.
 2. Do not create a redundant wrapper in a case like this.
 3. Remove this particular bang from integer-gmp.

 I have tried (1) and (3), and they seem to have very similar effects. (3)
 is definitely the easiest to implement, but I wonder if (2) is more
 correct. I'd like to hear some suggestions about this.

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


More information about the ghc-tickets mailing list