[project @ 2000-12-08 13:20:52 by simonpj]
[ghc-hetmet.git] / ghc / compiler / simplCore / LiberateCase.lhs
1 %
2 % (c) The AQUA Project, Glasgow University, 1994-1998
3 %
4 \section[LiberateCase]{Unroll recursion to allow evals to be lifted from a loop}
5
6 \begin{code}
7 module LiberateCase ( liberateCase ) where
8
9 #include "HsVersions.h"
10
11 import CmdLineOpts      ( DynFlags, DynFlag(..), dopt, opt_LiberateCaseThreshold )
12 import CoreLint         ( showPass, endPass )
13 import CoreSyn
14 import CoreUnfold       ( couldBeSmallEnoughToInline )
15 import Var              ( Id )
16 import VarEnv
17 import UniqFM           ( ufmToList )
18 import Maybes
19 import Outputable
20 \end{code}
21
22 This module walks over @Core@, and looks for @case@ on free variables.
23 The criterion is:
24         if there is case on a free on the route to the recursive call,
25         then the recursive call is replaced with an unfolding.
26
27 Example
28
29 \begin{verbatim}
30 f = \ t -> case v of
31                V a b -> a : f t
32 \end{verbatim}
33
34 => the inner f is replaced.
35
36 \begin{verbatim}
37 f = \ t -> case v of
38                V a b -> a : (letrec
39                                 f =  \ t -> case v of
40                                                V a b -> a : f t
41                              in f) t
42 \end{verbatim}
43 (note the NEED for shadowing)
44
45 => Simplify
46
47 \begin{verbatim}
48 f = \ t -> case v of
49                V a b -> a : (letrec
50                                 f = \ t -> a : f t
51                              in f t)
52 \begin{verbatim}
53
54 Better code, because 'a' is  free inside the inner letrec, rather
55 than needing projection from v.
56
57 Other examples we'd like to catch with this kind of transformation
58
59         last []     = error 
60         last (x:[]) = x
61         last (x:xs) = last xs
62
63 We'd like to avoid the redundant pattern match, transforming to
64
65         last [] = error
66         last (x:[]) = x
67         last (x:(y:ys)) = last' y ys
68                 where
69                   last' y []     = y
70                   last' _ (y:ys) = last' y ys
71
72         (is this necessarily an improvement)
73
74
75 Similarly drop:
76
77         drop n [] = []
78         drop 0 xs = xs
79         drop n (x:xs) = drop (n-1) xs
80
81 Would like to pass n along unboxed.
82         
83
84 To think about (Apr 94)
85 ~~~~~~~~~~~~~~
86
87 Main worry: duplicating code excessively.  At the moment we duplicate
88 the entire binding group once at each recursive call.  But there may
89 be a group of recursive calls which share a common set of evaluated
90 free variables, in which case the duplication is a plain waste.
91
92 Another thing we could consider adding is some unfold-threshold thing,
93 so that we'll only duplicate if the size of the group rhss isn't too
94 big.
95
96 Data types
97 ~~~~~~~~~~
98
99 The ``level'' of a binder tells how many
100 recursive defns lexically enclose the binding
101 A recursive defn "encloses" its RHS, not its
102 scope.  For example:
103 \begin{verbatim}
104         letrec f = let g = ... in ...
105         in
106         let h = ...
107         in ...
108 \end{verbatim}
109 Here, the level of @f@ is zero, the level of @g@ is one,
110 and the level of @h@ is zero (NB not one).
111
112 \begin{code}
113 type LibCaseLevel = Int
114
115 topLevel :: LibCaseLevel
116 topLevel = 0
117 \end{code}
118
119 \begin{code}
120 data LibCaseEnv
121   = LibCaseEnv
122         Int                     -- Bomb-out size for deciding if
123                                 -- potential liberatees are too big.
124                                 -- (passed in from cmd-line args)
125
126         LibCaseLevel            -- Current level
127
128         (IdEnv LibCaseLevel)    -- Binds all non-top-level in-scope Ids
129                                 -- (top-level and imported things have
130                                 -- a level of zero)
131
132         (IdEnv CoreBind)        -- Binds *only* recursively defined
133                                 -- Ids, to their own binding group,
134                                 -- and *only* in their own RHSs
135
136         [(Id,LibCaseLevel)]     -- Each of these Ids was scrutinised by an
137                                 -- enclosing case expression, with the
138                                 -- specified number of enclosing
139                                 -- recursive bindings; furthermore,
140                                 -- the Id is bound at a lower level
141                                 -- than the case expression.  The
142                                 -- order is insignificant; it's a bag
143                                 -- really
144
145 initEnv :: Int -> LibCaseEnv
146 initEnv bomb_size = LibCaseEnv bomb_size 0 emptyVarEnv emptyVarEnv []
147
148 pprEnv :: LibCaseEnv -> SDoc
149 pprEnv (LibCaseEnv _ lvl lvl_env _ scruts)
150   = vcat [text "LibCaseEnv" <+> int lvl,
151           fsep (map ppr (ufmToList lvl_env)),
152           fsep (map ppr scruts)]
153
154 bombOutSize (LibCaseEnv bomb_size _ _ _ _) = bomb_size
155 \end{code}
156
157
158 Programs
159 ~~~~~~~~
160 \begin{code}
161 liberateCase :: DynFlags -> [CoreBind] -> IO [CoreBind]
162 liberateCase dflags binds
163   = do {
164         showPass dflags "Liberate case" ;
165         let { binds' = do_prog (initEnv opt_LiberateCaseThreshold) binds } ;
166         endPass dflags "Liberate case" Opt_D_verbose_core2core binds'
167                                 {- no specific flag for dumping -} 
168     }
169   where
170     do_prog env [] = []
171     do_prog env (bind:binds) = bind' : do_prog env' binds
172                              where
173                                (env', bind') = libCaseBind env bind
174 \end{code}
175
176 Bindings
177 ~~~~~~~~
178
179 \begin{code}
180 libCaseBind :: LibCaseEnv -> CoreBind -> (LibCaseEnv, CoreBind)
181
182 libCaseBind env (NonRec binder rhs)
183   = (addBinders env [binder], NonRec binder (libCase env rhs))
184
185 libCaseBind env (Rec pairs)
186   = (env_body, Rec pairs')
187   where
188     (binders, rhss) = unzip pairs
189
190     env_body = addBinders env binders
191
192     pairs' = [(binder, libCase env_rhs rhs) | (binder,rhs) <- pairs]
193
194     env_rhs = if all rhs_small_enough rhss then extended_env else env
195
196         -- We extend the rec-env by binding each Id to its rhs, first
197         -- processing the rhs with an *un-extended* environment, so
198         -- that the same process doesn't occur for ever!
199
200     extended_env = addRecBinds env [ (binder, libCase env_body rhs)
201                                    | (binder, rhs) <- pairs ]
202
203     rhs_small_enough rhs = couldBeSmallEnoughToInline lIBERATE_BOMB_SIZE rhs
204     lIBERATE_BOMB_SIZE   = bombOutSize env
205 \end{code}
206
207
208 Expressions
209 ~~~~~~~~~~~
210
211 \begin{code}
212 libCase :: LibCaseEnv
213         -> CoreExpr
214         -> CoreExpr
215
216 libCase env (Var v)             = libCaseId env v
217 libCase env (Lit lit)           = Lit lit
218 libCase env (Type ty)           = Type ty
219 libCase env (App fun arg)       = App (libCase env fun) (libCase env arg)
220 libCase env (Note note body)    = Note note (libCase env body)
221
222 libCase env (Lam binder body)
223   = Lam binder (libCase (addBinders env [binder]) body)
224
225 libCase env (Let bind body)
226   = Let bind' (libCase env_body body)
227   where
228     (env_body, bind') = libCaseBind env bind
229
230 libCase env (Case scrut bndr alts)
231   = Case (libCase env scrut) bndr (map (libCaseAlt env_alts) alts)
232   where
233     env_alts = addBinders env_with_scrut [bndr]
234     env_with_scrut = case scrut of
235                         Var scrut_var -> addScrutedVar env scrut_var
236                         other         -> env
237
238 libCaseAlt env (con,args,rhs) = (con, args, libCase (addBinders env args) rhs)
239 \end{code}
240
241 Ids
242 ~~~
243 \begin{code}
244 libCaseId :: LibCaseEnv -> Id -> CoreExpr
245 libCaseId env v
246   | Just the_bind <- lookupRecId env v  -- It's a use of a recursive thing
247   -- = not (null free_scruts)           -- with free vars scrutinised in RHS
248   = if null free_scruts then
249         pprTrace "No:" (ppr v $$ pprEnv env) (Var v)
250     else
251         pprTrace "Yes:" (ppr v) $ Let the_bind (Var v)
252
253   | otherwise
254   = Var v
255
256   where
257     rec_id_level = lookupLevel env v
258     free_scruts  = freeScruts env rec_id_level
259 \end{code}
260
261
262
263 Utility functions
264 ~~~~~~~~~~~~~~~~~
265 \begin{code}
266 addBinders :: LibCaseEnv -> [CoreBndr] -> LibCaseEnv
267 addBinders (LibCaseEnv bomb lvl lvl_env rec_env scruts) binders
268   = LibCaseEnv bomb lvl lvl_env' rec_env scruts
269   where
270     lvl_env' = extendVarEnvList lvl_env (binders `zip` repeat lvl)
271
272 addRecBinds :: LibCaseEnv -> [(Id,CoreExpr)] -> LibCaseEnv
273 addRecBinds (LibCaseEnv bomb lvl lvl_env rec_env scruts) pairs
274   = LibCaseEnv bomb lvl' lvl_env' rec_env' scruts
275   where
276     lvl'     = lvl + 1
277     lvl_env' = extendVarEnvList lvl_env [(binder,lvl) | (binder,_) <- pairs]
278     rec_env' = extendVarEnvList rec_env [(binder, Rec pairs) | (binder,_) <- pairs]
279
280 addScrutedVar :: LibCaseEnv
281               -> Id             -- This Id is being scrutinised by a case expression
282               -> LibCaseEnv
283
284 addScrutedVar env@(LibCaseEnv bomb lvl lvl_env rec_env scruts) scrut_var
285   | bind_lvl < lvl
286   = LibCaseEnv bomb lvl lvl_env rec_env scruts'
287         -- Add to scruts iff the scrut_var is being scrutinised at
288         -- a deeper level than its defn
289
290   | otherwise = env
291   where
292     scruts'  = (scrut_var, lvl) : scruts
293     bind_lvl = case lookupVarEnv lvl_env scrut_var of
294                  Just lvl -> lvl
295                  Nothing  -> topLevel
296
297 lookupRecId :: LibCaseEnv -> Id -> Maybe CoreBind
298 lookupRecId (LibCaseEnv bomb lvl lvl_env rec_env scruts) id
299   = lookupVarEnv rec_env id
300
301 lookupLevel :: LibCaseEnv -> Id -> LibCaseLevel
302 lookupLevel (LibCaseEnv bomb lvl lvl_env rec_env scruts) id
303   = case lookupVarEnv lvl_env id of
304       Just lvl -> lvl
305       Nothing  -> topLevel
306
307 freeScruts :: LibCaseEnv
308            -> LibCaseLevel      -- Level of the recursive Id
309            -> [Id]              -- Ids that are bound ouside the recursive Id, (level <=)
310                                 -- but which are scrutinised on the way to this call
311 freeScruts (LibCaseEnv bomb lvl lvl_env rec_env scruts) rec_bind_lvl
312   = [v | (v,lvl) <- scruts, lvl <= rec_bind_lvl]
313 \end{code}