
I was wondering if we could be sure to get dependingOn :: a -> b -> a dependingOn = .... in ghc 6.6? this has been discussed before, it is implemented in jhc and I have found all sorts of use for it as it can be used to control let floating and inlining in a nice general way and is trivial to implement. (one for ghc was posted before based on primitives it already implements) we just need to decide on a module to export it. the meaning is that x = ... `dependingOn` y returns x with an artificial dependency on y. so things using x cannot be floated out above where y is defined. John -- John Meacham - ⑆repetae.net⑆john⑈

Hmm. It's pretty late in the day. What's the implementation you have in mind? It's sure to get in the way of some optimisations; e.g. ((\x.e) `dependingOn` y) arg Maybe that doesn’t matter. I'm reluctant to build in optimisation rules for dependingOn. Is the argument order right? dependingOn is very like "seq" except that it's lazy. Shouldn't it have the same type? When is it ok to inline the function, to reveal its (lack of) implementation? Can you just implement it in a library of your own? Can you list the "all sorts of applications" you have in mind? It might be good to collect this stuff in a Trac feature request. Simon | -----Original Message----- | From: glasgow-haskell-users-bounces@haskell.org [mailto:glasgow-haskell-users- | bounces@haskell.org] On Behalf Of John Meacham | Sent: 09 August 2006 00:59 | To: glasgow-haskell-users@haskell.org | Subject: dependingOn in 6.6 | | I was wondering if we could be sure to get | | dependingOn :: a -> b -> a | dependingOn = .... | | in ghc 6.6? this has been discussed before, it is implemented in jhc and | I have found all sorts of use for it as it can be used to control let | floating and inlining in a nice general way and is trivial to implement. | (one for ghc was posted before based on primitives it already | implements) | | we just need to decide on a module to export it. | | the meaning is that | | x = ... `dependingOn` y | | returns x with an artificial dependency on y. so things using x cannot | be floated out above where y is defined. | | | John | | | -- | John Meacham - ⑆repetae.net⑆john⑈ | _______________________________________________ | Glasgow-haskell-users mailing list | Glasgow-haskell-users@haskell.org | http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

On Wed, Aug 09, 2006 at 08:40:06AM +0100, Simon Peyton-Jones wrote:
What's the implementation you have in mind? It's sure to get in the way of some optimisations; e.g. ((\x.e) `dependingOn` y) arg Maybe that doesn’t matter. I'm reluctant to build in optimisation rules for dependingOn.
getting in the way of optimizations is 100% exactly the purpose of it. there are two optimizations in particular it gives the user fine grained control over, CSE and let floating. it is also very useful for implementing low level IO stuff, and some special case code in ghc dealing with the world# can be dropped probably if dependingOn were used. (I'll get to that)
Is the argument order right? dependingOn is very like "seq" except that it's lazy. Shouldn't it have the same type?
I think the similarity to seq is mainly superficial. seq doesn't actually keep its arguments coupled together, it causes its first argument to be strict in a given context, but other than that it doesn't really use its second argument. both evaluations can be floated around independently after the initial transformation. dependingOn maintains the relaionship between its arguments throughout the compilation process right up to code generation.
When is it ok to inline the function, to reveal its (lack of) implementation? Can you just implement it in a library of your own?
I am assuming it will be transformed into a primitive that is simply passed through the opimizer like normal and discarded by the code generator. the existing touch# might do the job.
Can you list the "all sorts of applications" you have in mind?
for the user there are a couple of uses, mainly it gets rid of the caveats of using unsafePerformIO so you no longer need to turn of let-floating or cse to use it safely in certain cases. -- no need for CSE
data Dummy1 = Dummy1 intVar1 :: IORef Int intVar1 = unsafePerformIO (newIORef 0 `dependingOn` Dummy1)
data Dummy2 = Dummy2 intVar2 :: IORef Int intVar2 = unsafePerformIO (newIORef 0 `dependingOn` Dummy2)
normally, you would have to compile with -fno-cse to keep these two variables from being turned into one. however, since Dummy1 and Dummy2 will never be the same, the two terms cannot be considered the same by he optimizer so there is no problem. -- no need for turning off let-floating f x = log `seq` ... where log = unsafePerformIO (putErrLn "f called" `dependingOn` x) normally, the log function will be floated out so the rouinte is only called once when you actually want it to be executed every time f x is entered. the 'dependingOn' ensures this is the case. similarly, it can be used to quash space leaks bigAndFast is something that is trivial to compute, but would take up a ton of space if kept around, like an expanded string. you want to ensure it is not floated to the top level. f x = ... bigAndFast ... where bigAndFast = unpackString (constantString `dependingOn` x) now it cannot be floated to the top level. Now for some of the low level goodness: right now, ghc has to be careful to never inline unsafePerformIO, this gets in the way of optimizations, like if what it computes is a good producer, you still can't fusion it with a consumer. -- current definition {-# NOINLINE unsafePerformIO #-} unsafePerformIO :: IO a -> a unsafePerformIO (IO m) = case m realWorld# of (# _, r #) -> r -- new definition unsafePerformIO :: IO a -> a unsafePerformIO (IO m) = case m (realWorld# `dependingOn` m) of (# _, r #) -> r now the problem goes away, realWord# is no longer a consant that might lead to CSEing with something else, but now depends on the argumen to unsafePerformIO. now unsafePerformIO can safely be inlined. similarly, runST and array creation can be simplified in the same way. it allows sequence points to be implemented, right now there is special case code in the compiler to ensure certain strict values are never floated 'ahead' in the IO monad. you can implement something like sequence :: a -> IO a sequence x = IO \world -> (# world, x `dependingOn` world #) now, any use of thunks passed through sequence are guarenteed to not be evaluated until after all IO actions happening before it have completed. other uses have popped up. I implemented it just as a hack to get array creation to work, but have found it to be very useful in general. John -- John Meacham - ⑆repetae.net⑆john⑈

John Meacham wrote:
data Dummy1 = Dummy1 intVar1 :: IORef Int intVar1 = unsafePerformIO (newIORef 0 `dependingOn` Dummy1)
data Dummy2 = Dummy2 intVar2 :: IORef Int intVar2 = unsafePerformIO (newIORef 0 `dependingOn` Dummy2)
normally, you would have to compile with -fno-cse to keep these two variables from being turned into one. however, since Dummy1 and Dummy2 will never be the same, the two terms cannot be considered the same by he optimizer so there is no problem.
I would like to see this in GHC. It's still an ugly hack but at least it's a better option than remembering to compile with -fno-cse IMO. I guess you still need the NOINLINE pragma too though. Regards -- Adrian Hey

John Meacham wrote:
I was wondering if we could be sure to get
dependingOn :: a -> b -> a dependingOn = ....
in ghc 6.6? this has been discussed before, it is implemented in jhc and I have found all sorts of use for it as it can be used to control let floating and inlining in a nice general way and is trivial to implement. (one for ghc was posted before based on primitives it already implements)
we just need to decide on a module to export it.
the meaning is that
x = ... `dependingOn` y
returns x with an artificial dependency on y. so things using x cannot be floated out above where y is defined.
If you make a ticket for it, we can try to get to it for 6.6, but it's probably unlikely at this stage. It's like the touch# primitive we already have, but I'm not sure if it can be implemented using touch#. We did discuss this before, IIRC - do you have a pointer to the discussion? Cheers, Simon
participants (4)
-
Adrian Hey
-
John Meacham
-
Simon Marlow
-
Simon Peyton-Jones