| 71 | | [TODO] |
| | 71 | Demand analysis in GHC drives the ''worker-wrapper transformation'', which exposes specialised calling conventions to the rest of the compiler. In particular, the worker-wrapper transformation implements the unboxing optimisation. |
| | 72 | |
| | 73 | The worker-wrapper transformation splits each |
| | 74 | function `f` into a ''wrapper'', with the |
| | 75 | ordinary calling convention, and a ''worker'', with a specialised |
| | 76 | calling convention. The wrapper serves as an impedance-matcher to the |
| | 77 | worker; it simply calls the worker using the specialised calling convention. |
| | 78 | The transformation can be expressed directly in GHC's intermediate language. |
| | 79 | Suppose that `f` is defined thus: |
| | 80 | {{{ |
| | 81 | f :: (Int,Int) -> Int |
| | 82 | f p = <rhs> |
| | 83 | }}} |
| | 84 | and that we know that `f` is strict in its argument (the pair, that is), |
| | 85 | and uses its components. |
| | 86 | What worker-wrapper split shall we make? Here is one |
| | 87 | possibility: |
| | 88 | {{{ |
| | 89 | f :: (Int,Int) -> Int |
| | 90 | f p = case p of |
| | 91 | (a,b) -> $wf a b |
| | 92 | |
| | 93 | $wf :: Int -> Int -> Int |
| | 94 | $wf a b = let p = (a,b) in <rhs> |
| | 95 | }}} |
| | 96 | Now the wrapper, `f`, can be inlined at every call site, so that |
| | 97 | the caller evaluates `p`, passing only the components to the worker |
| | 98 | `$wf`, thereby implementing the unboxing transformation. |
| | 99 | |
| | 100 | |
| | 101 | But what if `f` did not use `a`, or `b`? Then it would be silly to |
| | 102 | pass them to the worker `$wf`. Hence the need for absence |
| | 103 | analysis. Suppose, then, that we know that `b` is not needed. Then |
| | 104 | we can transform to: |
| | 105 | {{{ |
| | 106 | f :: (Int,Int) -> Int |
| | 107 | f p = case p of (a,b) -> $wf a |
| | 108 | |
| | 109 | $wf :: Int -> Int |
| | 110 | $wf a = let p = (a,error "abs") in <rhs> |
| | 111 | }}} |
| | 112 | Since `b` is not needed, we can avoid passing it from the wrapper to |
| | 113 | the worker; while in the worker, we can use `error "abs"` instead of |
| | 114 | `b`. |
| | 115 | |
| | 116 | |
| | 117 | In short, the worker-wrapper transformation allows the knowledge |
| | 118 | gained from strictness and absence analysis to be exposed to the rest |
| | 119 | of the compiler simply by performing a local transformation on the |
| | 120 | function definition. Then ordinary inlining and case elimination will |
| | 121 | do the rest, transformations the compiler does anyway. |
| | 122 | |