[GHC] #12620: Allow the user to prevent floating and CSE

GHC ghc-devs at haskell.org
Sat Sep 24 23:28:27 UTC 2016


#12620: Allow the user to prevent floating and CSE
-------------------------------------+-------------------------------------
           Reporter:  nomeata        |             Owner:
               Type:  feature        |            Status:  new
  request                            |
           Priority:  normal         |         Milestone:
          Component:  Compiler       |           Version:  8.0.1
           Keywords:                 |  Operating System:  Unknown/Multiple
       Architecture:                 |   Type of failure:  None/Unknown
  Unknown/Multiple                   |
          Test Case:                 |        Blocked By:
           Blocking:                 |   Related Tickets:
Differential Rev(s):                 |         Wiki Page:
-------------------------------------+-------------------------------------
 This is a write-up of a rough idea that Andres Löw and me had at ICFP 2016
 in order to address some Real World problems Andres noticed and that are
 currently hard to avoid.

 The goal is to give the user more control about expressions that the
 compiler would like to float out (or CSE), but the programmer knows
 better. Example (assume no list fusion exists):

 {{{
 enum xs = zip [1..] xs
 }}}

 This leads to a horrible space leak, as GHC will float out `[1..]` to the
 top.

 Our idea is to have a magic function `nofloat :: a -> a` (magic in the
 same sense as `inline` and `lazy`) that the programmer would use here:

 {{{
 enum xs = zip (nofloat [1..]) xs
 }}}

 With these effects:

  * Sub expressions are not floated out of a `nofloat`.
  * An expression of the form `nofloat e` would not be floated beyond the
 innermost enclosing lambda.
  * Two expressions of the form `nofloat e` would not be commoned up by
 CSE.

 This way, unwanted sharing is prevented.

 In contrast to a hypothetical `veryCheap` function, it does ''not'' mean
 that the compiler should float it into lambda (no unwanted duplication
 either).

 Two open questions (among many others, I am sure:)

  * Likely, rule matching should look through `nofloat`. At least in this
 example (and similar ones like `map (nofloat [1..])`, the rules in
 question will avoid the spaceleaks).

  *  Possibly, nothing should be floated (inlined) ''into'' a `nofloat`.
 Rationale: Assume the library is changed so that
   {{{
   [n..] = nofloat (realEnumFrom n)
   {-# INLINE [n..] #-}
   }}}
   Then `zip [fib 1000..]` would be rewritten by the inliner to `zip (let x
 = fib 1000 in (nofloat [x..]))`. Moving the `fib 1000` into the `nofloat`
 would change the behaviour in a possibly surprising way.

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


More information about the ghc-tickets mailing list