[GHC] #13289: Terrible loss of optimisation in presence of ticks

#13289: Terrible loss of optimisation in presence of ticks -------------------------------------+------------------------------------- Reporter: simonpj | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Keywords: Profiling | Operating System: Unknown/Multiple Architecture: | Type of failure: None/Unknown Unknown/Multiple | Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- Consider {{{ case (error "blah") of BIG }}} You'd expect that to simplify to `error "blah"`, or more precisely to `case error "blah" of {}`. And usually it does. But if there are ticks around it, it does not, and we retain {{{ case (tick x (error "blah")) of BIG }}} The problem is in `Simpify.simplTick`. It calls `splitCont` which implements semantics I do not understand. The Right Thing is surely this. * Always push the tick onto the continuation {{{ simplTick env tickish expr cont = simplExprF env expr (mkTickIt tickish cont) }}} * Implement a suitable `mkTickIt` that pushes a tick past a continuation where possible. For example I think {{{ mkTickIt t (ApplyTo arg cont) = ApplyTo arg (mkTickIt t cont) }}} That is `(tick t e) a` becomes `tick t (e a)`. It's probably conditioned on what sort of tick, but that's fine. * The comments from `7bb0447d` (simonmar) say {{{ -- XXX: we cannot do this, because the simplifier assumes that -- the context can be pushed into a case with a single branch. e.g. -- scc<f> case expensive of p -> e -- becomes -- case expensive of p -> scc<f> e -- -- So I'm disabling this for now. It just means we will do more }}} But that's wrong. All we need to do is to ensure that `prepareCaseCont` always stops at the kind of tick we don't want to push inside. * Finally, the bottom case of `rebuildCall` should retain ticks from the continuation. Not too hard, but requires understanding of the semantics of ticks, which I do not have. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13289 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13289: Terrible loss of optimisation in presence of ticks -------------------------------------+------------------------------------- Reporter: simonpj | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Profiling Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by simonmar): * cc: simonmar (added) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13289#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13289: Terrible loss of optimisation in presence of ticks -------------------------------------+------------------------------------- Reporter: simonpj | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Profiling 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 simonmar): `splitCont` looks like it separates out any outer type applications and coercions from the continuation, so in `(a,b) = splitCont c`, `a` is a continuation that consists only of the outer type applications and coercions from `c`, and `b` is the rest of the continuation. In order to transform `(tick t e) a` into `tick t (e a)`, the conditions should be * Either `a` is a type, or * `tickishScopesLike t NoScope` the second condition says that we must not float things in or out of the tick. (This `tickishScopesLike` thing is Peter's, I'm not all that familiar with it but I think this is right) The other thing that the current code is doing is pushing coercions inside the tick, which is always safe (and probably a good idea, given that I made it do this before). But it's slightly strange that this code appears to be lifting ticks out of type applications, whereas `CoreUtils.mkTick` is doing exactly the opposite! I have no idea why. The semantics wouldn't tell us; both are safe to do (like, say, floating a `let` outside an application), it's just a question of which one gives the best results. There are a couple of things we can do here: - Run the profiling tests in `testsuite/tests/profiling` - Run nofib with profiling on So I suggest making the change you propose, put it up on Phab, and also run the tests and nofib to check whether the changes don't introduce obvious regressions. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13289#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC