# GHC optimisations

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

## Introduction

• Everybody else: Feel free to add questions!

## General optimisations

### Common subexpression elimination

First of all, common subexpression elemination (CSE) means that if an expression appears in several places, the code is rearranged so that the value of that expression is computed only once. For example:

```  foo x = (bar x) * (bar x)
```

might be transformed into

```  foo x = let x' = bar x in x' * x'
```

thus, the `bar` function is only called once. (And if `bar` is a particularly expensive function, this might save quite a lot of work.)

GHC doesn't actually perform CSE as often as you might expect. The trouble is, performing CSE can affect the strictness/lazyness of the program. So GHC does do CSE, but only in specific circumstances --- see the GHC manual. (Section??)

Long story short: "If you care about CSE, do it by hand."

### Inlining

Inlining is where a function call is replaced by that function's definition. For example, the standard `map` function can be defined as

```  map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = f x : map f xs
```

Now if you write something like

```  foo = map bar
```

it's possible that the compiler might inline the definition of `map`, yielding something like

```  foo [] = []
foo (x:xs) = bar x : foo xs
```

which is (hopefully!) faster, because it doesn't involve a call to the `map` function any more, it just does the work directly. (This might also expose new optimisations opportunities; `map` works for any types, whereas `foo` probably works for only one type.)

So, that's what inlining is. By default, GHC will inline things if they are 'small enough'. Every time you inline a function, you are in a sense making a (customised) copy of that function. Do too much of this and the compiled program will be enormous. So it's only worth it for 'small' functions.

(How does GHC determine 'small'? Isn't there a switch that adjusts this?)