[GHC] #7865: SpecConstr duplicating computations

GHC cvs-ghc at haskell.org
Fri Apr 26 03:59:41 CEST 2013


#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



More information about the ghc-tickets mailing list