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 <lexi.lambda@gmail.com> 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 <rae@richarde.dev> 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 <lexi.lambda@gmail.com> writes: ...
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 <ben@smart-cactus.org> 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 <ghc-devs-bounces@haskell.org> On Behalf Of Alexis King | Sent: 27 April 2020 22:58 | To: Richard Eisenberg <rae@richarde.dev> | Cc: ghc-devs <ghc-devs@haskell.org> | Subject: Re: Why doesn’t the simple optimizer fuse casts? | | 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 <rae@richarde.dev> 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 | _______________________________________________ | ghc-devs mailing list | ghc-devs@haskell.org | https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmail.has | kell.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fghc- | devs&data=02%7C01%7Csimonpj%40microsoft.com%7C825fe41065dd450030e908d | 7eaf61d19%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637236215077850647 | &sdata=w%2Fk4JG%2FOmpwPoUAAGqdC62ssQSYcLQioY8T9%2BZ3XS8E%3D&reser | ved=0
participants (4)
-
Alexis King -
Ben Gamari -
Richard Eisenberg -
Simon Peyton Jones