GHC supports several pragmas, or instructions to the compiler placed in the source code. Pragmas don't affect the meaning of the program, but they might affect the efficiency of the generated code.
GHC (with -O, as always) tries to inline (or “unfold”) functions/values that are “small enough,” thus avoiding the call overhead and possibly exposing other more-wonderful optimisations.
You will probably see these unfoldings (in Core syntax) in your interface files.
Normally, if GHC decides a function is “too expensive” to inline, it will not do so, nor will it export that unfolding for other modules to use.
The sledgehammer you can bring to bear is the INLINE pragma, used thusly:
key_function :: Int -> String -> (Bool, Double) #ifdef __GLASGOW_HASKELL__ {-# INLINE key_function #-} #endif |
The major effect of an INLINE pragma is to declare a function's “cost” to be very low. The normal unfolding machinery will then be very keen to inline it.
An INLINE pragma for a function can be put anywhere its type signature could be put.
INLINE pragmas are a particularly good idea for the then/return (or bind/unit) functions in a monad. For example, in GHC's own UniqueSupply monad code, we have:
#ifdef __GLASGOW_HASKELL__ {-# INLINE thenUs #-} {-# INLINE returnUs #-} #endif |
The NOINLINE pragma does exactly what you'd expect: it stops the named function from being inlined by the compiler. You shouldn't ever need to do this, unless you're very cautious about code size.
(UK spelling also accepted.) For key overloaded functions, you can create extra versions (NB: more code space) specialised to particular types. Thus, if you have an overloaded function:
hammeredLookup :: Ord key => [(key, value)] -> key -> value |
If it is heavily used on lists with Widget keys, you could specialise it as follows:
{-# SPECIALIZE hammeredLookup :: [(Widget, value)] -> Widget -> value #-} |
To get very fancy, you can also specify a named function to use for the specialised value, as in:
{-# RULES hammeredLookup = blah #-} |
where blah is an implementation of hammerdLookup written specialy for Widget lookups. It's Your Responsibility to make sure that blah really behaves as a specialised version of hammeredLookup!!!
Note we use the RULE pragma here to indicate that hammeredLookup applied at a certain type should be replaced by blah. See Section 7.15.6 for more information on RULES.
An example in which using RULES for specialisation will Win Big:
toDouble :: Real a => a -> Double toDouble = fromRational . toRational {-# SPECIALIZE toDouble :: Int -> Double = i2d #-} i2d (I# i) = D# (int2Double# i) -- uses Glasgow prim-op directly |
A SPECIALIZE pragma for a function can be put anywhere its type signature could be put.
Same idea, except for instance declarations. For example:
instance (Eq a) => Eq (Foo a) where { ... usual stuff ... } {-# SPECIALIZE instance Eq (Foo [(Int, Bar)] #-} |
This pragma is similar to C's #line pragma, and is mainly for use in automatically generated Haskell code. It lets you specify the line number and filename of the original code; for example
{-# LINE 42 "Foo.vhs" #-} |
if you'd generated the current file from something called Foo.vhs and this line corresponds to line 42 in the original. GHC will adjust its error messages to refer to the line/file named in the LINE pragma.
The RULES pragma lets you specify rewrite rules. It is described in Section 7.16.