[GHC] #13286: Late floating of join points
#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
#13286: Late floating of join points -------------------------------------+------------------------------------- Reporter: simonpj | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: JoinPoints Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): Another example is `simplCore/should_compile/spec-inline.hs`. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13286#comment:1> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13286: Late floating of join points -------------------------------------+------------------------------------- Reporter: simonpj | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: JoinPoints Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): Another: `perf/should_run/MethSharing` improves if you do float to top level. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13286#comment:2> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13286: Late floating of join points -------------------------------------+------------------------------------- Reporter: simonpj | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: JoinPoints Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by David Feuer <David.Feuer@…>): In [changeset:"6eb52cfc2e31df2561860f43d41766464ccfe8af/ghc" 6eb52cfc/ghc]: {{{ #!CommitTicketReference repository="ghc" revision="6eb52cfc2e31df2561860f43d41766464ccfe8af" Improve SetLevels for join points C.f. Trac #13286, #13236 * Never destroy a join point unless it goes to top level See Note [Floating join point bindings] * Never float a MFE if it has a free join variable Note [Free join points] * Stop treating nullary join points specially * Enforce the invariant that le_join_ceil >= le_ctxt_lvl (Needs more thought...) Reviewers: austin, bgamari Subscribers: thomie Differential Revision: https://phabricator.haskell.org/D3199 }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13286#comment:3> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#13286: Late floating of join points -------------------------------------+------------------------------------- Reporter: simonpj | Owner: (none) Type: bug | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: fixed | Keywords: JoinPoints Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by simonpj): * status: new => closed * resolution: => fixed Comment: If you read `Note [Floating join point bindings]` you'll see that in the end I decide that we ''should'' float join point to top level if they can go there. I got better results in a handful of cases (see the Note, and comment:1, comment:2), so it seems like a modest win. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13286#comment:4> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
participants (1)
-
GHC