
#13353: foldr/nil rule not applied consistently -------------------------------------+------------------------------------- Reporter: nomeata | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Compile-time | Unknown/Multiple performance bug | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj):
So it seems that after splitting the function into two pieces, it is small enough(?) so that both pieces inline?
Yes that is galling I agree. * Part of the trouble is that strictness analysis does a deep semantic analysis, pulls all the evals to the top, inlines them unconditionally, leaving behind a worker that may now be a lot smaller. The `sizeExpr` code in `CoreUnfold` is necessarily much simpler. * The discount we award for a scrutinised argument is computed in `size_up` here: {{{ alts_size (SizeIs tot tot_disc tot_scrut) -- Size of all alternatives (SizeIs max _ _) -- Size of biggest alternative = SizeIs tot (unitBag (v, 20 + tot - max) `unionBags` tot_disc) tot_scrut }}} For a single-alternative case (and you have a tuple arg here) `tot` = `max`, so there's fixed discount of 20. You could make that into a controllable flag and try varying it. * Idea. If a function ''starts'' with `case x of blah` (even if wrapped in lets) we know that the strictness analyser will find it strict in x. So we know it'll generate a wrapper, and the wrapper will inline. So in the end it'll be as if that case cost nothing at all. It would not be hard to make `sizeExpr` simply count zero for the cost of such cases; including nested. (Certainly for single-alternative ones.) Worth a try? Simon -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13353#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler