[GHC] #11778: Preserve demandInfo on lambda binders in the simpifier

GHC ghc-devs at haskell.org
Thu Mar 31 09:28:40 UTC 2016


#11778: Preserve demandInfo on lambda binders in the simpifier
-------------------------------------+-------------------------------------
           Reporter:  nomeata        |             Owner:
               Type:  task           |            Status:  new
           Priority:  normal         |         Milestone:
          Component:  Compiler       |           Version:  8.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:
-------------------------------------+-------------------------------------
 In ticket:11731#comment:30, simonpj writes:

 > Meanwhile, there is a separate issue in ticket:11731#comment:20.  It
 seems that for any un-saturated lambda, we nuke (a) the `occInfo` on the
 binders (fair enough; the next run of the occurrence analyser will
 regenerate it), and (b) the `demandInfo` on the binders.  The reasoning is
 explained in comment:20.
 >
 > But (b) is permanent; it won't be re-generated until the next run of the
 demand analyser.  And, worse, it applies to function definitions
 > {{{
 > f = \xy . x+y
 > }}}
 > Here `x` and `y` will be marked as strictly demanded, but that info will
 get stripped after the first run of the simplifier. Try it on
 > {{{
 > f :: [Int] -> [Int] -> Int
 > f x y = head x + head y
 > }}}
 > After the demand analyser we have
 > {{{
 > f = \ (x_amY [Dmd=<S,1*U>] :: [Int]) (y_amZ [Dmd=<S,1*U>] :: [Int]) ->
 ...
 > }}}
 > but after the first run of the simplifier we get
 > {{{
 > f = \ (x_amY :: [Int]) (y_amZ :: [Int]) -> ...
 > }}}
 > (`f` itself still has a strictness signature that says it is strict in
 both args.)
 >
 > Does this matter?  Well, the main reason is that if `f` is inlined, we'd
 like to get a strict `let`.  And now we won't.
 >
 > Happily I think it is easily fixed.  The key thing is that when doing
 beta-reduction, which effectively does `(\x.e) b` into `let x=b in e`, we
 must kill off x's demand/occurrence info if the lambda is not saturated.
 >
 > So, idea, in `Simplify.hs`:
 >
 >  * Give an extra `Bool` to `simplLam` indictating "saturated".
 >
 >  * Compute (value) saturation in the `simplExprF1 env expr@(Lam {})
 cont`, before calling `simpLam`, but do no zapping.
 >
 >  * In `simplLam`, in the beta-reduction case,
 > {{{
 > simplLam env (bndr:bndrs) body (ApplyToVal { sc_arg = arg, sc_env =
 arg_se
 >                                            , sc_cont = cont })
 >   = do  { tick (BetaReduction bndr)
 >         ; simplNonRecE env' (zap_unfolding bndr) (arg, arg_se) (bndrs,
 body) cont }
 > }}}
 >   do the binder-zapping right there, if "saturated" is not true.  (That
 neatly puts it with the unfolding-zapping code.)
 >
 > Now the non-beta-reduced lambdas won't be zapped, which is right.
 >
 > Would you like to try that?

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


More information about the ghc-tickets mailing list