[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