[GHC] #14816: Missed Called Arity opportunity?

GHC ghc-devs at haskell.org
Tue Feb 20 10:09:38 UTC 2018


#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


More information about the ghc-tickets mailing list