Is there a way to optimize out some foreign calls?

Brian Hulley brianh at metamilk.com
Tue Apr 4 11:20:05 EDT 2006


H -
I'm wondering if there is any way to specify that certain sequences of 
foreign calls can be merged into a single foreign call. For example, in a 
common situation where a state of a foreign API is pushed and popped so that 
the previous state is restored, I'd like successive pops to avoid wasting 
time restoring intermediate states as in:

-- push a state onto the API's state stack (without changing the state)
foreign import ccall api_push :: State -> IO ()

-- discards the state at the top of the stack
foreign import ccall api_pop :: IO ()

-- synchronises the API's state with the state at the top of the stack
foreign import ccall api_sync :: IO ()

use :: State -> IO () -> IO ()
use s action = do
               api_push s
               api_sync
               action
               api_pop
               api_sync   -- put the API back into the previous state

main = do
              use State1 $ do
                     actionIn1a
                     use State2 $ do
                          actionIn2
                          use State3 $ do
                               actionIn3
                     actionIn1b

If 'use' is inlined, the compiler would (presumably) produce code like:

main = do
              api_push State1
              api_sync
              actionIn1a
              api_push State2
              api_sync
              actionIn2
              api_push State3
              api_sync
              actionIn3
              api_pop
              api_sync  -- This is a waste of time
              api_pop
              api_sync
              actionIn1b
              api_pop
              api_sync

I'm wondering if there is any way to cause the compiler to avoid the 
wasteful call to api_sync above.

I'm thinking in terms of some way of marking foreign functions to specify 
how they can be optimized out or specifying rewrite sequences eg

             x >> api_sync >> api_pop >> api_sync >> y = x >> api_pop >> 
api_sync >> y

I've read the manual (7.10) on rewrite rules, but I'm having difficulty 
understanding how to express the lhs of the above equation as a rewrite rule 
so that it matches a sequence anywhere in a do block (to deal with nested 
parentheses and the use of >>= instead of >>)

Any ideas?

Thanks, Brian. 



More information about the Glasgow-haskell-users mailing list