[GHC] #14375: Implement with# primop

GHC ghc-devs at haskell.org
Fri Oct 20 09:45:39 UTC 2017


#14375: Implement with# primop
-------------------------------------+-------------------------------------
        Reporter:  simonpj           |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              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:  #14346            |  Differential Rev(s):  ​Phab:D4110
       Wiki Page:                    |
-------------------------------------+-------------------------------------
Changes (by simonpj):

 * related:   => #14346


Comment:

 In Phab:D4110 Simon M says

 > The one downside of this is that we have to build a function closure to
 pass to with#, which entails more allocation than we were doing
 previously. But there's an alternative approach that would avoid this:
 expand with# during CoreToStg (or CorePrep perhaps) into the original case
 expression + touch#. There should be no extra allocation, no new primops
 needed, all it does is prevent the simplifier from eliminating the
 continuation.

 That's a good point.  We implement `runST` in this way too.

 But that seems very ad hoc.  I've realised that we have quite a bunch of
 primops that take continuations.  For example
 {{{
 maskAsyncExceptions# :: (State# RealWorld -> (# State# RealWorld, a #))
                      -> (State# RealWorld -> (# State# RealWorld, a #))
 }}}
 We don't really want to allocate a continuation here, only to immediately
 enter it.  But in fact we do!

 I've also realised that it's quite easy to avoid:

 * When converting to STG, instead of insisting that the argument to
 `maskAsyncExceptions#` is a variable, insiste that it is a lambda `(\s.e)`

 * When doing code-gen for `maskAsyncExceptions# (\s.e) s2`, emit the mask
 code (as now) and continue code-gen for `e`.

 That would mean altering STG a bit to allow non-variable arguments.

 An alternative would be to convert `maskAsyncExceptions# e s` to this STG:
 {{{
 join j s = e
 in maskAsyncExceptions# j s
 }}}
 This isn't quite as good because it flushes the live variables of `e` to
 the stack, and then takes a jump to it (the latter will be elminated in
 Cmm land); but it's much better than what we do now.   NB: this would not
 be valid Core because `j` is not saturated; but here it's just an
 intermediate step in codegen.

 Moreover, we don't want to make it ''too'' much like join points; in
 particular not in the simplifier.  For example
 {{{
   case (maskAsyncExceptions# (\s. e) s2) of
      (# s3, r #) -> blah

 ----> ????

   maskAsyncExceptions (\s. case e of (# s3, r #) -> blah) s2
 }}}
 Probably not!  Because that would broaden the scope of the mask.  But it's
 fine to treat it in a very join-point-like way at codegen time.

 We can apply similar thinking to `catch#`.
 {{{
 catch# :: (State# RealWorld -> (# State# RealWorld, a #) )
        -> (b -> State# RealWorld -> (# State# RealWorld, a #) )
        -> State# RealWorld
        -> (# State# RealWorld, a #)
 }}}
 Here we allocate two continuations. But we'd really prefer to allocate
 none!  Just push a catch frame (which we do anyway).

 Perhaps we can generate this STG:
 {{{
 join jnormal s = e1 s
 in join jexception b s = e2 b s
 in catch# jnormal jexception s
 }}}
 Again we compile those join point just as we normally do (live variables
 on the stack),
 so that invoking one is just "adjust SP and jump".  Again this would not
 be valid Core,
 just a codegen intermediate.

 I like this.

 Conclusion: let's not do any special codegen stuff for `with#` until we've
 worked this out.

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


More information about the ghc-tickets mailing list