2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
4 \section[FloatOut]{Float bindings outwards (towards the top level)}
6 ``Long-distance'' floating of bindings towards the top level.
9 #include "HsVersions.h"
11 module FloatOut ( floatOutwards ) where
14 IMPORT_1_3(List(partition))
18 import CmdLineOpts ( opt_D_verbose_core2core, opt_D_simplifier_stats )
19 import CostCentre ( dupifyCC, CostCentre )
20 import Id ( nullIdEnv, addOneToIdEnv, growIdEnvList, SYN_IE(IdEnv),
21 GenId{-instance Outputable-}, SYN_IE(Id)
23 import Outputable ( Outputable(..){-instance (,)-} )
25 import PprStyle ( PprStyle(..) )
26 import PprType ( GenTyVar )
27 import Pretty ( Doc, int, ptext, hcat, vcat )
28 import SetLevels -- all of it
29 import TyVar ( GenTyVar{-instance Eq-}, SYN_IE(TyVar) )
30 import Unique ( Unique{-instance Eq-} )
31 import UniqSupply ( UniqSupply )
32 import Usage ( SYN_IE(UVar) )
33 import Util ( pprTrace, panic )
39 At the moment we never float a binding out to between two adjacent
43 \x y -> let t = x+x in ...
45 \x -> let t = x+x in \y -> ...
47 Reason: this is less efficient in the case where the original lambda
48 is never partially applied.
50 But there's a case I've seen where this might not be true. Consider:
56 elem' x (y:ys) = x==y || elem' x ys
58 It turns out that this generates a subexpression of the form
60 \deq x ys -> let eq = eqFromEqDict deq in ...
62 which might usefully be separated to
64 \deq -> let eq = eqFromEqDict deq in \xy -> ...
66 Well, maybe. We don't do this at the moment.
69 type LevelledExpr = GenCoreExpr (Id, Level) Id TyVar UVar
70 type LevelledBind = GenCoreBinding (Id, Level) Id TyVar UVar
71 type FloatingBind = (Level, Floater)
72 type FloatingBinds = [FloatingBind]
75 = LetFloater CoreBinding
76 | CaseFloater (CoreExpr -> CoreExpr)
77 -- A CoreExpr with a hole in it:
78 -- "Give me a right-hand side of the
79 -- (usually single) alternative, and
80 -- I'll build the case..."
83 %************************************************************************
85 \subsection[floatOutwards]{@floatOutwards@: let-floating interface function}
87 %************************************************************************
90 floatOutwards :: UniqSupply -> [CoreBinding] -> [CoreBinding]
93 = case (setLevels pgm us) of { annotated_w_levels ->
95 case (unzip (map floatTopBind annotated_w_levels))
96 of { (fss, final_toplev_binds_s) ->
98 (if opt_D_verbose_core2core
99 then pprTrace "Levels added:\n"
100 (vcat (map (ppr PprDebug) annotated_w_levels))
103 ( if not (opt_D_simplifier_stats) then
107 (tlets, ntlets, lams) = get_stats (sum_stats fss)
109 pprTrace "FloatOut stats: " (hcat [
110 int tlets, ptext SLIT(" Lets floated to top level; "),
111 int ntlets, ptext SLIT(" Lets floated elsewhere; from "),
112 int lams, ptext SLIT(" Lambda groups")])
114 concat final_toplev_binds_s
117 floatTopBind bind@(NonRec _ _)
118 = case (floatBind nullIdEnv tOP_LEVEL bind) of { (fs, floats, bind', _) ->
119 (fs, floatsToBinds floats ++ [bind'])
122 floatTopBind bind@(Rec _)
123 = case (floatBind nullIdEnv tOP_LEVEL bind) of { (fs, floats, Rec pairs', _) ->
124 -- Actually floats will be empty
125 --false:ASSERT(null floats)
126 (fs, [Rec (floatsToBindPairs floats ++ pairs')])
130 %************************************************************************
132 \subsection[FloatOut-Bind]{Floating in a binding (the business end)}
134 %************************************************************************
138 floatBind :: IdEnv Level
141 -> (FloatStats, FloatingBinds, CoreBinding, IdEnv Level)
143 floatBind env lvl (NonRec (name,level) rhs)
144 = case (floatExpr env level rhs) of { (fs, rhs_floats, rhs') ->
146 -- A good dumping point
147 case (partitionByMajorLevel level rhs_floats) of { (rhs_floats', heres) ->
150 NonRec name (install heres rhs'),
151 addOneToIdEnv env name level)
154 floatBind env lvl bind@(Rec pairs)
155 = case (unzip3 (map do_pair pairs)) of { (fss, rhss_floats, new_pairs) ->
157 if not (isTopLvl bind_level) then
159 (sum_stats fss, concat rhss_floats, Rec new_pairs, new_env)
161 {- In a recursive binding, destined for the top level (only),
162 the rhs floats may contain
163 references to the bound things. For example
165 f = ...(let v = ...f... in b) ...
172 and hence we must (pessimistically) make all the floats recursive
173 with the top binding. Later dependency analysis will unravel it.
178 Rec (new_pairs ++ floatsToBindPairs (concat rhss_floats)),
183 new_env = growIdEnvList env (map fst pairs)
185 bind_level = getBindLevel bind
187 do_pair ((name, level), rhs)
188 = case (floatExpr new_env level rhs) of { (fs, rhs_floats, rhs') ->
190 -- A good dumping point
191 case (partitionByMajorLevel level rhs_floats) of { (rhs_floats', heres) ->
193 (fs, rhs_floats', (name, install heres rhs'))
197 %************************************************************************
199 \subsection[FloatOut-Expr]{Floating in expressions}
201 %************************************************************************
204 floatExpr :: IdEnv Level
207 -> (FloatStats, FloatingBinds, CoreExpr)
209 floatExpr env _ (Var v) = (zero_stats, [], Var v)
210 floatExpr env _ (Lit l) = (zero_stats, [], Lit l)
211 floatExpr env _ (Prim op as) = (zero_stats, [], Prim op as)
212 floatExpr env _ (Con con as) = (zero_stats, [], Con con as)
214 floatExpr env lvl (App e a)
215 = case (floatExpr env lvl e) of { (fs, floating_defns, e') ->
216 (fs, floating_defns, App e' a) }
218 floatExpr env lvl (Lam (UsageBinder _) e)
219 = panic "FloatOut.floatExpr: Lam UsageBinder"
221 floatExpr env lvl (Lam (TyBinder tv) e)
223 incd_lvl = incMinorLvl lvl
225 case (floatExpr env incd_lvl e) of { (fs, floats, e') ->
227 -- Dump any bindings which absolutely cannot go any further
228 case (partitionByLevel incd_lvl floats) of { (floats', heres) ->
230 (fs, floats', Lam (TyBinder tv) (install heres e'))
233 floatExpr env lvl (Lam (ValBinder (arg,incd_lvl)) rhs)
235 new_env = addOneToIdEnv env arg incd_lvl
237 case (floatExpr new_env incd_lvl rhs) of { (fs, floats, rhs') ->
239 -- Dump any bindings which absolutely cannot go any further
240 case (partitionByLevel incd_lvl floats) of { (floats', heres) ->
242 (add_to_stats fs floats',
244 Lam (ValBinder arg) (install heres rhs'))
247 floatExpr env lvl (SCC cc expr)
248 = case (floatExpr env lvl expr) of { (fs, floating_defns, expr') ->
250 -- annotate bindings floated outwards past an scc expression
251 -- with the cc. We mark that cc as "duplicated", though.
253 annotated_defns = annotate (dupifyCC cc) floating_defns
255 (fs, annotated_defns, SCC cc expr') }
257 annotate :: CostCentre -> FloatingBinds -> FloatingBinds
259 annotate dupd_cc defn_groups
260 = [ (level, ann_bind floater) | (level, floater) <- defn_groups ]
262 ann_bind (LetFloater (NonRec binder rhs))
263 = LetFloater (NonRec binder (ann_rhs rhs))
265 ann_bind (LetFloater (Rec pairs))
266 = LetFloater (Rec [(binder, ann_rhs rhs) | (binder, rhs) <- pairs])
268 ann_bind (CaseFloater fn) = CaseFloater ( \ rhs -> SCC dupd_cc (fn rhs) )
270 ann_rhs (Lam arg e) = Lam arg (ann_rhs e)
271 ann_rhs rhs@(Con _ _) = rhs -- no point in scc'ing WHNF data
272 ann_rhs rhs = SCC dupd_cc rhs
274 -- Note: Nested SCC's are preserved for the benefit of
275 -- cost centre stack profiling (Durham)
277 floatExpr env lvl (Coerce c ty expr)
278 = case (floatExpr env lvl expr) of { (fs, floating_defns, expr') ->
279 (fs, floating_defns, Coerce c ty expr') }
281 floatExpr env lvl (Let bind body)
282 = case (floatBind env lvl bind) of { (fsb, rhs_floats, bind', new_env) ->
283 case (floatExpr new_env lvl body) of { (fse, body_floats, body') ->
285 rhs_floats ++ [(bind_lvl, LetFloater bind')] ++ body_floats,
289 bind_lvl = getBindLevel bind
291 floatExpr env lvl (Case scrut alts)
292 = case (floatExpr env lvl scrut) of { (fse, fde, scrut') ->
294 case (scrut', float_alts alts) of
295 (_, (fsa, fda, alts')) ->
296 (add_stats fse fsa, fda ++ fde, Case scrut' alts')
298 {- OLD CASE-FLOATING CODE: DROPPED FOR NOW. (SLPJ 7/2/94)
300 (Var scrut_var, (fda, AlgAlts [(con,bs,rhs')] NoDefault))
301 | scrut_var_lvl `ltMajLvl` lvl ->
303 -- Candidate for case floater; scrutinising a variable; it can
304 -- escape outside a lambda; there's only one alternative.
305 (fda ++ fde ++ [case_floater], rhs')
308 case_floater = (scrut_var_lvl, CaseFloater fn)
309 fn body = Case scrut' (AlgAlts [(con,bs,body)] NoDefault)
310 scrut_var_lvl = case lookupIdEnv env scrut_var of
312 Just lvl -> unTopify lvl
314 END OF CASE FLOATING DROPPED -}
316 incd_lvl = incMinorLvl lvl
318 partition_fn = partitionByMajorLevel
321 We don't want to be too keen about floating lets out of case alternatives
322 because they may benefit from seeing the evaluation done by the case.
324 The main reason for doing this is to allocate in fewer larger blocks
325 but that's really an STG-level issue.
328 -- Just one alternative, then dump only
329 -- what *has* to be dumped
330 AlgAlts [_] NoDefault -> partitionByLevel
331 AlgAlts [] (BindDefault _ _) -> partitionByLevel
332 PrimAlts [_] NoDefault -> partitionByLevel
333 PrimAlts [] (BindDefault _ _) -> partitionByLevel
335 -- If there's more than one alternative, then
336 -- this is a dumping point
337 other -> partitionByMajorLevel
340 float_alts (AlgAlts alts deflt)
341 = case (float_deflt deflt) of { (fsd, fdd, deflt') ->
342 case (unzip3 (map float_alg_alt alts)) of { (fsas, fdas, alts') ->
343 (foldr add_stats fsd fsas,
345 AlgAlts alts' deflt') }}
347 float_alts (PrimAlts alts deflt)
348 = case (float_deflt deflt) of { (fsd, fdd, deflt') ->
349 case (unzip3 (map float_prim_alt alts)) of { (fsas, fdas, alts') ->
350 (foldr add_stats fsd fsas,
352 PrimAlts alts' deflt') }}
355 float_alg_alt (con, bs, rhs)
358 new_env = growIdEnvList env bs
360 case (floatExpr new_env incd_lvl rhs) of { (fs, rhs_floats, rhs') ->
361 case (partition_fn incd_lvl rhs_floats) of { (rhs_floats', heres) ->
362 (fs, rhs_floats', (con, bs', install heres rhs')) }}
365 float_prim_alt (lit, rhs)
366 = case (floatExpr env incd_lvl rhs) of { (fs, rhs_floats, rhs') ->
367 case (partition_fn incd_lvl rhs_floats) of { (rhs_floats', heres) ->
368 (fs, rhs_floats', (lit, install heres rhs')) }}
371 float_deflt NoDefault = (zero_stats, [], NoDefault)
373 float_deflt (BindDefault (b,lvl) rhs)
374 = case (floatExpr new_env lvl rhs) of { (fs, rhs_floats, rhs') ->
375 case (partition_fn incd_lvl rhs_floats) of { (rhs_floats', heres) ->
376 (fs, rhs_floats', BindDefault b (install heres rhs')) }}
378 new_env = addOneToIdEnv env b lvl
381 %************************************************************************
383 \subsection{Utility bits for floating stats}
385 %************************************************************************
387 I didn't implement this with unboxed numbers. I don't want to be too
388 strict in this stuff, as it is rarely turned on. (WDP 95/09)
392 = FlS Int -- Number of top-floats * lambda groups they've been past
393 Int -- Number of non-top-floats * lambda groups they've been past
394 Int -- Number of lambda (groups) seen
396 get_stats (FlS a b c) = (a, b, c)
398 zero_stats = FlS 0 0 0
400 sum_stats xs = foldr add_stats zero_stats xs
402 add_stats (FlS a1 b1 c1) (FlS a2 b2 c2)
403 = FlS (a1 + a2) (b1 + b2) (c1 + c2)
405 add_to_stats (FlS a b c) floats
406 = FlS (a + length top_floats) (b + length other_floats) (c + 1)
408 (top_floats, other_floats) = partition to_very_top floats
410 to_very_top (my_lvl, _) = isTopLvl my_lvl
413 %************************************************************************
415 \subsection{Utility bits for floating}
417 %************************************************************************
420 getBindLevel (NonRec (_, lvl) _) = lvl
421 getBindLevel (Rec (((_,lvl), _) : _)) = lvl
425 partitionByMajorLevel, partitionByLevel
426 :: Level -- Partitioning level
428 -> FloatingBinds -- Defns to be divided into 2 piles...
430 -> (FloatingBinds, -- Defns with level strictly < partition level,
431 FloatingBinds) -- The rest
434 partitionByMajorLevel ctxt_lvl defns
435 = partition float_further defns
437 float_further (my_lvl, _) = my_lvl `ltMajLvl` ctxt_lvl ||
440 partitionByLevel ctxt_lvl defns
441 = partition float_further defns
443 float_further (my_lvl, _) = my_lvl `ltLvl` ctxt_lvl
447 floatsToBinds :: FloatingBinds -> [CoreBinding]
448 floatsToBinds floats = map get_bind floats
450 get_bind (_, LetFloater bind) = bind
451 get_bind (_, CaseFloater _) = panic "floatsToBinds"
453 floatsToBindPairs :: FloatingBinds -> [(Id,CoreExpr)]
455 floatsToBindPairs floats = concat (map mk_pairs floats)
457 mk_pairs (_, LetFloater (Rec pairs)) = pairs
458 mk_pairs (_, LetFloater (NonRec binder rhs)) = [(binder,rhs)]
459 mk_pairs (_, CaseFloater _) = panic "floatsToBindPairs"
461 install :: FloatingBinds -> CoreExpr -> CoreExpr
463 install defn_groups expr
464 = foldr install_group expr defn_groups
466 install_group (_, LetFloater defns) body = Let defns body
467 install_group (_, CaseFloater fn) body = fn body