[GHC] #11731: Simplifier: Inlining trivial let can lose sharing

GHC ghc-devs at haskell.org
Tue Mar 22 13:42:39 UTC 2016


#11731: Simplifier: Inlining trivial let can lose sharing
-------------------------------------+-------------------------------------
        Reporter:  nomeata           |                Owner:
            Type:  bug               |               Status:  new
        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):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by nomeata):

 >  I tried the test program with -O; but it only prints "Evaluated" once.
 So, strangely, I can't reproduce the bug. What exact commands did you use?

 Well spotted! I ran with `-O2`, and indeed, it does not happen with `-O`,
 but with `-O -fspec-constr`. Nothing deep here, it’s just that constructor
 specialization is required in this particular example to massage the code
 into the shape we want.

 > Does using -flate-dmd-anal fix the problem?

 Indeed it does. It recalculates the demand signature correctly, and will
 share the `shareMeThunk`. But after `-flate-dmd-anal`, there is another
 round of worker-wrapper and simplifier. So the principle, the problem
 could occur again.

 I would prefer to take a step back and think about what, at the level of
 Core, the semantics of
 {{{
 let x = y in foo x
 }}}
 should be, independent of any possible annotations. Here a digression that
 follows that train of thought:

 If this code should indeed guarantee that `y` is evaluated at most once,
 then rewriting to `foo y` is in general wrong (and may only be justified
 if we ''know'' that `foo` evaluates its argument only once – this is more
 conservative than not doing the substitution if we happen to know that it
 can go wrong).

 Alternatively, we declare the semantics that a `let` with a trivial RHS
 should ''not'' (guarantee) sharin (just like a trivial function argument
 does not indicate sharing!). But then the problem was one step earlier
 where GHC replaced
 {{{
 let x = case (y,z) of (y,z) -> y
 in foo x
 }}}
 with the trivial let above. Maybe it should have changed it to something
 like
 {{{
 let x = share y
 in foo x
 }}}
 where `share` is a magic id that is semantically the identity, but
 prevents the `let` from being trivial. Now `x` can even be safely inlined
 then `foo (share y)`. The simplifier could know some rules about when
 occurrences of `share` can be removed (e.g. when the argument is not
 trivial any more, or when it is itself known to be shared).

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


More information about the ghc-tickets mailing list