[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