2 % (c) The AQUA Project, Glasgow University, 1993-1996
4 \section[SimplEnv]{Environment stuff for the simplifier}
9 getEnvs, setTyEnv, setIdEnv, notInScope, setSubstEnvs,
11 bindTyVar, bindTyVars, simplTy,
13 lookupIdSubst, lookupOutIdEnv,
15 bindIdToAtom, bindIdToExpr,
18 lookupRhsInfo, isEvaluated,
19 extendEnvGivenBinding, extendEnvGivenNewRhs,
20 extendEnvGivenRhsInfo,
24 getSwitchChecker, switchIsSet, getSimplIntSwitch,
25 switchOffInlining, setCaseScrutinee,
27 setEnclosingCC, getEnclosingCC,
35 InId, InBinder, InBinding, InType,
36 OutId, OutBinder, OutBinding, OutType,
38 InExpr, InAlts, InDefault, InArg,
39 OutExpr, OutAlts, OutDefault, OutArg
42 #include "HsVersions.h"
44 import BinderInfo ( orBinderInfo, andBinderInfo, noBinderInfo, isOneOcc,
45 okToInline, isOneFunOcc,
48 import CmdLineOpts ( switchIsOn, intSwitchSet, opt_UnfoldingCreationThreshold,
49 SimplifierSwitch(..), SwitchResult(..)
52 import CoreUnfold ( mkFormSummary, couldBeSmallEnoughToInline, whnfOrBottom,
53 Unfolding(..), SimpleUnfolding(..), FormSummary(..),
54 calcUnfoldingGuidance )
55 import CoreUtils ( coreExprCc )
56 import CostCentre ( CostCentre, subsumedCosts, costsAreSubsumed, noCostCentreAttached )
57 import FiniteMap -- lots of things
58 import Id ( getInlinePragma,
59 nullIdEnv, growIdEnvList, lookupIdEnv, delOneFromIdEnv,
60 addOneToIdEnv, modifyIdEnv, modifyIdEnv_Directly,
62 import Literal ( Literal{-instances-} )
63 import Maybes ( expectJust )
64 import OccurAnal ( occurAnalyseExpr )
65 import PprCore -- various instances
66 import Type ( instantiateTy, Type )
67 import TyVar ( TyVarEnv, emptyTyVarEnv, plusTyVarEnv, addToTyVarEnv, growTyVarEnvList,
68 TyVarSet, emptyTyVarSet,
71 import Unique ( Unique{-instance Outputable-}, Uniquable(..) )
72 import UniqFM ( addToUFM, addToUFM_C, ufmToList, mapUFM )
73 import Util ( Eager, returnEager, zipEqual, thenCmp, cmpList )
77 %************************************************************************
79 \subsection[Simplify-types]{Type declarations}
81 %************************************************************************
84 type InId = Id -- Not yet cloned
85 type InBinder = (InId, BinderInfo)
86 type InType = Type -- Ditto
87 type InBinding = SimplifiableCoreBinding
88 type InExpr = SimplifiableCoreExpr
89 type InAlts = SimplifiableCoreCaseAlts
90 type InDefault = SimplifiableCoreCaseDefault
91 type InArg = SimplifiableCoreArg
93 type OutId = Id -- Cloned
95 type OutType = Type -- Cloned
96 type OutBinding = CoreBinding
97 type OutExpr = CoreExpr
98 type OutAlts = CoreCaseAlts
99 type OutDefault = CoreCaseDefault
100 type OutArg = CoreArg
102 type SwitchChecker = SimplifierSwitch -> SwitchResult
105 %************************************************************************
107 \subsubsection{The @SimplEnv@ type}
109 %************************************************************************
112 INVARIANT: we assume {\em no shadowing}. (ToDo: How can we ASSERT
113 this? WDP 94/06) This allows us to neglect keeping everything paired
114 with its static environment.
116 The environment contains bindings for all
118 {\em locally-defined}
121 For such things, any unfolding is found in the environment, not in the
122 Id. Unfoldings in the Id itself are used only for imported things
123 (otherwise we get trouble because we have to simplify the unfoldings
124 inside the Ids, etc.).
130 CostCentre -- The enclosing cost-centre (when profiling)
131 SimplTypeEnv -- Maps old type variables to new clones
132 SimplValEnv -- Maps locally-bound Ids to new clones
133 ConAppMap -- Maps constructor applications back to OutIds
135 type SimplTypeEnv = (TyVarSet, -- In-scope tyvars (in result)
136 TyVarEnv Type) -- Type substitution
137 -- If t is in the in-scope set, it certainly won't be
138 -- in the domain of the substitution, and vice versa
140 type SimplValEnv = (IdEnv StuffAboutId, -- Domain includes *all* in-scope
141 -- Ids (in result), range gives info about them
142 IdEnv SubstInfo) -- Id substitution
143 -- The first envt tells what Ids are in scope; it
144 -- corresponds to the TyVarSet in SimplTypeEnv
146 -- The substitution usually maps an Id to its clone,
147 -- but if the orig defn is a let-binding, and
148 -- the RHS of the let simplifies to an atom,
149 -- we just add the binding to the substitution and elide the let.
151 -- Ids in the domain of the substitution are *not* in scope;
152 -- they *must* be substituted for the given OutArg
155 = SubstArg OutArg -- The Id maps to an already-substituted atom
156 | SubstExpr -- Id maps to an as-yet-unsimplified expression
157 (TyVarEnv Type) -- ...hence we need to capture the substitution
158 (IdEnv SubstInfo) -- environments too
161 type StuffAboutId = (OutId, -- Always has the same unique as the
162 -- Id that maps to it; but may have better
163 -- IdInfo, and a correctly-substituted type,
164 -- than the occurrences of the Id. So use
165 -- this to replace occurrences
167 BinderInfo, -- How it occurs
168 -- We keep this info so we can modify it when
169 -- something changes.
171 RhsInfo) -- Info about what it is bound to
174 The @RhsInfo@ part tells about the value to which the @OutId@ is bound.
177 data RhsInfo = NoRhsInfo
178 | OtherLit [Literal] -- It ain't one of these
179 | OtherCon [Id] -- It ain't one of these
180 | OutUnfolding CostCentre
181 SimpleUnfolding -- Already-simplified unfolding
186 nullSimplEnv :: SwitchChecker -> SimplEnv
189 = SimplEnv sw_chkr subsumedCosts (emptyTyVarSet, emptyTyVarEnv) (nullIdEnv, nullIdEnv) nullConApps
191 getEnvs :: SimplEnv -> (SimplTypeEnv, SimplValEnv)
192 getEnvs (SimplEnv _ _ ty_env id_env _) = (ty_env, id_env)
194 setTyEnv :: SimplEnv -> SimplTypeEnv -> SimplEnv
195 setTyEnv (SimplEnv chkr encl_cc _ in_id_env con_apps) ty_env
196 = SimplEnv chkr encl_cc ty_env in_id_env con_apps
198 setIdEnv :: SimplEnv -> SimplValEnv -> SimplEnv
199 setIdEnv (SimplEnv chkr encl_cc ty_env _ con_apps) id_env
200 = SimplEnv chkr encl_cc ty_env id_env con_apps
202 setSubstEnvs :: SimplEnv -> TyVarEnv Type -> IdEnv SubstInfo -> SimplEnv
203 setSubstEnvs (SimplEnv chkr encl_cc (in_scope_tyvars, _) (in_scope_ids, _) con_apps)
205 = SimplEnv chkr encl_cc (in_scope_tyvars, ty_subst) (in_scope_ids, id_subst) con_apps
209 %************************************************************************
211 \subsubsection{Command-line switches}
213 %************************************************************************
216 getSwitchChecker :: SimplEnv -> SwitchChecker
217 getSwitchChecker (SimplEnv chkr _ _ _ _) = chkr
219 switchIsSet :: SimplEnv -> SimplifierSwitch -> Bool
220 switchIsSet (SimplEnv chkr _ _ _ _) switch
221 = switchIsOn chkr switch
223 getSimplIntSwitch :: SwitchChecker -> (Int-> SimplifierSwitch) -> Int
224 getSimplIntSwitch chkr switch
225 = expectJust "getSimplIntSwitch" (intSwitchSet chkr switch)
228 setCaseScrutinee :: SimplEnv -> SimplEnv
229 setCaseScrutinee (SimplEnv chkr encl_cc ty_env id_env con_apps)
230 = SimplEnv chkr' encl_cc ty_env id_env con_apps
232 chkr' SimplCaseScrutinee = SwBool True
233 chkr' other = chkr other
236 @switchOffInlining@ is used to prepare the environment for simplifying
237 the RHS of an Id that's marked with an INLINE pragma. It is going to
238 be inlined wherever they are used, and then all the inlining will take
239 effect. Meanwhile, there isn't much point in doing anything to the
240 as-yet-un-INLINEd rhs. Furthremore, it's very important to switch off
242 (a) not doing so will inline a worker straight back into its wrapper!
244 and (b) Consider the following example
249 in ...g...g...g...g...g...
251 Now, if that's the ONLY occurrence of f, it will be inlined inside g,
252 and thence copied multiple times when g is inlined.
254 Andy disagrees! Example:
255 all xs = foldr (&&) True xs
256 any p = all . map p {-# INLINE any #-}
258 Problem: any won't get deforested, and so if it's exported and
259 the importer doesn't use the inlining, (eg passes it as an arg)
260 then we won't get deforestation at all.
261 We havn't solved this problem yet!
263 We prepare the envt by simply modifying the id_env, which has
264 all the unfolding info. At one point we did it by modifying the chkr so
265 that it said "EssentialUnfoldingsOnly", but that prevented legitmate, and important,
266 simplifications happening in the body of the RHS.
269 switchOffInlining :: SimplEnv -> SimplEnv
270 switchOffInlining (SimplEnv chkr encl_cc ty_env (in_scope_ids, id_subst) con_apps)
271 = SimplEnv chkr encl_cc ty_env (mapUFM forget in_scope_ids, id_subst) nullConApps
273 forget (id, binder_info, rhs_info) = (id, noBinderInfo, NoRhsInfo)
277 %************************************************************************
279 \subsubsection{The ``enclosing cost-centre''}
281 %************************************************************************
284 setEnclosingCC :: SimplEnv -> CostCentre -> SimplEnv
286 setEnclosingCC env@(SimplEnv chkr _ ty_env id_env con_apps) encl_cc
287 | costsAreSubsumed encl_cc
290 = SimplEnv chkr encl_cc ty_env id_env con_apps
292 getEnclosingCC :: SimplEnv -> CostCentre
293 getEnclosingCC (SimplEnv chkr encl_cc ty_env id_env con_apps) = encl_cc
296 %************************************************************************
298 \subsubsection{The @TypeEnv@ part}
300 %************************************************************************
302 These two "bind" functions extend the tyvar substitution.
303 They don't affect what tyvars are in scope.
306 bindTyVar :: SimplEnv -> TyVar -> Type -> SimplEnv
307 bindTyVar (SimplEnv chkr encl_cc (tyvars, ty_subst) id_env con_apps) tyvar ty
308 = SimplEnv chkr encl_cc (tyvars, new_ty_subst) id_env con_apps
310 new_ty_subst = addToTyVarEnv ty_subst tyvar ty
312 bindTyVars :: SimplEnv -> TyVarEnv Type -> SimplEnv
313 bindTyVars (SimplEnv chkr encl_cc (tyvars, ty_subst) id_env con_apps) extra_subst
314 = SimplEnv chkr encl_cc (tyvars, new_ty_subst) id_env con_apps
316 new_ty_subst = ty_subst `plusTyVarEnv` extra_subst
320 simplTy (SimplEnv _ _ (_, ty_subst) _ _) ty = returnEager (instantiateTy ty_subst ty)
323 %************************************************************************
325 \subsubsection{The ``Id env'' part}
327 %************************************************************************
329 notInScope forgets that the specified binder is in scope.
330 It is used when we decide to bind a let(rec) bound thing to
331 an atom, *after* the Id has been added to the in-scope mapping by simplBinder.
334 notInScope :: SimplEnv -> OutBinder -> SimplEnv
335 notInScope (SimplEnv chkr encl_cc ty_env (in_scope_ids, id_subst) con_apps) id
336 = SimplEnv chkr encl_cc ty_env (new_in_scope_ids, id_subst) con_apps
338 new_in_scope_ids = delOneFromIdEnv in_scope_ids id
341 These "bind" functions extend the Id substitution.
344 bindIdToAtom :: SimplEnv
346 -> OutArg -- Val args only, please
349 bindIdToAtom (SimplEnv chkr encl_cc ty_env (in_scope_ids, id_subst) con_apps)
350 (in_id,occ_info) atom
351 = SimplEnv chkr encl_cc ty_env (in_scope_ids', id_subst') con_apps
353 id_subst' = addOneToIdEnv id_subst in_id (SubstArg atom)
354 in_scope_ids' = case atom of
355 LitArg _ -> in_scope_ids
356 VarArg out_id -> modifyOccInfo in_scope_ids (uniqueOf out_id) occ_info
358 bindIdToExpr :: SimplEnv
360 -> SimplifiableCoreExpr
363 bindIdToExpr (SimplEnv chkr encl_cc ty_env@(_, ty_subst) (in_scope_ids, id_subst) con_apps)
364 (in_id,occ_info) expr
365 = ASSERT( isOneFunOcc occ_info ) -- Binder occurs just once, safely, so no
366 -- need to adjust occurrence info for RHS,
367 -- unlike bindIdToAtom
368 SimplEnv chkr encl_cc ty_env (in_scope_ids, id_subst') con_apps
370 id_subst' = addOneToIdEnv id_subst in_id (SubstExpr ty_subst id_subst expr)
374 %************************************************************************
376 \subsubsection{The @OutIdEnv@}
378 %************************************************************************
381 lookupIdSubst :: SimplEnv -> InId -> Maybe SubstInfo
382 lookupIdSubst (SimplEnv _ _ _ (_, id_subst) _) id = lookupIdEnv id_subst id
384 lookupOutIdEnv :: SimplEnv -> OutId -> Maybe (OutId,BinderInfo,RhsInfo)
385 lookupOutIdEnv (SimplEnv _ _ _ (in_scope_ids, _) _) id = lookupIdEnv in_scope_ids id
387 lookupRhsInfo :: SimplEnv -> OutId -> RhsInfo
389 = case lookupOutIdEnv env id of
390 Just (_,_,info) -> info
393 modifyOutEnvItem :: (OutId, BinderInfo, RhsInfo)
394 -> (OutId, BinderInfo, RhsInfo)
395 -> (OutId, BinderInfo, RhsInfo)
396 modifyOutEnvItem (id, occ, info1) (_, _, info2)
397 = case (info1, info2) of
398 (OtherLit ls1, OtherLit ls2) -> (id,occ, OtherLit (ls1++ls2))
399 (OtherCon cs1, OtherCon cs2) -> (id,occ, OtherCon (cs1++cs2))
400 (_, NoRhsInfo) -> (id,occ, info1)
401 other -> (id,occ, info2)
406 isEvaluated :: RhsInfo -> Bool
407 isEvaluated (OtherLit _) = True
408 isEvaluated (OtherCon _) = True
409 isEvaluated (OutUnfolding _ (SimpleUnfolding ValueForm _ expr)) = True
410 isEvaluated other = False
416 mkSimplUnfoldingGuidance chkr out_id rhs
417 = calcUnfoldingGuidance (getInlinePragma out_id) opt_UnfoldingCreationThreshold rhs
419 extendEnvGivenRhsInfo :: SimplEnv -> OutId -> BinderInfo -> RhsInfo -> SimplEnv
420 extendEnvGivenRhsInfo env@(SimplEnv chkr encl_cc ty_env (in_scope_ids, id_subst) con_apps)
421 out_id occ_info rhs_info
422 = SimplEnv chkr encl_cc ty_env (new_in_scope_ids, id_subst) con_apps
424 new_in_scope_ids = addToUFM_C modifyOutEnvItem in_scope_ids out_id
425 (out_id, occ_info, rhs_info)
430 modifyOccInfo in_scope_ids uniq new_occ
431 = modifyIdEnv_Directly modify_fn in_scope_ids uniq
433 modify_fn (id,occ,rhs) = (id, orBinderInfo occ new_occ, rhs)
435 markDangerousOccs (SimplEnv chkr encl_cc ty_env (in_scope_ids, id_subst) con_apps) atoms
436 = SimplEnv chkr encl_cc ty_env (new_in_scope_ids, id_subst) con_apps
438 new_in_scope_ids = foldl (modifyIdEnv modify_fn) in_scope_ids [v | VarArg v <- atoms]
439 modify_fn (id,occ,rhs) = (id, noBinderInfo, rhs)
443 %************************************************************************
445 \subsubsection{The @ConAppMap@ type}
447 %************************************************************************
449 The @ConAppMap@ maps applications of constructors (to value atoms)
450 back to an association list that says "if the constructor was applied
451 to one of these lists-of-Types, then this OutId is your man (in a
452 non-gender-specific sense)". I.e., this is a reversed mapping for
453 (part of) the main OutIdEnv
456 type ConAppMap = FiniteMap UnfoldConApp [([Type], OutId)]
459 = UCA OutId -- data constructor
460 [OutArg] -- *value* arguments; see use below
464 nullConApps = emptyFM
466 extendConApps con_apps id (Con con args)
467 = addToFM_C (\old new -> new++old) con_apps (UCA con val_args) [(ty_args,id)]
469 val_args = filter isValArg args -- Literals and Ids
470 ty_args = [ty | TyArg ty <- args] -- Just types
472 extendConApps con_apps id other_rhs = con_apps
476 lookForConstructor env@(SimplEnv _ _ _ _ con_apps) (Con con args)
477 | switchIsSet env SimplReuseCon
478 = case lookupFM con_apps (UCA con val_args) of
481 Just assocs -> case [id | (tys, id) <- assocs,
482 and (zipWith (==) tys ty_args)]
487 val_args = filter isValArg args -- Literals and Ids
488 ty_args = [ty | TyArg ty <- args] -- Just types
490 lookForConstructor env other = Nothing
493 NB: In @lookForConstructor@ we used (before Apr 94) to have a special case
494 for nullary constructors, but now we only do constructor re-use in
495 let-bindings the special case isn't necessary any more.
498 = -- Don't re-use nullary constructors; it's a waste. Consider
506 -- Here the False in the second case will get replace by "a", hardly
512 The main thing about @UnfoldConApp@ is that it has @Ord@ defined on
513 it, so we can use it for a @FiniteMap@ key.
516 instance Eq UnfoldConApp where
517 a == b = case (a `compare` b) of { EQ -> True; _ -> False }
518 a /= b = case (a `compare` b) of { EQ -> False; _ -> True }
520 instance Ord UnfoldConApp where
521 a <= b = case (a `compare` b) of { LT -> True; EQ -> True; GT -> False }
522 a < b = case (a `compare` b) of { LT -> True; EQ -> False; GT -> False }
523 a >= b = case (a `compare` b) of { LT -> False; EQ -> True; GT -> True }
524 a > b = case (a `compare` b) of { LT -> False; EQ -> False; GT -> True }
525 compare a b = cmp_app a b
527 cmp_app (UCA c1 as1) (UCA c2 as2)
528 = compare c1 c2 `thenCmp` cmpList cmp_arg as1 as2
530 -- ToDo: make an "instance Ord CoreArg"???
532 cmp_arg (VarArg x) (VarArg y) = x `compare` y
533 cmp_arg (LitArg x) (LitArg y) = x `compare` y
534 cmp_arg (TyArg x) (TyArg y) = panic "SimplEnv.cmp_app:TyArgs"
536 | tag x _LT_ tag y = LT
539 tag (VarArg _) = ILIT(1)
540 tag (LitArg _) = ILIT(2)
541 tag (TyArg _) = panic# "SimplEnv.cmp_app:TyArg"
545 @extendUnfoldEnvGivenRhs@ records in the UnfoldEnv info about the RHS
546 of a new binding. There is a horrid case we have to take care about,
547 due to Andr\'e Santos:
549 type Array_type b = Array Int b;
550 type Descr_type = (Int,Int);
552 tabulate :: (Int -> x) -> Descr_type -> Array_type x;
553 tabulate f (l,u) = listArray (l,u) [f i | i <- [l..u]];
557 f_aareorder::(Array_type Int) -> (Array_type t1) -> Array_type t1;
558 f_aareorder a_index a_ar=
560 f_aareorder' a_i= a_ar ! (a_index ! a_i)
561 } in tabulate f_aareorder' (bounds a_ar);
562 r_index=tabulate ((+) 1) (1,1);
563 arr = listArray (1,1) a_xs;
564 arg = f_aareorder r_index arr
567 Now, when the RHS of arg gets simplified, we inline f_aareorder to get
569 arg = let f_aareorder' a_i = arr ! (r_index ! a_i)
570 in tabulate f_aareorder' (bounds arr)
572 Note that r_index is not inlined, because it was bound to a_index which
573 occurs inside a lambda.
575 Alas, if elems is inlined, so that (elems arg) becomes (case arg of ...),
576 then arg is inlined. IF WE USE THE NEW VERSION OF arg, and re-occurrence
577 analyse it, we won't spot the inside-lambda property of r_index, so r_index
578 will get inlined inside the lambda. AARGH.
580 Solution: when we occurrence-analyse the new RHS we have to go back
581 and modify the info recorded in the UnfoldEnv for the free vars
582 of the RHS. In the example we'd go back and record that r_index is now used
586 extendEnvGivenNewRhs :: SimplEnv -> OutId -> OutExpr -> SimplEnv
587 extendEnvGivenNewRhs env out_id rhs
588 = extendEnvGivenBinding env noBinderInfo out_id rhs
590 extendEnvGivenBinding :: SimplEnv -> BinderInfo -> OutId -> OutExpr -> SimplEnv
591 extendEnvGivenBinding env@(SimplEnv chkr encl_cc ty_env (in_scope_ids, id_subst) con_apps)
593 = SimplEnv chkr encl_cc ty_env (new_in_scope_ids, id_subst) new_con_apps
595 new_in_scope_ids | okToInline (whnfOrBottom form)
596 (couldBeSmallEnoughToInline out_id guidance)
601 -- Don't bother to munge the OutIdEnv unless there is some possibility
602 -- that the thing might be inlined. We check this by calling okToInline suitably.
604 new_con_apps = _scc_ "eegnr.conapps"
605 extendConApps con_apps out_id rhs
607 -- Modify the occ info for rhs's interesting free variables.
608 -- That's to take account of:
609 -- let a = \x -> BIG in
611 -- in ...b...b...b...
612 -- Here "a" occurs exactly once. "b" simplifies to a small value.
613 -- So "b" will be inlined at each call site, and there's a good chance
614 -- that "a" will too. So we'd better modify "a"s occurrence info to
615 -- record the fact that it can now occur many times by virtue that "b" can.
616 env_with_unfolding = _scc_ "eegnr.modify_occ"
617 foldl zap env1 (ufmToList fv_occ_info)
618 zap env (uniq,_) = modifyOccInfo env uniq occ_info
621 -- Add an unfolding and rhs_info for the new Id.
622 -- If the out_id is already in the OutIdEnv (which should be the
623 -- case because it was put there by simplBinder)
624 -- then just replace the unfolding, leaving occurrence info alone.
625 env1 = _scc_ "eegnr.modify_out"
626 addToUFM_C modifyOutEnvItem in_scope_ids out_id
627 (out_id, occ_info, rhs_info)
629 -- Occurrence-analyse the RHS
630 -- The "interesting" free variables we want occurrence info for are those
631 -- in the OutIdEnv that have only a single occurrence right now.
632 (fv_occ_info, template) = _scc_ "eegnr.occ-anal"
633 occurAnalyseExpr is_interesting rhs
635 is_interesting v = _scc_ "eegnr.mkidset"
636 case lookupIdEnv in_scope_ids v of
637 Just (_, occ, _) -> isOneOcc occ
640 -- Compute unfolding details
641 rhs_info = OutUnfolding unf_cc (SimpleUnfolding form guidance template)
642 form = _scc_ "eegnr.form_sum"
644 guidance = _scc_ "eegnr.guidance"
645 mkSimplUnfoldingGuidance chkr out_id rhs
647 -- Compute cost centre for thing
648 unf_cc | noCostCentreAttached expr_cc = encl_cc
649 | otherwise = expr_cc
651 expr_cc = coreExprCc rhs