[GHC] #13966: Skip-less stream fusion

GHC ghc-devs at haskell.org
Sun Jul 16 15:59:38 UTC 2017


#13966: Skip-less stream fusion
-------------------------------------+-------------------------------------
        Reporter:  jmspiewak         |                Owner:  (none)
            Type:  feature request   |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              Version:  8.2.1-rc3
      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 jmspiewak):

 I conducted more tests - it's not about the typeclass. Somehow putting the
 filter predicate in stream state allows fusion to happen. Is it changing
 the order of inlining? Prevents some other optimization which was
 clobbering the fusion opportunity?

 {{{#!hs
 filter5 :: (a -> Bool) -> Stream1 a -> Stream1 a
 filter5 predicate (Stream1 s0 next) = Stream1 (Filter3 predicate s0) f
 where
   f (Filter3 p s1) = loop s1 where
     loop s = case next s of
       Done1 -> Done1
       Yield1 s' x
         | p x       -> Yield1 (Filter3 p s') x
         | otherwise -> loop s'

 {-# NOINLINE chain5 #-}
 chain5 :: Int -> Int
 chain5 = sum1 . filter5 even . enumFromTo1 1
 }}}

 Compiles to:

 {{{
 -- RHS size: {terms: 36, types: 12, coercions: 0, joins: 2/2}
 Main.$wchain5 [InlPrag=NOINLINE] :: Int# -> Int#
 [GblId, Arity=1, Caf=NoCafRefs, Str=<S,U>]
 Main.$wchain5
   = \ (ww_s9EU :: Int#) ->
       joinrec {
         $s$wloop_s9QI [Occ=LoopBreaker] :: Int# -> Int# -> Int#
         [LclId[JoinId(2)], Arity=2, Str=<S,U><S,U>, Unf=OtherCon []]
         $s$wloop_s9QI (sc_s9QH :: Int#) (sc1_s9QG :: Int#)
           = joinrec {
               $wloop2_s9EA [InlPrag=[0], Occ=LoopBreaker] :: Int# -> Int#
               [LclId[JoinId(1)], Arity=1, Str=<S,U>, Unf=OtherCon []]
               $wloop2_s9EA (ww1_s9Ey :: Int#)
                 = case tagToEnum# @ Bool (># ww1_s9Ey ww_s9EU) of {
                     False ->
                       case remInt# ww1_s9Ey 2# of {
                         __DEFAULT -> jump $wloop2_s9EA (+# ww1_s9Ey 1#);
                         0# -> jump $s$wloop_s9QI (+# ww1_s9Ey 1#) (+#
 sc1_s9QG ww1_s9Ey)
                       };
                     True -> sc1_s9QG
                   }; } in
             jump $wloop2_s9EA sc_s9QH; } in
       jump $s$wloop_s9QI 1# 0#
 }}}

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


More information about the ghc-tickets mailing list