RE: [Haskell] unsafePerformIO and optimizations

On 06 August 2005 15:24, Wolfgang Jeltsch wrote:
First, what is the problem with inlining a function call? Say, I have a function f defined as follows:
f :: Char -> () f c = unsafePerformIO (putChar c)
If inlining is allowed, the expression f '*' becomes
unsafePerformIO (putChar '*').
Is this a problem? Or is inlining dangerous in other situations?
On the other hand, I can see that inlining non-functions could cause harm. Say I have something like this:
u :: () u = unsafePerformIO (putChar '*')
Now, inlining u would transform (u,u) to
(unsafePerformIO (putChar '*),unsafePerformIO (putChar '*'))
which could result in putChar '*' being executed multiple times. So why does the library documentation only talk about disabling inlining of functions?
Well, you're right - it's all about sharing of redexes of the form (unsafePerformIO e). When you write an unsafePerformIO with a side effect, you probably have an intuition about when you expect that redex to be reduced. In your example above, you're probably thinking "it'll be executed whenever f is called". However, optimisations can invalidate your intuition in many ways, by increasing (or reducing) sharing of the unsafePerformIO redex. Inlining 'f' itself isn't a problem, because that doesn't change sharing, as you pointed out. However, it might expose potential for *reducing* sharing, because (unsafePerformIO (putChar '*')) is now a visibly constant expression, it only needs to be evaluated once per run of the program.
I understand that common subexpression elimination could cause harm. It could transform the expression
(unsafePerformIO (putChar '*),unsafePerformIO (putChar '*'))
to
let u = unsafePerformIO (putChar '*') in (u,u),
couldn't it? This would result in the I/O action be performed at most once which is not what was intended. But couldn't the same thing also happen if I use the expression (f '*',f '*'), probably in a different module?
Well, quite.
Does this mean that I have to use -fno-cse not only in the module which contains the unsafePerformIO application but also in every other module which uses unsafePerformIO indirectly via f or functions using f?
This way leads to madness - GHC's optimisations are simply not designed to provide any kind of guarantee about maintaining sharing properties. The guidelines we've given for unsafePerformIO are enough to cover simple uses like global variables. We should probably amend the documentation to say this. Cheers, Simon

Am Montag, 8. August 2005 11:33 schrieb Simon Marlow:
[...]
This way leads to madness - GHC's optimisations are simply not designed to provide any kind of guarantee about maintaining sharing properties. The guidelines we've given for unsafePerformIO are enough to cover simple uses like global variables. We should probably amend the documentation to say this.
How about unsafeInterleaveIO? Are there any optimizations that could be dangerous here or is the bevavior of unsafeInterleaveIO independent of optimizations?
Cheers, Simon
Best regards, Wolfgang
participants (2)
-
Simon Marlow
-
Wolfgang Jeltsch