2 % (c) The AQUA Project, Glasgow University, 1994-1996
4 \section[LiberateCase]{Unroll recursion to allow evals to be lifted from a loop}
6 96/03: We aren't using this at the moment
9 module LiberateCase ( liberateCase ) where
11 #include "HsVersions.h"
15 liberateCase = panic "LiberateCase.liberateCase: ToDo"
17 {- LATER: to end of file:
18 import CoreUnfold ( UnfoldingGuidance(..) )
19 import Id ( localiseId )
20 import IdInfo { InlinePragInfo(..) }
26 This module walks over @Core@, and looks for @case@ on free variables.
28 if there is case on a free on the route to the recursive call,
29 then the recursive call is replaced with an unfolding.
38 => the inner f is replaced.
47 (note the NEED for shadowing)
49 => Run Andr\'e's wonder pass ...
56 Better code, because 'a' is free inside the inner letrec, rather
57 than needing projection from v.
60 To think about (Apr 94)
63 Main worry: duplicating code excessively. At the moment we duplicate
64 the entire binding group once at each recursive call. But there may
65 be a group of recursive calls which share a common set of evaluated
66 free variables, in which case the duplication is a plain waste.
68 Another thing we could consider adding is some unfold-threshold thing,
69 so that we'll only duplicate if the size of the group rhss isn't too
75 The ``level'' of a binder tells how many
76 recursive defns lexically enclose the binding
77 A recursive defn "encloses" its RHS, not its
80 letrec f = let g = ... in ...
85 Here, the level of @f@ is zero, the level of @g@ is one,
86 and the level of @h@ is zero (NB not one).
89 type LibCaseLevel = Int
91 topLevel :: LibCaseLevel
98 Int -- Bomb-out size for deciding if
99 -- potential liberatees are too big.
100 -- (passed in from cmd-line args)
102 LibCaseLevel -- Current level
104 (IdEnv LibCaseLevel) -- Binds all non-top-level in-scope Ids
105 -- (top-level and imported things have
108 (IdEnv CoreBinding)-- Binds *only* recursively defined
109 -- Ids, to their own binding group,
110 -- and *only* in their own RHSs
112 [(Id,LibCaseLevel)] -- Each of these Ids was scrutinised by an
113 -- enclosing case expression, with the
114 -- specified number of enclosing
115 -- recursive bindings; furthermore,
116 -- the Id is bound at a lower level
117 -- than the case expression. The
118 -- order is insignificant; it's a bag
121 initEnv :: Int -> LibCaseEnv
122 initEnv bomb_size = LibCaseEnv bomb_size 0 nullIdEnv nullIdEnv []
124 bombOutSize (LibCaseEnv bomb_size _ _ _ _) = bomb_size
131 liberateCase :: Int -> [CoreBinding] -> [CoreBinding]
132 liberateCase bomb_size prog
133 = do_prog (initEnv bomb_size) prog
136 do_prog env (bind:binds) = bind' : do_prog env' binds
138 (env', bind') = libCaseBind env bind
145 libCaseBind :: LibCaseEnv -> CoreBinding -> (LibCaseEnv, CoreBinding)
147 libCaseBind env (NonRec binder rhs)
148 = (addBinders env [binder], NonRec binder (libCase env rhs))
150 libCaseBind env (Rec pairs)
151 = (env_body, Rec pairs')
153 (binders, rhss) = unzip pairs
155 env_body = addBinders env binders
157 pairs' = [(binder, libCase env_rhs rhs) | (binder,rhs) <- pairs]
159 env_rhs = if all rhs_small_enough rhss then extended_env else env
161 -- We extend the rec-env by binding each Id to its rhs, first
162 -- processing the rhs with an *un-extended* environment, so
163 -- that the same process doesn't occur for ever!
166 = addRecBinds env [ (localiseId binder, libCase env_body rhs)
167 | (binder, rhs) <- pairs ]
169 -- Why "localiseId" above? Because we're creating a new local
170 -- copy of the original binding. In particular, the original
171 -- binding might have been for a top-level, and this copy clearly
172 -- will not be top-level!
174 -- It is enough to change just the binder, because subsequent
175 -- simplification will propagate the right info from the binder.
177 -- Why does it matter? Because the codeGen keeps a separate
178 -- environment for top-level Ids, and it is disastrous for it
179 -- to think that something is top-level when it isn't.
182 = case (calcUnfoldingGuidance NoPragmaInfo lIBERATE_BOMB_SIZE rhs) of
184 _ -> True -- we didn't BOMB, so it must be OK
186 lIBERATE_BOMB_SIZE = bombOutSize env
194 libCase :: LibCaseEnv
198 libCase env (Lit lit) = Lit lit
199 libCase env (Var v) = mkCoLetsNoUnboxed (libCaseId env v) (Var v)
200 libCase env (App fun arg) = mkCoLetsNoUnboxed (libCaseAtom env arg) (App (libCase env fun) arg)
201 libCase env (CoTyApp fun ty) = CoTyApp (libCase env fun) ty
202 libCase env (Con con tys args) = mkCoLetsNoUnboxed (libCaseAtoms env args) (Con con tys args)
203 libCase env (Prim op tys args) = mkCoLetsNoUnboxed (libCaseAtoms env args) (Prim op tys args)
204 libCase env (CoTyLam tv body) = CoTyLam tv (libCase env body)
205 libCase env (Note note body) = Note note (libCase env body)
207 libCase env (Lam binder body)
208 = Lam binder (libCase (addBinders env [binder]) body)
210 libCase env (Let bind body)
211 = Let bind' (libCase env_body body)
213 (env_body, bind') = libCaseBind env bind
215 libCase env (Case scrut alts)
216 = Case (libCase env scrut) (libCaseAlts env_alts alts)
218 env_alts = case scrut of
219 Var scrut_var -> addScrutedVar env scrut_var
228 libCaseAlts env (AlgAlts alts deflt)
229 = AlgAlts (map do_alt alts) (libCaseDeflt env deflt)
231 do_alt (con,args,rhs) = (con, args, libCase (addBinders env args) rhs)
233 libCaseAlts env (PrimAlts alts deflt)
234 = PrimAlts (map do_alt alts) (libCaseDeflt env deflt)
236 do_alt (lit,rhs) = (lit, libCase env rhs)
238 libCaseDeflt env NoDefault
240 libCaseDeflt env (BindDefault binder rhs)
241 = BindDefault binder (libCase (addBinders env [binder]) rhs)
247 libCaseAtoms :: LibCaseEnv -> [CoreArg] -> [CoreBinding]
248 libCaseAtoms env atoms = concat [libCaseAtom env atom | atom <- atoms]
250 libCaseAtom :: LibCaseEnv -> CoreArg -> [CoreBinding]
251 libCaseAtom env (VarArg arg_id) = libCaseId env arg_id
252 libCaseAtom env (LitArg lit) = []
254 libCaseId :: LibCaseEnv -> Id -> [CoreBinding]
256 | maybeToBool maybe_rec_bind && -- It's a use of a recursive thing
257 there_are_free_scruts -- with free vars scrutinised in RHS
264 maybe_rec_bind :: Maybe CoreBinding -- The binding of the recursive thingy
265 maybe_rec_bind = lookupRecId env v
266 Just the_bind = maybe_rec_bind
268 rec_id_level = lookupLevel env v
270 there_are_free_scruts = freeScruts env rec_id_level
278 addBinders :: LibCaseEnv -> [Id] -> LibCaseEnv
279 addBinders (LibCaseEnv bomb lvl lvl_env rec_env scruts) binders
280 = LibCaseEnv bomb lvl lvl_env' rec_env scruts
282 lvl_env' = growIdEnvList lvl_env (binders `zip` repeat lvl)
284 addRecBinds :: LibCaseEnv -> [(Id,CoreExpr)] -> LibCaseEnv
285 addRecBinds (LibCaseEnv bomb lvl lvl_env rec_env scruts) pairs
286 = LibCaseEnv bomb lvl' lvl_env' rec_env' scruts
289 lvl_env' = growIdEnvList lvl_env [(binder,lvl) | (binder,_) <- pairs]
290 rec_env' = growIdEnvList rec_env [(binder, Rec pairs) | (binder,_) <- pairs]
292 addScrutedVar :: LibCaseEnv
293 -> Id -- This Id is being scrutinised by a case expression
296 addScrutedVar env@(LibCaseEnv bomb lvl lvl_env rec_env scruts) scrut_var
298 = LibCaseEnv bomb lvl lvl_env rec_env scruts'
299 -- Add to scruts iff the scrut_var is being scrutinised at
300 -- a deeper level than its defn
304 scruts' = (scrut_var, lvl) : scruts
305 bind_lvl = case lookupIdEnv lvl_env scrut_var of
309 lookupRecId :: LibCaseEnv -> Id -> Maybe CoreBinding
310 lookupRecId (LibCaseEnv bomb lvl lvl_env rec_env scruts) id
312 = lookupIdEnv rec_env id
314 = case (lookupIdEnv rec_env id) of
319 lookupLevel :: LibCaseEnv -> Id -> LibCaseLevel
320 lookupLevel (LibCaseEnv bomb lvl lvl_env rec_env scruts) id
321 = case lookupIdEnv lvl_env id of
325 freeScruts :: LibCaseEnv
326 -> LibCaseLevel -- Level of the recursive Id
327 -> Bool -- True <=> there is an enclosing case of a variable
328 -- bound outside (ie level <=) the recursive Id.
329 freeScruts (LibCaseEnv bomb lvl lvl_env rec_env scruts) rec_bind_lvl
330 = not (null free_scruts)
332 free_scruts = [v | (v,lvl) <- scruts, lvl > rec_bind_lvl]