[GHC] #13286: Late floating of join points
GHC
ghc-devs at haskell.org
Thu Feb 16 11:28:25 UTC 2017
#13286: Late floating of join points
-------------------------------------+-------------------------------------
Reporter: simonpj | Owner: (none)
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 8.0.1
Keywords: JoinPoints | Operating System: Unknown/Multiple
Architecture: | Type of failure: None/Unknown
Unknown/Multiple |
Test Case: | Blocked By:
Blocking: | Related Tickets:
Differential Rev(s): | Wiki Page:
-------------------------------------+-------------------------------------
Consider this, from `GHC.Real`:
{{{
GHC.Real.$w$s^1 [InlPrag=[0]] :: Int -> Int# -> Int#
GHC.Real.$w$s^1 =
\ (w_s6xh :: Int) (ww_s6xl :: Int#) ->
case tagToEnum# @ Bool (<# ww_s6xl 0#) of {
False ->
case ww_s6xl of wild1_XdK {
__DEFAULT ->
case w_s6xh of { I# ww2_s6xa ->
joinrec {
$wf_s6xg [InlPrag=[0], Occ=LoopBreaker] :: Int# -> Int# ->
Int#
[LclId[JoinId(2)], Arity=2, Str=<S,U><S,U>, Unf=OtherCon []]
$wf_s6xg (ww3_X6Hi :: Int#) (ww4_s6xe :: Int#) =
case remInt# ww4_s6xe 2# of {
__DEFAULT ->
case ww4_s6xe of wild3_Xe3 {
__DEFAULT ->
joinrec {
$wg_s6x5 [InlPrag=[0], Occ=LoopBreaker]
:: Int# -> Int# -> Int# -> Int#
[LclId[JoinId(3)], Arity=3, Str=<S,U><S,U><S,U>,
Unf=OtherCon []]
$wg_s6x5 (ww5_s6wV :: Int#) (ww6_s6wZ :: Int#)
(ww7_s6x3 :: Int#) =
case remInt# ww6_s6wZ 2# of {
__DEFAULT ->
case ww6_s6wZ of wild5_Xen {
__DEFAULT ->
jump $wg_s6x5
(*# ww5_s6wV ww5_s6wV)
(quotInt# (-# wild5_Xen 1#) 2#)
(*# ww5_s6wV ww7_s6x3);
1# -> *# ww5_s6wV ww7_s6x3
};
0# ->
jump $wg_s6x5
(*# ww5_s6wV ww5_s6wV) (quotInt#
ww6_s6wZ 2#) ww7_s6x3
}; } in
jump $wg_s6x5
(*# ww3_X6Hi ww3_X6Hi) (quotInt# (-# wild3_Xe3
1#) 2#) ww3_X6Hi;
1# -> ww3_X6Hi
};
0# -> jump $wf_s6xg (*# ww3_X6Hi ww3_X6Hi) (quotInt#
ww4_s6xe 2#)
}; } in
jump $wf_s6xg ww2_s6xa wild1_XdK
};
0# -> 1#
};
True -> case GHC.Real.^2 of wild1_00 { }
}
}}}
Note those two `joinrecs`. Neither has any free variables. So we could
float them to
top level, as ordinary functions, thus
{{{
$wg_s6x5 [InlPrag=[0], Occ=LoopBreaker]
:: Int# -> Int# -> Int# -> Int#
$wg_s6x5 (ww5_s6wV :: Int#) (ww6_s6wZ :: Int#) (ww7_s6x3 :: Int#) =
case remInt# ww6_s6wZ 2# of {
__DEFAULT ->
case ww6_s6wZ of wild5_Xen {
__DEFAULT ->
jump $wg_s6x5
(*# ww5_s6wV ww5_s6wV)
(quotInt# (-# wild5_Xen 1#) 2#)
(*# ww5_s6wV ww7_s6x3);
1# -> *# ww5_s6wV ww7_s6x3
};
0# ->
$wg_s6x5 (*# ww5_s6wV ww5_s6wV) (quotInt# ww6_s6wZ 2#) ww7_s6x3
$wf_s6xg [InlPrag=[0], Occ=LoopBreaker] :: Int# -> Int# -> Int#
$wf_s6xg (ww3_X6Hi :: Int#) (ww4_s6xe :: Int#) =
case remInt# ww4_s6xe 2# of {
__DEFAULT ->
case ww4_s6xe of wild3_Xe3 {
__DEFAULT ->
$wg_s6x5
(*# ww3_X6Hi ww3_X6Hi) (quotInt# (-# wild3_Xe3 1#) 2#)
ww3_X6Hi;
1# -> ww3_X6Hi
};
0# -> $wf_s6xg (*# ww3_X6Hi ww3_X6Hi) (quotInt# ww4_s6xe 2#)
GHC.Real.$w$s^1 [InlPrag=[0]] :: Int -> Int# -> Int#
GHC.Real.$w$s^1 =
\ (w_s6xh :: Int) (ww_s6xl :: Int#) ->
case tagToEnum# @ Bool (<# ww_s6xl 0#) of {
False ->
case ww_s6xl of wild1_XdK {
__DEFAULT ->
case w_s6xh of { I# ww2_s6xa -> $wf_s6xg ww2_s6xa wild1_XdK
};
0# -> 1#
};
True -> case GHC.Real.^2 of wild1_00 { }
}
}}}
Is this better?
* Better before: the nested join points don't allocate a closure; but the
top-level defns do build a (never used) closure and slow entry point.
* Better after: the externally-visible function might inline more at call
sites in other modules.
So it's a bit moot. It has something of the flavour of the late lambda-
lifting pass.
For now I'm doing nothing; just recording the observation. The simple
thing is not to float.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13286>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list