Why doesn’t the simple optimizer fuse casts?

This question is spurred by curiosity more than anything else, but I’ve noticed that the simple optimizer doesn’t fuse nested casts, and I’m wondering if there’s any reason it couldn’t. To make what I’m talking about more concrete, suppose we have an expression like this: (x |> co) |> sym co It seems like it would be trivial for simpleOptExpr to fuse the nested casts to get x |> co; sym co and then the coercion optimizer could get rid of it entirely. Moreover, this seems within the spirit of the simple optimizer, since it’s really just “cleaning up” an expression. Is there any reason the simple optimizer doesn’t do this, or is it just something nobody implemented? (For context, I’ve recently been staring at a lot of -ddump-ds output, and there happen to be a bunch of nested casts in the result that are really just noise. It would be nice if the simple optimizer got rid of them for me.) Alexis

Hi Alexis, Nested casts shouldn't happen. The mkCast function gets rid of them. Someone somewhere is forgetting to call it. If you have a concrete program that leads to nested casts, post a bug report. :) Thanks! Richard
On Apr 27, 2020, at 8:29 PM, Alexis King
wrote: This question is spurred by curiosity more than anything else, but I’ve noticed that the simple optimizer doesn’t fuse nested casts, and I’m wondering if there’s any reason it couldn’t. To make what I’m talking about more concrete, suppose we have an expression like this:
(x |> co) |> sym co
It seems like it would be trivial for simpleOptExpr to fuse the nested casts to get
x |> co; sym co
and then the coercion optimizer could get rid of it entirely. Moreover, this seems within the spirit of the simple optimizer, since it’s really just “cleaning up” an expression. Is there any reason the simple optimizer doesn’t do this, or is it just something nobody implemented?
(For context, I’ve recently been staring at a lot of -ddump-ds output, and there happen to be a bunch of nested casts in the result that are really just noise. It would be nice if the simple optimizer got rid of them for me.)
Alexis _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

Hi Richard, Nested casts can absolutely happen after the simple optimizer runs. Suppose we produce a desugared expression like: let { y = x `cast` co1 } in y `cast` co2 The simple optimizer will inline y, since it only appears once, so now we have a nested cast. Perhaps you mean you expect the casts to be merged when the simple optimizer gets to the Cast expression itself, but they aren’t, as it doesn’t use mkCast to reconstruct the result: -- from GHC.Core.SimpleOpt.simple_opt_expr go (Cast e co) | isReflCo co' = go e | otherwise = Cast (go e) co' I suppose a really simple fix would be to just use mkCast here instead of Cast, but that wouldn’t be completely satisfying, since the merged coercion wouldn’t be optimized. So you’d have to do something slightly more complicated to detect if the result of `go e` was a cast expression and combine the coercions before calling optCoercion. Whether or not doing that would be a good idea is precisely what I’m asking about. :) Alexis
On Apr 27, 2020, at 16:22, Richard Eisenberg
wrote: Hi Alexis,
Nested casts shouldn't happen. The mkCast function gets rid of them. Someone somewhere is forgetting to call it. If you have a concrete program that leads to nested casts, post a bug report. :)
Thanks! Richard

Alexis King
Whether or not doing that would be a good idea is precisely what I’m asking about. :)
Sounds like it would be worth a quick try. Given that this will get hit by the simplifier eventually anyways I suspect it won't make much of a difference one way or the other. That being said, I've been wrong before... Cheers, - Ben

On Apr 28, 2020, at 1:07 AM, Ben Gamari
wrote: Sounds like it would be worth a quick try.
I agree with Ben. I generally expect not to see nested casts -- the Cast constructor should rarely (never?) appear as an expression outside of mkCast. But you're right about the missing optimization opportunity if we do the naive thing. Let us know if you run into trouble with the "quick try"! Richard

Good spot. The very simple optimiser is, well, very simple. So let's not do anything complicated.
But could you submit a ticket, and patch, to replace that Cast with mkCast? Thanks!
Simon
| -----Original Message-----
| From: ghc-devs
participants (4)
-
Alexis King
-
Ben Gamari
-
Richard Eisenberg
-
Simon Peyton Jones