[GHC] #7865: SpecConstr duplicating computations

#7865: SpecConstr duplicating computations ------------------------------------+--------------------------------------- Reporter: amosrobinson | Owner: Type: bug | Status: new Priority: normal | Component: Compiler Version: | Keywords: SpecConstr Os: Unknown/Multiple | Architecture: Unknown/Multiple Failure: Runtime performance bug | Blockedby: Blocking: | Related: ------------------------------------+--------------------------------------- In some (very rare) cases, SpecConstr can actually duplicate let bindings. When SpecConstr sees something like {{{ let tuple = (let x = expensive in x, simple) case tuple of (a,b) -> a + a }}} it records the value of tuple, and replaces the case with {{{ (let x = expensive in x) + (let x = expensive in x) }}} Usually we wouldn't notice this, because the Simplifier would let-float expensive out of the tuple before SpecConstr runs. In some cases though, the tuple constructor will only be exposed after specialisation happens. To test, compile TSpecConstr_DoubleInline with {{{ ghc TSpecConstr_DoubleInline.hs -O2 -fspec-constr -dverbose-core2core -fforce-recomp -dppr-case-as-let -dsuppress-all | less }}} and search for the SpecConstr pass. The first specialisation is {{{ $srecursive_sf3 $srecursive_sf3 = \ sc_seR sc_seS sc_seT sc_seU -> let { a'_sep a'_sep = (let { I# x_adP ~ _ <- expensive sc_seR } in I# (*# x_adP 2), sc_seR) } in let { ds_seq ds_seq = recursive (: sc_seR (: sc_seR (: sc_seS sc_seT))) (sc_seR, let { I# x_adP ~ _ <- expensive sc_seR } in I# (*# x_adP 2)) } in (let { (p_XdA, q_Xdu) ~ _ <- ds_seq } in let { I# x_ae7 ~ _ <- p_XdA } in let { I# y_aeb ~ _ <- let { I# x_adP ~ _ <- expensive sc_seR } in I# (*# x_adP 2) } in I# (+# x_ae7 y_aeb), let { (p_adg, q_XdA) ~ _ <- ds_seq } in let { I# x_ae7 ~ _ <- q_XdA } in let { I# y_aeb ~ _ <- sc_seR } in I# (+# x_ae7 y_aeb)) }}} With three calls to expensive. If you look at the -ddump-prep, one of the calls is simplified out, but there is still one too many at the end. This is happening on at least 7.4.1 and head. -- Ticket URL: http://hackage.haskell.org/trac/ghc/ticket/7865 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#7865: SpecConstr duplicating computations ------------------------------------+--------------------------------------- Reporter: amosrobinson | Owner: Type: bug | Status: new Priority: normal | Component: Compiler Version: | Keywords: SpecConstr Os: Unknown/Multiple | Architecture: Unknown/Multiple Failure: Runtime performance bug | Blockedby: Blocking: | Related: ------------------------------------+--------------------------------------- Comment(by amosrobinson): I am not sure how to fix this. It seems that SpecConstr is trying to do the job of the inliner and case of constructor. Could we make SpecConstr ignore these cases and run it multiple times, between each Simplifier pass? Or perhaps call the Simplifier from SpecConstr when this inlining needs to be done? -- Ticket URL: http://hackage.haskell.org/trac/ghc/ticket/7865#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#7865: SpecConstr duplicating computations ------------------------------------+--------------------------------------- Reporter: amosrobinson | Owner: Type: bug | Status: new Priority: normal | Component: Compiler Version: | Keywords: SpecConstr Os: Unknown/Multiple | Architecture: Unknown/Multiple Failure: Runtime performance bug | Blockedby: Blocking: | Related: ------------------------------------+--------------------------------------- Comment(by amosrobinson): Or maybe just let-floating on constructors would fix it? -- Ticket URL: http://hackage.haskell.org/trac/ghc/ticket/7865#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#7865: SpecConstr duplicating computations ---------------------------------+------------------------------------------ Reporter: amosrobinson | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: Keywords: SpecConstr | Os: Unknown/Multiple Architecture: Unknown/Multiple | Failure: Runtime performance bug Difficulty: Unknown | Testcase: Blockedby: | Blocking: Related: | ---------------------------------+------------------------------------------ Changes (by simonpj): * difficulty: => Unknown Comment: Excellent point. `SpecConstr` is (and I'm afraid must) do some on-the-fly simplification, but here is is going too far by duplicating an expensive sub-computation. I've made the on-the-fly inlining less aggressive; and written a long comment about it `Note [Work-free values only in environment]`. Pushing shortly. Thanks for identifying this so clearly. Simon -- Ticket URL: http://hackage.haskell.org/trac/ghc/ticket/7865#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#7865: SpecConstr duplicating computations
---------------------------------+------------------------------------------
Reporter: amosrobinson | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version:
Keywords: SpecConstr | Os: Unknown/Multiple
Architecture: Unknown/Multiple | Failure: Runtime performance bug
Difficulty: Unknown | Testcase:
Blockedby: | Blocking:
Related: |
---------------------------------+------------------------------------------
Comment(by simonpj@…):
commit ed54858977e98a833a5767a9c2d07b05c20e5aff
{{{
Author: Simon Peyton Jones

#7865: SpecConstr duplicating computations ---------------------------------------------+------------------------------ Reporter: amosrobinson | Owner: Type: bug | Status: closed Priority: normal | Milestone: Component: Compiler | Version: Resolution: fixed | Keywords: SpecConstr Os: Unknown/Multiple | Architecture: Unknown/Multiple Failure: Runtime performance bug | Difficulty: Unknown Testcase: simplCore/should_compile/T7865 | Blockedby: Blocking: | Related: ---------------------------------------------+------------------------------ Changes (by simonpj): * status: new => closed * testcase: => simplCore/should_compile/T7865 * resolution: => fixed -- Ticket URL: http://hackage.haskell.org/trac/ghc/ticket/7865#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC