
#14816: Missed Called Arity opportunity? -------------------------------------+------------------------------------- Reporter: dfeuer | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: 8.6.1 Component: Compiler | Version: 8.2.2 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Runtime | Unknown/Multiple performance bug | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by sgraf): Hey, it seems I'm lucky I subscribed to ghc-ticket just yesterday :) I investigated a little. So, it turns out that Demand Analysis doesn't recognize `insertModifyingArr`s argument `f` to be called once (has usage `C(U(U)`). That's really weird, actually the analysis should be able to figure that out. The fact that `-ddump-stranal` doesn't mention `f` in the demand type as a free variable to `go` makes me feel like there is some conservative approximation at play here. And in fact, I believe that's how fix-pointing works for functions in DmdAnal: Completely forget about free variables and assume the most pessimistic result. You can circumvent that if you make `f` an argument to `go` (reverse static arg transform, essentially): {{{ insertModifyingArr :: Int -> (a -> (# a #)) -> STArray s Int a -> ST s (STArray s Int a) insertModifyingArr i0 f arr0 = do rng <- range <$> getBounds arr0 go f i0 rng arr0 where go f i [] arr = pure arr go f i (k : ks) arr | i == k = do old <- readArray arr i case f old of (# new #) -> writeArray arr i new return arr | otherwise = go f i ks arr }}} This makes DmdAnal propagate the usage information to the top-level: The demand signature for `inserModifyingArr` mentions `f` with usage `1*C1(U(U))`, which in theory should be enough information for the simplifier to eta-expand the `blink` expression. And sure enough, it does (somewhere inside `test`: {{{ Fish.insertModifyingArr_$spoly_go @ a_a3IX @ s_a3IY w_s4pP ww6_s4s2 ww8_s4s5 ww3_s4q2 ww4_s4q3 (GHC.Enum.eftInt ww6_s4s2 ww8_s4s5) k_a15T (\ (a2_a15S [OS=OneShot] :: a_a3IX) -> (# f_a15V a1_a15U a2_a15S #)) }}} The interactions between free vars and static args are a little counter- intuitive, I suppose... -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/14816#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler