RE: Fusing loops by specializing on functions with SpecConstr?

2020-04-06 Thread Simon Peyton Jones via ghc-devs
Cool -- but please do write a blog post or something to distil what you have learned. I have not followed this thread in detail, and I bet others haven't either. But it'd be a pity for your learning not to be shared somehow! Thanks Simon | -Original Message- | From: ghc-devs On

Re: Fusing loops by specializing on functions with SpecConstr?

2020-04-05 Thread Sebastian Graf
> > That’s it. These two rules alone are enough to eliminate the redundant > tupling. Now the optimized version of `mapMaybeSF` is beautiful! > Beautiful indeed! That's wonderful to hear. Good luck messing about with your FRP framework! Sebastian Am Sa., 4. Apr. 2020 um 03:45 Uhr schrieb Alexis

Re: Fusing loops by specializing on functions with SpecConstr?

2020-04-03 Thread Alexis King
I fiddled with alternative representations for a while and didn’t make any progress—it was too easy to end up with code explosion in the presence of any unknown calls—but I seem to have found a RULES-based approach that works very well on the examples I’ve tried. It’s quite simple, which makes it

RE: Fusing loops by specializing on functions with SpecConstr?

2020-04-01 Thread Simon Peyton Jones via ghc-devs
I have started a wiki page for join points here https://gitlab.haskell.org/ghc/ghc/-/wikis/Join-points-in-GHC Do add to it Simon | -Original Message- | From: ghc-devs On Behalf Of Joachim | Breitner | Sent: 01 April 2020 19:37 | To: ghc-devs | Subject: Re: Fusing loops by specializing

RE: Fusing loops by specializing on functions with SpecConstr?

2020-04-01 Thread Simon Peyton Jones via ghc-devs
Thanks. Perhaps I was thinking of Section 5 of the join-point paper https://www.microsoft.com/en-us/research/publication/compiling-without-continuations/ That's about compositions of tiny tail recursive loops. Alexis, just conceivably this might be relevant to your thinking on FRP ... but I'm

Re: Fusing loops by specializing on functions with SpecConstr?

2020-04-01 Thread Joachim Breitner
Hi, I think most of the docs about exitification are the notes in the Exitify module, and then there is the original ticket at https://gitlab.haskell.org/ghc/ghc/issues/14152 I don’t immediately see the connection to SpecConstr on function values, though, so I don't really know what’s tickling

Re: Fusing loops by specializing on functions with SpecConstr?

2020-04-01 Thread Alexis King
> On Apr 1, 2020, at 03:21, Sebastian Graf wrote: > > That is indeed true. But note that as long as you manage to inline > `mapMaybeSF`, the final `runSF` will only allocate once on the "edge" of each > iteration, all intermediate allocations will have been fused away. But the > allocation of

Re: Fusing loops by specializing on functions with SpecConstr?

2020-04-01 Thread Sebastian Graf
> > Looking at the optimized core, it’s true that the conversion of Maybe to > Either and back again gets eliminated, which is wonderful! But what’s less > wonderful is the value passed around through `s`: > > mapMaybeSF > = \ (@ a) (@ b) (f :: SF a b) -> > case f of { SF @ s

Re: Fusing loops by specializing on functions with SpecConstr?

2020-04-01 Thread Harendra Kumar
On Wed, 1 Apr 2020 at 02:49, Alexis King wrote: > > I’ve been trying to figure out if it would be possible to help the > optimizer out by annotating the program with special combinators like the > existing ones provided by GHC.Magic. However, I haven’t been able to come > up with anything yet

Re: Fusing loops by specializing on functions with SpecConstr?

2020-03-31 Thread Alexis King
> On Mar 31, 2020, at 17:05, Sebastian Graf wrote: > > Yeah, SPEC is quite unreliable, because IIRC at some point it's either > consumed or irrelevant. But none of the combinators you mentioned should rely > on SpecConstr! They are all non-recursive, so the Simplifier will take care > of

RE: Fusing loops by specializing on functions with SpecConstr?

2020-03-31 Thread Simon Peyton Jones via ghc-devs
Joachim: this conversation is triggering some hind-brain neurons related to exitification, or something like that. I recall that we discovered we could get some surprising fusion of recursive functions expressed as join points. Something like f . g . h where h loops for a while and

Re: Fusing loops by specializing on functions with SpecConstr?

2020-03-31 Thread Sebastian Graf
> > This is a neat trick, though I’ve had trouble getting it to work reliably > in my experiments (even though I was using GHC.Types.SPEC). That said, I > also feel like I don’t understand the subtleties of SpecConstr very well, > so it could have been my fault. > Yeah, SPEC is quite unreliable,

Re: Fusing loops by specializing on functions with SpecConstr?

2020-03-31 Thread Alexis King
Sebastian and Simon, Thank you both for your responses—they are all quite helpful! I agree with both of you that figuring out how to do this kind of specialization without any guidance from the programmer seems rather intractable. It’s too hard to divine where it would actually be beneficial,

Re: Fusing loops by specializing on functions with SpecConstr?

2020-03-31 Thread Sebastian Graf
We can formulate SF as a classic Stream that needs an `a` to produce its next element of type `b` like this (SF2 below): {-# LANGUAGE BangPatterns #-} {-# LANGUAGE GADTs #-} module Lib where newtype SF a b = SF { runSF :: a -> (b, SF a b) } inc1 :: SF Int Int inc1 = SF $ \a -> let !b = a+1 in

RE: Fusing loops by specializing on functions with SpecConstr?

2020-03-31 Thread Simon Peyton Jones via ghc-devs
Wow – tricky stuff! I would never have thought of trying to optimise that program, but it’s fascinating that you get lots and lots of them from FRP. * Don’t lose this thread! Make a ticket, or a wiki page. If the former, put the main payload (including Alexis’s examples) into the

Fusing loops by specializing on functions with SpecConstr?

2020-03-29 Thread Alexis King
Hi all, I have recently been toying with FRP, and I’ve noticed that traditional formulations generate a lot of tiny loops that GHC does a very poor job optimizing. Here’s a simplified example: newtype SF a b = SF { runSF :: a -> (b, SF a b) } add1_snd :: SF (String, Int) (String, Int)