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 | |