[GHC] #14223: Casts get in the way of join points

GHC ghc-devs at haskell.org
Tue Sep 12 21:40:36 UTC 2017


#14223: Casts get in the way of join points
-------------------------------------+-------------------------------------
           Reporter:  nomeata        |             Owner:  (none)
               Type:  task           |            Status:  new
           Priority:  normal         |         Milestone:
          Component:  Compiler       |           Version:  8.2.1
           Keywords:  JoinPoints     |  Operating System:  Unknown/Multiple
       Architecture:                 |   Type of failure:  None/Unknown
  Unknown/Multiple                   |
          Test Case:                 |        Blocked By:
           Blocking:                 |   Related Tickets:
Differential Rev(s):                 |         Wiki Page:
-------------------------------------+-------------------------------------
 I was checking which of HLint’s rewirte rules are actually already known
 to the compiler in the sense that the simplifier can do them (using [ghc-
 proofs](http://hackage.haskell.org/package/ghc-proofs). I stumbled on this
 interesting case.

 `foldr @[] (&&) True xs` compiles down to this nice core
 {{{
         joinrec {
           go [Occ=LoopBreaker] :: [Bool] -> Bool
           [LclId[JoinId(1)],
            Arity=1,
            Unf=Unf{Src=<vanilla>, TopLvl=False, Value=True, ConLike=True,
                    WorkFree=True, Expandable=True, Guidance=IF_ARGS [30]
 44 20}]
           go (ds :: [Bool])
             = case ds of {
                 [] -> GHC.Types.True;
                 : y ys ->
                   case y of {
                     False -> GHC.Types.False;
                     True -> jump go ys
                   }
               }; } in
         jump go xs
 }}}


 But `and @[] xs` (which HLint suggests to use instead, and we surely want
 people to use!) compiles down to
 {{{
           go [Occ=LoopBreaker] :: [Bool] -> All
           [LclId,
            Arity=1,
            Unf=Unf{Src=<vanilla>, TopLvl=False, Value=True, ConLike=True,
                    WorkFree=True, Expandable=True, Guidance=IF_ARGS [30]
 60 20}]
           go
             = \ (ds :: [Bool]) ->
                 case ds of {
                   [] ->
                     GHC.Types.True
                     `cast` (Sym Data.Monoid.N:All[0] :: Coercible Bool
 All);
                   : y ys ->
                     case y of {
                       False ->
                         GHC.Types.False
                         `cast` (Nth:3
                                   (Nth:3
                                      ((Sym Data.Monoid.N:All[0]
                                        -> Sym Data.Monoid.N:All[0] ->
 <Bool>_R)
                                       ; (<All>_R -> <All>_R -> Sym
 Data.Monoid.N:All[0])))
                                 :: Coercible Bool All);
                       True -> go ys
                     }
                 }; } in
         (go xs) `cast` (Data.Monoid.N:All[0] :: Coercible All Bool)
 }}}

 If you squint and ignore all the casts, these two expressions are the
 same. So it would be very desirable to get a `joinrec` for `and xs` as
 well.

 Note that all “exit paths” of the return function cast from `Bool` to
 `All`, and the return value of the whole recursion casts back. That looks
 as if some smart floating of coercions could do the job. Maybe the common
 context transformation (https://mail.haskell.org/pipermail/ghc-
 devs/2013-December/003481.html)?

 Is this tied to GHC’s deviation of the paper to have a fixed return type
 for a join point?

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


More information about the ghc-tickets mailing list