E.g. the program:
import Control.Ev.Eff
main :: IO ()
main = print $ runEff $ local 0 $ do
localModify (+ 1)
localGet
Prints (when compiled with -O):
I think that this is due to common sub-expression elimination. First the code above gets turned into something like:
import Control.Ev.Eff
main :: IO ()
main =
let !r = unsafePerformIO (newIORef 0)
!x1 = unsafePerformIO (readIORef r)
!() = unsafePerformIO (writeIORef r (x1 + 1)
!x2 = unsafePerformIO (readIORef r)
in pure x2
And common sub-expression elimination transforms that to:
import Control.Ev.Eff
main :: IO ()
main =
let !r = unsafePerformIO (newIORef 0)
!x1andx2 = unsafePerformIO (readIORef r)
!() = unsafePerformIO (writeIORef r (x1andx2 + 1)
in pure x1andx2
A simple solution seems to be to mark perform NOINLINE, but that probably affects performance.
E.g. the program:
Prints (when compiled with
-O):I think that this is due to common sub-expression elimination. First the code above gets turned into something like:
And common sub-expression elimination transforms that to:
A simple solution seems to be to mark
performNOINLINE, but that probably affects performance.