2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
4 %************************************************************************
6 \section[OccurAnal]{Occurrence analysis pass}
8 %************************************************************************
10 The occurrence analyser re-typechecks a core expression, returning a new
11 core expression with (hopefully) improved usage information.
15 occurAnalyseBinds, occurAnalyseExpr, occurAnalyseGlobalExpr
18 #include "HsVersions.h"
21 import CmdLineOpts ( opt_D_dump_occur_anal, SimplifierSwitch(..) )
23 import Digraph ( stronglyConnCompR, SCC(..) )
24 import Id ( idWantsToBeINLINEd, addNoInlinePragma, nukeNoInlinePragma,
26 emptyIdSet, unionIdSets, mkIdSet,
29 nullIdEnv, unitIdEnv, combineIdEnvs,
30 delOneFromIdEnv, delManyFromIdEnv, isNullIdEnv,
31 mapIdEnv, lookupIdEnv, IdEnv,
34 import Name ( isExported, isLocallyDefined )
35 import Type ( splitFunTy_maybe, splitForAllTys )
36 import Maybes ( maybeToBool )
38 import PprType ( GenType{-instance Outputable-}, GenTyVar{-ditto-} )
39 import TyVar ( GenTyVar{-instance Eq-} )
40 import Unique ( Unique{-instance Eq-}, u2i )
41 import UniqFM ( keysUFM )
42 import Util ( zipWithEqual )
45 isSpecPragmaId_maybe x = Nothing -- ToDo:!trace "OccurAnal.isSpecPragmaId_maybe"
49 %************************************************************************
51 \subsection[OccurAnal-types]{Data types}
53 %************************************************************************
58 Bool -- Keep-unused-bindings flag
59 -- False <=> OK to chuck away binding
60 -- and ignore occurrences within it
61 Bool -- Keep-spec-pragma-ids flag
62 -- False <=> OK to chuck away spec pragma bindings
63 -- and ignore occurrences within it
64 Bool -- Keep-conjurable flag
65 -- False <=> OK to throw away *dead*
66 -- "conjurable" Ids; at the moment, that
67 -- *only* means constant methods, which
68 -- are top-level. A use of a "conjurable"
69 -- Id may appear out of thin air -- e.g.,
70 -- specialiser conjuring up refs to const methods.
71 Bool -- IgnoreINLINEPragma flag
72 -- False <=> OK to use INLINEPragma information
73 -- True <=> ignore INLINEPragma information
75 (Id -> IdSet -> Bool) -- Tells whether an Id occurrence is interesting,
76 -- given the set of in-scope variables
81 addNewCands :: OccEnv -> [Id] -> OccEnv
82 addNewCands (OccEnv kd ks kc ip ifun cands) ids
83 = OccEnv kd ks kc ip ifun (cands `unionIdSets` mkIdSet ids)
85 addNewCand :: OccEnv -> Id -> OccEnv
86 addNewCand (OccEnv ks kd kc ip ifun cands) id
87 = OccEnv kd ks kc ip ifun (addOneToIdSet cands id)
89 isCandidate :: OccEnv -> Id -> Bool
90 isCandidate (OccEnv _ _ _ _ ifun cands) id = ifun id cands
92 inlineMe :: OccEnv -> Id -> Bool
94 = {- See comments with simplIdWantsToBeINLINEd in SimplUtils.lhs
95 not ignore_inline_prag &&
99 keepUnusedBinding :: OccEnv -> Id -> Bool
100 keepUnusedBinding (OccEnv keep_dead keep_spec keep_conjurable _ _ _) binder
101 = keep_dead || (keep_spec && maybeToBool (isSpecPragmaId_maybe binder))
104 keepBecauseConjurable :: OccEnv -> Id -> Bool
105 keepBecauseConjurable (OccEnv _ _ keep_conjurable _ _ _) binder
107 {- keep_conjurable && isConstMethodId binder -}
110 type UsageDetails = IdEnv BinderInfo -- A finite map from ids to their usage
112 combineUsageDetails, combineAltsUsageDetails
113 :: UsageDetails -> UsageDetails -> UsageDetails
115 combineUsageDetails usage1 usage2
116 = combineIdEnvs addBinderInfo usage1 usage2
118 combineAltsUsageDetails usage1 usage2
119 = combineIdEnvs orBinderInfo usage1 usage2
121 addOneOcc :: UsageDetails -> Id -> BinderInfo -> UsageDetails
122 addOneOcc usage id info
123 = combineIdEnvs addBinderInfo usage (unitIdEnv id info)
124 -- ToDo: make this more efficient
126 emptyDetails = (nullIdEnv :: UsageDetails)
128 unitDetails id info = (unitIdEnv id info :: UsageDetails)
130 tagBinders :: UsageDetails -- Of scope
132 -> (UsageDetails, -- Details with binders removed
133 [(Id,BinderInfo)]) -- Tagged binders
135 tagBinders usage binders =
137 usage' = usage `delManyFromIdEnv` binders
138 uss = [ (binder, usage_of usage binder) | binder <- binders ]
140 if isNullIdEnv usage' then
145 = (usage `delManyFromIdEnv` binders,
146 [ (binder, usage_of usage binder) | binder <- binders ]
149 tagBinder :: UsageDetails -- Of scope
151 -> (UsageDetails, -- Details with binders removed
152 (Id,BinderInfo)) -- Tagged binders
154 tagBinder usage binder =
156 usage' = usage `delOneFromIdEnv` binder
157 us = usage_of usage binder
159 if isNullIdEnv usage' then -- Bogus test to force evaluation.
160 (usage', (binder, us))
162 (usage', (binder, us))
164 if isDeadOcc us then -- Ditto
170 usage_of usage binder
171 | isExported binder = noBinderInfo -- Visible-elsewhere things count as many
173 = case (lookupIdEnv usage binder) of
174 Nothing -> deadOccurrence
177 isNeeded env usage binder
178 = if isDeadOcc (usage_of usage binder) then
179 keepUnusedBinding env binder -- Maybe keep it anyway
185 %************************************************************************
187 \subsection[OccurAnal-main]{Counting occurrences: main function}
189 %************************************************************************
191 Here's the externally-callable interface:
195 :: [CoreBinding] -- input
196 -> (SimplifierSwitch -> Bool)
197 -> [SimplifiableCoreBinding] -- output
199 occurAnalyseBinds binds simplifier_sw_chkr
200 | opt_D_dump_occur_anal = pprTrace "OccurAnal:"
201 (vcat (map ppr_bind binds'))
205 (_, binds') = doo initial_env binds
207 initial_env = OccEnv (simplifier_sw_chkr KeepUnusedBindings)
208 (simplifier_sw_chkr KeepSpecPragmaIds)
209 (not (simplifier_sw_chkr SimplMayDeleteConjurableIds))
210 (simplifier_sw_chkr IgnoreINLINEPragma)
211 (\id in_scope -> isLocallyDefined id) -- Anything local is interesting
212 emptyIdSet -- Not actually used
214 doo env [] = (emptyDetails, [])
216 = (final_usage, new_binds ++ the_rest)
218 new_env = env `addNewCands` (bindersOf bind)
219 (binds_usage, the_rest) = doo new_env binds
220 (final_usage, new_binds) = occAnalBind env bind binds_usage
222 -- This really ought to be done properly by PprCore, but
223 -- it isn't. pprCoreBinding only works on Id binders, and
224 -- the general case is complicated by the fact that it has to work
225 -- for interface files too. Sigh
227 ppr_bind bind@(NonRec binder expr)
230 ppr_bind bind@(Rec binds)
231 = vcat [ptext SLIT("Rec {"),
233 ptext SLIT("end Rec }")]
237 occurAnalyseExpr :: (Id -> Bool) -- Tells if a variable is interesting
239 -> (IdEnv BinderInfo, -- Occ info for interesting free vars
240 SimplifiableCoreExpr)
242 occurAnalyseExpr interesting expr
243 = occAnal initial_env expr
245 initial_env = OccEnv False {- Drop unused bindings -}
246 False {- Drop SpecPragmaId bindings -}
247 True {- Keep conjurable Ids -}
248 False {- Do not ignore INLINE Pragma -}
249 (\id locals -> interesting id || elementOfIdSet id locals)
252 occurAnalyseGlobalExpr :: CoreExpr -> SimplifiableCoreExpr
253 occurAnalyseGlobalExpr expr
254 = -- Top level expr, so no interesting free vars, and
255 -- discard occurence info returned
256 snd (occurAnalyseExpr (\_ -> False) expr)
259 %************************************************************************
261 \subsection[OccurAnal-main]{Counting occurrences: main function}
263 %************************************************************************
269 type Node details = (details, Int, [Int]) -- The Ints are gotten from the Unique,
270 -- which is gotten from the Id.
271 type Details1 = (Id, (UsageDetails, SimplifiableCoreExpr))
272 type Details2 = ((Id, BinderInfo), SimplifiableCoreExpr)
275 occAnalBind :: OccEnv
277 -> UsageDetails -- Usage details of scope
278 -> (UsageDetails, -- Of the whole let(rec)
279 [SimplifiableCoreBinding])
281 occAnalBind env (NonRec binder rhs) body_usage
282 | isNeeded env body_usage binder -- It's mentioned in body
283 = (final_body_usage `combineUsageDetails` rhs_usage,
284 [NonRec tagged_binder rhs'])
286 | otherwise -- Not mentioned, so drop dead code
290 binder' = nukeNoInlinePragma binder
291 (rhs_usage, rhs') = occAnalRhs env binder' rhs
292 (final_body_usage, tagged_binder) = tagBinder body_usage binder'
295 Dropping dead code for recursive bindings is done in a very simple way:
297 the entire set of bindings is dropped if none of its binders are
298 mentioned in its body; otherwise none are.
300 This seems to miss an obvious improvement.
315 Now @f@ is unused. But dependency analysis will sort this out into a
316 @letrec@ for @g@ and a @let@ for @f@, and then @f@ will get dropped.
317 It isn't easy to do a perfect job in one blow. Consider
331 occAnalBind env (Rec pairs) body_usage
332 = foldr (_scc_ "occAnalBind.dofinal" do_final_bind) (body_usage, []) sccs
334 pp_item (_, bndr, _) = ppr bndr
336 binders = map fst pairs
337 new_env = env `addNewCands` binders
339 analysed_pairs :: [Details1]
340 analysed_pairs = [(nukeNoInlinePragma bndr, occAnalRhs new_env bndr rhs) | (bndr,rhs) <- pairs]
342 sccs :: [SCC (Node Details1)]
343 sccs = _scc_ "occAnalBind.scc" stronglyConnCompR edges
346 ---- stuff for dependency analysis of binds -------------------------------
347 edges :: [Node Details1]
348 edges = _scc_ "occAnalBind.assoc"
349 [ (pair, IBOX(u2i (idUnique id)), edges_from rhs_usage)
350 | pair@(id, (rhs_usage, rhs)) <- analysed_pairs
353 -- (a -> b) means a mentions b
354 -- Given the usage details (a UFM that gives occ info for each free var of
355 -- the RHS) we can get the list of free vars -- or rather their Int keys --
356 -- by just extracting the keys from the finite map. Grimy, but fast.
357 -- Previously we had this:
358 -- [ bndr | bndr <- bndrs,
359 -- maybeToBool (lookupIdEnv rhs_usage bndr)]
360 -- which has n**2 cost, and this meant that edges_from alone
361 -- consumed 10% of total runtime!
362 edges_from :: UsageDetails -> [Int]
363 edges_from rhs_usage = _scc_ "occAnalBind.edges_from"
366 ---- stuff to "re-constitute" bindings from dependency-analysis info ------
369 do_final_bind (AcyclicSCC ((bndr, (rhs_usage, rhs')), _, _)) (body_usage, binds_so_far)
370 | isNeeded env body_usage bndr
371 = (combined_usage, new_bind : binds_so_far)
373 = (body_usage, binds_so_far) -- Dead code
375 total_usage = combineUsageDetails body_usage rhs_usage
376 (combined_usage, tagged_bndr) = tagBinder total_usage bndr
377 new_bind = NonRec tagged_bndr rhs'
380 do_final_bind (CyclicSCC cycle) (body_usage, binds_so_far)
381 | any (isNeeded env body_usage) bndrs
382 = (combined_usage, final_bind:binds_so_far)
384 = (body_usage, binds_so_far) -- Dead code
386 pairs = [pair | (pair, _, _) <- cycle]
387 bndrs = [bndr | (bndr, _) <- pairs]
388 rhs_usages = [rhs_usage | (_, (rhs_usage, _)) <- pairs]
389 total_usage = foldr combineUsageDetails body_usage rhs_usages
390 (combined_usage, tagged_binders) = tagBinders total_usage bndrs
391 final_bind = Rec (reOrderRec env new_cycle)
393 new_cycle = CyclicSCC (zipWithEqual "occAnalBind" mk_new_bind tagged_binders cycle)
394 mk_new_bind tagged_bndr ((_, (_, rhs')), key, keys) = ((tagged_bndr, rhs'), key, keys)
397 @reOrderRec@ is applied to the list of (binder,rhs) pairs for a cyclic
398 strongly connected component (there's guaranteed to be a cycle). It returns the
400 a) in a better order,
401 b) with some of the Ids having a IMustNotBeINLINEd pragma
403 The "no-inline" Ids are sufficient to break all cycles in the SCC. This means
404 that the simplifier can guarantee not to loop provided it never records an inlining
405 for these no-inline guys.
407 Furthermore, the order of the binds is such that if we neglect dependencies
408 on the no-inline Ids then the binds are topologically sorted. This means
409 that the simplifier will generally do a good job if it works from top bottom,
410 recording inlinings for any Ids which aren't marked as "no-inline" as it goes.
412 Here's a case that bit me:
420 Re-ordering doesn't change the order of bindings, but there was no loop-breaker.
422 My solution was to make a=b bindings record b as Many, rather like INLINE bindings.
423 Perhaps something cleverer would suffice.
425 You might think that you can prevent non-termination simply by making
426 sure that we simplify a recursive binding's RHS in an environment that
427 simply clones the recursive Id. But no. Consider
429 letrec f = \x -> let z = f x' in ...
436 We bind n to its *simplified* RHS, we then *re-simplify* it when
437 we inline n. Then we may well inline f; and then the same thing
440 I don't think it's possible to prevent non-termination by environment
441 manipulation in this way. Apart from anything else, successive
442 iterations of the simplifier may unroll recursive loops in cases like
443 that above. The idea of beaking every recursive loop with an
444 IMustNotBeINLINEd pragma is much much better.
450 -> SCC (Node Details2)
452 -- Sorted into a plausible order. Enough of the Ids have
453 -- dontINLINE pragmas that there are no loops left.
455 -- Non-recursive case
456 reOrderRec env (AcyclicSCC (pair, _, _)) = [pair]
458 -- Common case of simple self-recursion
459 reOrderRec env (CyclicSCC [bind])
460 = [((addNoInlinePragma bndr, occ_info), rhs)]
462 (((bndr,occ_info), rhs), _, _) = bind
464 reOrderRec env (CyclicSCC binds)
465 = -- Choose a loop breaker, mark it no-inline,
466 -- do SCC analysis on the rest, and recursively sort them out
467 concat (map (reOrderRec env) (stronglyConnCompR unchosen))
469 [((addNoInlinePragma bndr, occ_info), rhs)]
472 (chosen_pair, unchosen) = choose_loop_breaker binds
473 ((bndr,occ_info), rhs) = chosen_pair
475 -- Choosing the loop breaker; heursitic
476 choose_loop_breaker (bind@(pair, _, _) : rest)
479 = (chosen, bind : unchosen) -- Don't pick it
480 | otherwise -- Pick it
483 (chosen, unchosen) = choose_loop_breaker rest
485 bad_choice ((bndr, occ_info), rhs)
486 = var_rhs rhs -- Dont pick var RHS
487 || inlineMe env bndr -- Dont pick INLINE thing
488 || isOneFunOcc occ_info -- Dont pick single-occ thing
489 || not_fun_ty (idType bndr) -- Dont pick data-ty thing
491 -- isOneFunOcc looks for one textual occurrence, whether inside lambda or whatever.
492 -- We stick to just FunOccs because if we're not going to be able
493 -- to inline the thing on this round it might be better to pick
494 -- this one as the loop breaker. Real example (the Enum Ordering instance
496 -- rec f = \ x -> case d of (p,q,r) -> p x
497 -- g = \ x -> case d of (p,q,r) -> q x
500 -- Here, f and g occur just once; but we can't inline them into d.
501 -- On the other hand we *could* simplify those case expressions if
502 -- we didn't stupidly choose d as the loop breaker.
504 not_fun_ty ty = not (maybeToBool (splitFunTy_maybe rho_ty))
506 (_, rho_ty) = splitForAllTys ty
509 var_rhs (Var v) = True
510 var_rhs other_rhs = False
513 @occAnalRhs@ deals with the question of bindings where the Id is marked
514 by an INLINE pragma. For these we record that anything which occurs
515 in its RHS occurs many times. This pessimistically assumes that ths
516 inlined binder also occurs many times in its scope, but if it doesn't
517 we'll catch it next time round. At worst this costs an extra simplifier pass.
518 ToDo: try using the occurrence info for the inline'd binder.
520 [March 97] We do the same for atomic RHSs. Reason: see notes with reOrderRec.
524 -> Id -> CoreExpr -- Binder and rhs
525 -> (UsageDetails, SimplifiableCoreExpr)
527 occAnalRhs env id (Var v)
529 = (unitIdEnv v (markMany (funOccurrence 0)), Var v)
532 = (emptyDetails, Var v)
534 occAnalRhs env id rhs
536 = (mapIdEnv markMany rhs_usage, rhs')
542 (rhs_usage, rhs') = occAnal env rhs
550 -> (UsageDetails, -- Gives info only about the "interesting" Ids
551 SimplifiableCoreExpr)
555 = (unitIdEnv v (funOccurrence 0), Var v)
558 = (emptyDetails, Var v)
560 occAnal env (Lit lit) = (emptyDetails, Lit lit)
561 occAnal env (Prim op args) = (occAnalArgs env args, Prim op args)
564 We regard variables that occur as constructor arguments as "dangerousToDup":
568 f x = let y = expensive x in
570 (case z of {(p,q)->q}, case z of {(p,q)->q})
573 We feel free to duplicate the WHNF (True,y), but that means
574 that y may be duplicated thereby.
576 If we aren't careful we duplicate the (expensive x) call!
577 Constructors are rather like lambdas in this way.
580 occAnal env (Con con args) = (mapIdEnv markDangerousToDup (occAnalArgs env args),
583 occAnal env (SCC cc body)
584 = (mapIdEnv markInsideSCC usage, SCC cc body')
586 (usage, body') = occAnal env body
588 occAnal env (Coerce c ty body)
589 = (usage, Coerce c ty body')
591 (usage, body') = occAnal env body
593 occAnal env (App fun arg)
594 = (fun_usage `combineUsageDetails` arg_usage, App fun' arg)
596 (fun_usage, fun') = occAnal env fun
597 arg_usage = occAnalArg env arg
599 -- For value lambdas we do a special hack. Consider
601 -- If we did nothing, x is used inside the \y, so would be marked
602 -- as dangerous to dup. But in the common case where the abstraction
603 -- is applied to two arguments this is over-pessimistic.
604 -- So instead we don't take account of the \y when dealing with x's usage;
605 -- instead, the simplifier is careful when partially applying lambdas
607 occAnal env expr@(Lam (ValBinder binder) body)
608 = (mapIdEnv markDangerousToDup final_usage,
609 foldr ( \v b -> Lam (ValBinder v) b) body' tagged_binders)
611 (binders,body) = collectValBinders expr
612 (body_usage, body') = occAnal (env `addNewCands` binders) body
613 (final_usage, tagged_binders) = tagBinders body_usage binders
615 -- ANDY: WE MUST THINK ABOUT THIS! (ToDo)
616 occAnal env (Lam (TyBinder tyvar) body)
617 = case occAnal env body of { (body_usage, body') ->
618 (mapIdEnv markDangerousToDup body_usage,
619 Lam (TyBinder tyvar) body') }
621 -- (body_usage, body') = occAnal env body
623 occAnal env (Case scrut alts)
624 = case occAnalAlts env alts of { (alts_usage, alts') ->
625 case occAnal env scrut of { (scrut_usage, scrut') ->
627 det = scrut_usage `combineUsageDetails` alts_usage
629 if isNullIdEnv det then
630 (det, Case scrut' alts')
632 (det, Case scrut' alts') }}
634 (scrut_usage `combineUsageDetails` alts_usage,
637 (scrut_usage, scrut') = occAnal env scrut
638 (alts_usage, alts') = occAnalAlts env alts
641 occAnal env (Let bind body)
642 = case occAnal new_env body of { (body_usage, body') ->
643 case occAnalBind env bind body_usage of { (final_usage, new_binds) ->
644 (final_usage, foldr Let body' new_binds) }} -- mkCoLet* wants Core... (sigh)
646 new_env = env `addNewCands` (bindersOf bind)
647 -- (body_usage, body') = occAnal new_env body
648 -- (final_usage, new_binds) = occAnalBind env bind body_usage
654 occAnalAlts env (AlgAlts alts deflt)
655 = (foldr combineAltsUsageDetails deflt_usage alts_usage,
656 -- Note: combine*Alts*UsageDetails...
657 AlgAlts alts' deflt')
659 (alts_usage, alts') = unzip (map do_alt alts)
660 (deflt_usage, deflt') = occAnalDeflt env deflt
662 do_alt (con, args, rhs)
663 = (final_usage, (con, tagged_args, rhs'))
665 new_env = env `addNewCands` args
666 (rhs_usage, rhs') = occAnal new_env rhs
667 (final_usage, tagged_args) = tagBinders rhs_usage args
669 occAnalAlts env (PrimAlts alts deflt)
670 = (foldr combineAltsUsageDetails deflt_usage alts_usage,
671 -- Note: combine*Alts*UsageDetails...
672 PrimAlts alts' deflt')
674 (alts_usage, alts') = unzip (map do_alt alts)
675 (deflt_usage, deflt') = occAnalDeflt env deflt
678 = (rhs_usage, (lit, rhs'))
680 (rhs_usage, rhs') = occAnal env rhs
682 occAnalDeflt env NoDefault = (emptyDetails, NoDefault)
684 occAnalDeflt env (BindDefault binder rhs)
685 = (final_usage, BindDefault tagged_binder rhs')
687 new_env = env `addNewCand` binder
688 (rhs_usage, rhs') = occAnal new_env rhs
689 (final_usage, tagged_binder) = tagBinder rhs_usage binder
696 occAnalArgs :: OccEnv -> [CoreArg] -> UsageDetails
698 occAnalArgs env atoms
699 = foldr do_one_atom emptyDetails atoms
701 do_one_atom (VarArg v) usage
702 | isCandidate env v = addOneOcc usage v (argOccurrence 0)
704 do_one_atom other_arg usage = usage
707 occAnalArg :: OccEnv -> CoreArg -> UsageDetails
709 occAnalArg env (VarArg v)
710 | isCandidate env v = unitDetails v (argOccurrence 0)
711 | otherwise = emptyDetails
712 occAnalArg _ _ = emptyDetails