[GHC] #14387: listToMaybe doesn't participate in foldr/build fusion

GHC ghc-devs at haskell.org
Wed Oct 25 11:33:15 UTC 2017


#14387: listToMaybe doesn't participate in foldr/build fusion
-------------------------------------+-------------------------------------
        Reporter:  duog              |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Core Libraries    |              Version:  8.2.1
      Resolution:                    |             Keywords:
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):

 > findIndex{2,4,5} get join points and findIndex{"",3} don't.

 Actually `findIndex3` does get a join point:
 {{{
 FindIndex.findIndex3
   = \ (@ a_a1kV)
       (p_s2Z2 [Occ=OnceL!] :: a_a1kV -> GHC.Types.Bool)
       (eta_s2Z3 [Occ=Once] :: [a_a1kV]) ->
       case GHC.List.zip
              @ GHC.Types.Int @ a_a1kV FindIndex.findIndex1 eta_s2Z3
       of sat_s2Zd
       { __DEFAULT ->
       joinrec {
         go_s2Z4 [Occ=LoopBreakerT[1]]
           :: [(GHC.Types.Int, a_a1kV)] -> GHC.Base.Maybe GHC.Types.Int
         [LclId[JoinId(1)], Arity=1, Str=<S,1*U>, Unf=OtherCon []]
         go_s2Z4 (ds_s2Z5 [Occ=Once!] :: [(GHC.Types.Int, a_a1kV)])
           = case ds_s2Z5 of {
               [] -> GHC.Base.Nothing @ GHC.Types.Int;
               : ds1_s2Z7 [Occ=Once!] xs_s2Z8 [Occ=Once] ->
                 case ds1_s2Z7 of { (i_s2Za [Occ=Once], x_s2Zb [Occ=Once])
 ->
                 case p_s2Z2 x_s2Zb of {
                   GHC.Types.False -> jump go_s2Z4 xs_s2Z8;
                   GHC.Types.True -> GHC.Base.Just @ GHC.Types.Int i_s2Za
                 }
                 }
             }; } in
       jump go_s2Z4 sat_s2Zd
       }
 }}}
 Note the join point.  But `findIndex4` and `findIndex` do not.  Maybe that
 was a typo.

 > Having a join point means constant stack space, not having a join point
 means linear stack space.

 This definitely isn't true.  Here's `findIndex` (the one that does not get
 a join point):
 {{{
 findIndex
   = \ (@ a_a1IQ) (p_a1eN :: a_a1IQ -> Bool) (x_a1Ld :: [a_a1IQ]) ->
       letrec {
         go_a1KZ [Occ=LoopBreaker] :: [a_a1IQ] -> Int# -> [Int]
         [LclId, Arity=2, Str=<S,1*U><L,U>, Unf=OtherCon []]
         go_a1KZ
           = \ (ds_a1L0 :: [a_a1IQ]) (eta_B1 :: Int#) ->
               case ds_a1L0 of {
                 [] -> GHC.Types.[] @ Int;
                 : y_a1L5 ys_a1L6 ->
                   case p_a1eN y_a1L5 of {
                     False -> go_a1KZ ys_a1L6 (+# eta_B1 1#);
                     True ->
                       GHC.Types.:
                         @ Int (GHC.Types.I# eta_B1) (go_a1KZ ys_a1L6 (+#
 eta_B1 1#))
                   }
               }; } in
       case go_a1KZ x_a1Ld 0# of {
         [] -> GHC.Base.Nothing @ Int;
         : a1_aX7 ds_d1KM -> GHC.Base.Just @ Int a1_aX7
       }
 }}}
 In the `False` branch inside `go`, there's a tail-call to `go` (no stack
 growth). In the `True` branch, `go` returns a cons-cell, and stops.  Then
 the `case go x o# of ...` scrutinises that cons cell and returns a `Just`.
 All done. No stack growth in either case.

 Why does `listToMaybe'` work (slightly) better?  Because it can perform
 foldr/build fusion with the list producer.

 > it seems that changing the definition of listToMaybe to use `foldr`
 would be a win

 Yes I agree.  It's a bit like making `map` use `foldr` rather than being
 written directly.  But you'd need an INLINE pragma on it.

 I can't see a downside.  If it doesn't fuse you get the original
 `listToMaybe` back instead.   If someone makes that change (in `base`) do
 add a Note to explain.

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


More information about the ghc-tickets mailing list