#11731: Simplifier: Inlining trivial let can lose sharing -------------------------------------+------------------------------------- Reporter: nomeata | Owner: Type: bug | Status: patch Priority: normal | Milestone: Component: Compiler | Version: 8.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D2064 Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): Meanwhile, there is a separate issue in 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/11731#comment:30> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler