[GHC] #4267: Strictness analyser is to conservative about passing a boxed parameter (was: Missing unboxing in pre-order fold over binary tree)

GHC cvs-ghc at haskell.org
Fri Sep 9 14:20:29 CEST 2011


#4267: Strictness analyser is to conservative about passing a boxed parameter
---------------------------------+------------------------------------------
    Reporter:  tibbe             |        Owner:              
        Type:  bug               |       Status:  new         
    Priority:  normal            |    Milestone:  7.4.1       
   Component:  Compiler          |      Version:  6.13        
    Keywords:                    |     Testcase:              
   Blockedby:                    |   Difficulty:              
          Os:  Unknown/Multiple  |     Blocking:              
Architecture:  Unknown/Multiple  |      Failure:  None/Unknown
---------------------------------+------------------------------------------

Comment(by simonpj):

 I took a little look at this.  As you say, you get the loop
 {{{
 sumTree_go :: Int -> Fold.Tree Int -> Int
 sumTree_go =
   \ (z :: Int) (ds_ddX :: Fold.Tree Int) ->
     case ds_ddX of _ {
       Fold.Leaf -> z;
       Fold.Node a l r ->
         case sumTree_go z l of _ { I# z' ->
         case a of _ { I# a# ->
         sumTree_go (I# (+# z' a#)) r
         } } }
 }}}
 Notice that this loop is ''strict'' in z, but does not actually ''unbox''
 z.  The strictness analyser conservatively passes the boxed version under
 such circumstances, to avoid the possiblity of unboxing it, passing it to
 the function, which immediately reboxes it.

 It turns out that adding a "!" to the defn of `go` is enough to fix this:
 {{{
     go z Leaf = z
     go !z (Node a l r)   -- NOTE THE "!"
         = let z'  = go z l
               z'' = f z' a
           in z' `seq` z'' `seq` go z'' r
 }}}
 In fact the `seq`s are redundant because `go` is strict in both args, so
 this gives the same resulting code
 {{{
     go z Leaf = z
     go !z (Node a l r)   -- NOTE THE "!"
         = go (f z' a) (go z l)
 }}}
 The code (in the `sumTree` call) is lovely
 {{{
 T4267.$wgo :: GHC.Prim.Int# -> T4267.Tree GHC.Types.Int -> GHC.Prim.Int#
 T4267.$wgo =
   \ (ww_sps :: GHC.Prim.Int#) (w_spu :: T4267.Tree GHC.Types.Int) ->
     case w_spu of _ {
       T4267.Leaf -> ww_sps;
       T4267.Node ipv_soP ipv1_soQ ipv2_soR ->
         case T4267.$wgo ww_sps ipv1_soQ of ww1_spx { __DEFAULT ->
         case ipv_soP of _ { GHC.Types.I# y_ap5 ->
         T4267.$wgo (GHC.Prim.+# ww1_spx y_ap5) ipv2_soR
         } } }

 }}}
 So that's a workaround.

 Meanwhile I think the strictness analyser should be a bit cleverer, so
 I'll keep the ticket open for that reason.

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/4267#comment:7>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler



More information about the Glasgow-haskell-bugs mailing list