2 % (c) The AQUA Project, Glasgow University, 1993-1998
4 \section[SimplMonad]{The simplifier Monad}
8 InId, InBind, InExpr, InAlt, InArg, InType, InBndr,
9 OutId, OutTyVar, OutBind, OutExpr, OutAlt, OutArg, OutType, OutBndr,
10 InCoercion, OutCoercion,
14 -- The simplifier mode
18 SwitchChecker, SwitchResult(..), getSwitchChecker, getSimplIntSwitch,
19 isAmongSimpl, intSwitchSet, switchIsOn,
21 setEnclosingCC, getEnclosingCC,
24 SimplEnv(..), -- Temp not abstract
25 mkSimplEnv, extendIdSubst, SimplEnv.extendTvSubst,
26 zapSubstEnv, setSubstEnv,
27 getInScope, setInScope, setInScopeSet, modifyInScope, addNewInScopeIds,
30 SimplSR(..), mkContEx, substId, lookupRecBndr,
32 simplNonRecBndr, simplRecBndrs, simplLamBndr, simplLamBndrs,
33 simplBinder, simplBinders, addLetIdInfo,
37 Floats, emptyFloats, isEmptyFloats, addNonRec, addFloats,
38 wrapFloats, floatBinds, setFloats, canFloat, zapFloats, addRecFloats,
42 #include "HsVersions.h"
57 import qualified CoreSubst ( Subst, mkSubst, substExpr, substSpec, substWorker )
58 import qualified Type ( substTy, substTyVarBndr )
59 import Type hiding ( substTy, substTyVarBndr )
68 %************************************************************************
70 \subsection[Simplify-types]{Type declarations}
72 %************************************************************************
75 type InBndr = CoreBndr
76 type InId = Id -- Not yet cloned
77 type InType = Type -- Ditto
78 type InBind = CoreBind
79 type InExpr = CoreExpr
82 type InCoercion = Coercion
84 type OutBndr = CoreBndr
85 type OutId = Id -- Cloned
86 type OutTyVar = TyVar -- Cloned
87 type OutType = Type -- Cloned
88 type OutCoercion = Coercion
89 type OutBind = CoreBind
90 type OutExpr = CoreExpr
96 isStrictBndr :: Id -> Bool
98 = ASSERT2( isId bndr, ppr bndr )
99 isStrictDmd (idNewDemandInfo bndr) || isStrictType (idType bndr)
102 %************************************************************************
104 \subsubsection{The @SimplEnv@ type}
106 %************************************************************************
112 seMode :: SimplifierMode,
113 seChkr :: SwitchChecker,
114 seCC :: CostCentreStack, -- The enclosing CCS (when profiling)
116 -- Rules from other modules
117 seExtRules :: RuleBase,
119 -- The current set of in-scope variables
120 -- They are all OutVars, and all bound in this module
121 seInScope :: InScopeSet, -- OutVars only
122 -- Includes all variables bound by seFloats
124 -- See Note [Simplifier floats]
126 -- The current substitution
127 seTvSubst :: TvSubstEnv, -- InTyVar |--> OutType
128 seIdSubst :: SimplIdSubst -- InId |--> OutExpr
132 type SimplIdSubst = IdEnv SimplSR -- IdId |--> OutExpr
133 -- See Note [Extending the Subst] in CoreSubst
136 = DoneEx OutExpr -- Completed term
137 | DoneId OutId -- Completed term variable
138 | ContEx TvSubstEnv -- A suspended substitution
142 instance Outputable SimplSR where
143 ppr (DoneEx e) = ptext SLIT("DoneEx") <+> ppr e
144 ppr (DoneId v) = ptext SLIT("DoneId") <+> ppr v
145 ppr (ContEx tv id e) = vcat [ptext SLIT("ContEx") <+> ppr e {-,
146 ppr (filter_env tv), ppr (filter_env id) -}]
149 filter_env env = filterVarEnv_Directly keep env
150 keep uniq _ = uniq `elemUFM_Directly` fvs
155 The in-scope part of Subst includes *all* in-scope TyVars and Ids
156 The elements of the set may have better IdInfo than the
157 occurrences of in-scope Ids, and (more important) they will
158 have a correctly-substituted type. So we use a lookup in this
159 set to replace occurrences
161 The Ids in the InScopeSet are replete with their Rules,
162 and as we gather info about the unfolding of an Id, we replace
163 it in the in-scope set.
165 The in-scope set is actually a mapping OutVar -> OutVar, and
166 in case expressions we sometimes bind
169 The substitution is *apply-once* only, because InIds and OutIds can overlap.
170 For example, we generally omit mappings
172 from the substitution, when we decide not to clone a77, but it's quite
173 legitimate to put the mapping in the substitution anyway.
175 Furthermore, consider
176 let x = case k of I# x77 -> ... in
177 let y = case k of I# x77 -> ... in ...
178 and suppose the body is strict in both x and y. Then the simplifier
179 will pull the first (case k) to the top; so the second (case k) will
180 cancel out, mapping x77 to, well, x77! But one is an in-Id and the
183 Of course, the substitution *must* applied! Things in its domain
184 simply aren't necessarily bound in the result.
186 * substId adds a binding (DoneId new_id) to the substitution if
187 the Id's unique has changed
190 Note, though that the substitution isn't necessarily extended
191 if the type changes. Why not? Because of the next point:
193 * We *always, always* finish by looking up in the in-scope set
194 any variable that doesn't get a DoneEx or DoneVar hit in the substitution.
195 Reason: so that we never finish up with a "old" Id in the result.
196 An old Id might point to an old unfolding and so on... which gives a space leak.
198 [The DoneEx and DoneVar hits map to "new" stuff.]
200 * It follows that substExpr must not do a no-op if the substitution is empty.
201 substType is free to do so, however.
203 * When we come to a let-binding (say) we generate new IdInfo, including an
204 unfolding, attach it to the binder, and add this newly adorned binder to
205 the in-scope set. So all subsequent occurrences of the binder will get mapped
206 to the full-adorned binder, which is also the one put in the binding site.
208 * The in-scope "set" usually maps x->x; we use it simply for its domain.
209 But sometimes we have two in-scope Ids that are synomyms, and should
210 map to the same target: x->x, y->x. Notably:
212 That's why the "set" is actually a VarEnv Var
216 mkSimplEnv :: SimplifierMode -> SwitchChecker -> RuleBase -> SimplEnv
217 mkSimplEnv mode switches rules
218 = SimplEnv { seChkr = switches, seCC = subsumedCCS,
219 seMode = mode, seInScope = emptyInScopeSet,
220 seExtRules = rules, seFloats = emptyFloats,
221 seTvSubst = emptyVarEnv, seIdSubst = emptyVarEnv }
222 -- The top level "enclosing CC" is "SUBSUMED".
224 ---------------------
225 getSwitchChecker :: SimplEnv -> SwitchChecker
226 getSwitchChecker env = seChkr env
228 ---------------------
229 getMode :: SimplEnv -> SimplifierMode
230 getMode env = seMode env
232 setMode :: SimplifierMode -> SimplEnv -> SimplEnv
233 setMode mode env = env { seMode = mode }
235 ---------------------
236 getEnclosingCC :: SimplEnv -> CostCentreStack
237 getEnclosingCC env = seCC env
239 setEnclosingCC :: SimplEnv -> CostCentreStack -> SimplEnv
240 setEnclosingCC env cc = env {seCC = cc}
242 ---------------------
243 extendIdSubst :: SimplEnv -> Id -> SimplSR -> SimplEnv
244 extendIdSubst env@(SimplEnv {seIdSubst = subst}) var res
245 = env {seIdSubst = extendVarEnv subst var res}
247 extendTvSubst :: SimplEnv -> TyVar -> Type -> SimplEnv
248 extendTvSubst env@(SimplEnv {seTvSubst = subst}) var res
249 = env {seTvSubst = extendVarEnv subst var res}
251 ---------------------
252 getInScope :: SimplEnv -> InScopeSet
253 getInScope env = seInScope env
255 setInScopeSet :: SimplEnv -> InScopeSet -> SimplEnv
256 setInScopeSet env in_scope = env {seInScope = in_scope}
258 setInScope :: SimplEnv -> SimplEnv -> SimplEnv
259 -- Set the in-scope set, and *zap* the floats
260 setInScope env env_with_scope
261 = env { seInScope = seInScope env_with_scope,
262 seFloats = emptyFloats }
264 setFloats :: SimplEnv -> SimplEnv -> SimplEnv
265 -- Set the in-scope set *and* the floats
266 setFloats env env_with_floats
267 = env { seInScope = seInScope env_with_floats,
268 seFloats = seFloats env_with_floats }
270 addNewInScopeIds :: SimplEnv -> [CoreBndr] -> SimplEnv
271 -- The new Ids are guaranteed to be freshly allocated
272 addNewInScopeIds env@(SimplEnv { seInScope = in_scope, seIdSubst = id_subst }) vs
273 = env { seInScope = in_scope `extendInScopeSetList` vs,
274 seIdSubst = id_subst `delVarEnvList` vs }
275 -- Why delete? Consider
276 -- let x = a*b in (x, \x -> x+3)
277 -- We add [x |-> a*b] to the substitution, but we must
278 -- *delete* it from the substitution when going inside
281 modifyInScope :: SimplEnv -> CoreBndr -> CoreBndr -> SimplEnv
282 modifyInScope env@(SimplEnv {seInScope = in_scope}) v v'
283 = env {seInScope = modifyInScopeSet in_scope v v'}
285 ---------------------
286 zapSubstEnv :: SimplEnv -> SimplEnv
287 zapSubstEnv env = env {seTvSubst = emptyVarEnv, seIdSubst = emptyVarEnv}
289 setSubstEnv :: SimplEnv -> TvSubstEnv -> SimplIdSubst -> SimplEnv
290 setSubstEnv env tvs ids = env { seTvSubst = tvs, seIdSubst = ids }
292 mkContEx :: SimplEnv -> InExpr -> SimplSR
293 mkContEx (SimplEnv { seTvSubst = tvs, seIdSubst = ids }) e = ContEx tvs ids e
295 isEmptySimplSubst :: SimplEnv -> Bool
296 isEmptySimplSubst (SimplEnv { seTvSubst = tvs, seIdSubst = ids })
297 = isEmptyVarEnv tvs && isEmptyVarEnv ids
299 ---------------------
300 getRules :: SimplEnv -> RuleBase
301 getRules = seExtRules
306 %************************************************************************
310 %************************************************************************
312 Note [Simplifier floats]
313 ~~~~~~~~~~~~~~~~~~~~~~~~~
314 The Floats is a bunch of bindings, classified by a FloatFlag.
316 NonRec x (y:ys) FltLifted
317 Rec [(x,rhs)] FltLifted
318 NonRec x# (y +# 3) FltOkSpec
319 NonRec x# (a /# b) FltCareful
320 NonRec x* (f y) FltCareful -- Might fail or diverge
321 NonRec x# (f y) FltCareful -- Might fail or diverge
322 (where f :: Int -> Int#)
325 data Floats = Floats (OrdList OutBind) FloatFlag
326 -- See Note [Simplifier floats]
329 = FltLifted -- All bindings are lifted and lazy
330 -- Hence ok to float to top level, or recursive
332 | FltOkSpec -- All bindings are FltLifted *or*
333 -- strict (perhaps because unlifted,
334 -- perhaps because of a strict binder),
335 -- *and* ok-for-speculation
336 -- Hence ok to float out of the RHS
337 -- of a lazy non-recursive let binding
338 -- (but not to top level, or into a rec group)
340 | FltCareful -- At least one binding is strict (or unlifted)
341 -- and not guaranteed cheap
342 -- Do not float these bindings out of a lazy let
344 instance Outputable Floats where
345 ppr (Floats binds ff) = ppr ff $$ ppr (fromOL binds)
347 instance Outputable FloatFlag where
348 ppr FltLifted = ptext SLIT("FltLifted")
349 ppr FltOkSpec = ptext SLIT("FltOkSpec")
350 ppr FltCareful = ptext SLIT("FltCareful")
352 andFF :: FloatFlag -> FloatFlag -> FloatFlag
353 andFF FltCareful _ = FltCareful
354 andFF FltOkSpec FltCareful = FltCareful
355 andFF FltOkSpec flt = FltOkSpec
356 andFF FltLifted flt = flt
358 classifyFF :: CoreBind -> FloatFlag
359 classifyFF (Rec _) = FltLifted
360 classifyFF (NonRec bndr rhs)
361 | not (isStrictBndr bndr) = FltLifted
362 | exprOkForSpeculation rhs = FltOkSpec
363 | otherwise = FltCareful
365 canFloat :: TopLevelFlag -> RecFlag -> Bool -> SimplEnv -> Bool
366 canFloat lvl rec str (SimplEnv {seFloats = Floats _ ff})
367 = canFloatFlt lvl rec str ff
369 canFloatFlt :: TopLevelFlag -> RecFlag -> Bool -> FloatFlag -> Bool
370 canFloatFlt lvl rec str FltLifted = True
371 canFloatFlt lvl rec str FltOkSpec = isNotTopLevel lvl && isNonRec rec
372 canFloatFlt lvl rec str FltCareful = str && isNotTopLevel lvl && isNonRec rec
377 emptyFloats :: Floats
378 emptyFloats = Floats nilOL FltLifted
380 unitFloat :: OutBind -> Floats
381 -- A single-binding float
382 unitFloat bind = Floats (unitOL bind) (classifyFF bind)
384 addNonRec :: SimplEnv -> OutId -> OutExpr -> SimplEnv
385 -- Add a non-recursive binding and extend the in-scope set
386 -- The latter is important; the binder may already be in the
387 -- in-scope set (although it might also have been created with newId)
388 -- but it may now have more IdInfo
390 = env { seFloats = seFloats env `addFlts` unitFloat (NonRec id rhs),
391 seInScope = extendInScopeSet (seInScope env) id }
393 addFloats :: SimplEnv -> SimplEnv -> SimplEnv
394 -- Add the floats for env2 to env1;
395 -- *plus* the in-scope set for env2, which is bigger
396 -- than that for env1
398 = env1 {seFloats = seFloats env1 `addFlts` seFloats env2,
399 seInScope = seInScope env2 }
401 addFlts :: Floats -> Floats -> Floats
402 addFlts (Floats bs1 l1) (Floats bs2 l2)
403 = Floats (bs1 `appOL` bs2) (l1 `andFF` l2)
405 zapFloats :: SimplEnv -> SimplEnv
406 zapFloats env = env { seFloats = emptyFloats }
408 addRecFloats :: SimplEnv -> SimplEnv -> SimplEnv
409 -- Flattens the floats from env2 into a single Rec group,
410 -- prepends the floats from env1, and puts the result back in env2
411 -- This is all very specific to the way recursive bindings are
412 -- handled; see Simplify.simplRecBind
413 addRecFloats env1 env2@(SimplEnv {seFloats = Floats bs ff})
414 = ASSERT2( case ff of { FltLifted -> True; other -> False }, ppr (fromOL bs) )
415 env2 {seFloats = seFloats env1 `addFlts` unitFloat (Rec (flattenBinds (fromOL bs)))}
417 wrapFloats :: SimplEnv -> OutExpr -> OutExpr
418 wrapFloats env expr = wrapFlts (seFloats env) expr
420 wrapFlts :: Floats -> OutExpr -> OutExpr
421 -- Wrap the floats around the expression, using case-binding where necessary
422 wrapFlts (Floats bs _) body = foldrOL wrap body bs
424 wrap (Rec prs) body = Let (Rec prs) body
425 wrap (NonRec b r) body = bindNonRec b r body
427 getFloats :: SimplEnv -> [CoreBind]
428 getFloats (SimplEnv {seFloats = Floats bs _}) = fromOL bs
430 isEmptyFloats :: SimplEnv -> Bool
431 isEmptyFloats env = isEmptyFlts (seFloats env)
433 isEmptyFlts :: Floats -> Bool
434 isEmptyFlts (Floats bs _) = isNilOL bs
436 floatBinds :: Floats -> [OutBind]
437 floatBinds (Floats bs _) = fromOL bs
441 %************************************************************************
445 %************************************************************************
449 substId :: SimplEnv -> Id -> SimplSR
450 substId (SimplEnv { seInScope = in_scope, seIdSubst = ids }) v
453 | otherwise -- A local Id
454 = case lookupVarEnv ids v of
455 Just (DoneId v) -> DoneId (refine in_scope v)
457 Nothing -> DoneId (refine in_scope v)
460 -- Get the most up-to-date thing from the in-scope set
461 -- Even though it isn't in the substitution, it may be in
462 -- the in-scope set with better IdInfo
463 refine in_scope v = case lookupInScope in_scope v of
465 Nothing -> WARN( True, ppr v ) v -- This is an error!
467 lookupRecBndr :: SimplEnv -> Id -> Id
468 -- Look up an Id which has been put into the envt by simplRecBndrs,
469 -- but where we have not yet done its RHS
470 lookupRecBndr (SimplEnv { seInScope = in_scope, seIdSubst = ids }) v
471 = case lookupVarEnv ids v of
473 Just res -> pprPanic "lookupRecBndr" (ppr v)
474 Nothing -> refine in_scope v
478 %************************************************************************
480 \section{Substituting an Id binder}
482 %************************************************************************
485 These functions are in the monad only so that they can be made strict via seq.
488 simplBinders, simplLamBndrs
489 :: SimplEnv -> [InBndr] -> SimplM (SimplEnv, [OutBndr])
490 simplBinders env bndrs = mapAccumLSmpl simplBinder env bndrs
491 simplLamBndrs env bndrs = mapAccumLSmpl simplLamBndr env bndrs
494 simplBinder :: SimplEnv -> InBndr -> SimplM (SimplEnv, OutBndr)
495 -- Used for lambda and case-bound variables
496 -- Clone Id if necessary, substitute type
497 -- Return with IdInfo already substituted, but (fragile) occurrence info zapped
498 -- The substitution is extended only if the variable is cloned, because
499 -- we *don't* need to use it to track occurrence info.
501 | isTyVar bndr = do { let (env', tv) = substTyVarBndr env bndr
502 ; seqTyVar tv `seq` return (env', tv) }
503 | otherwise = do { let (env', id) = substIdBndr env bndr
504 ; seqId id `seq` return (env', id) }
507 simplLamBndr :: SimplEnv -> Var -> SimplM (SimplEnv, Var)
508 -- Used for lambda binders. These sometimes have unfoldings added by
509 -- the worker/wrapper pass that must be preserved, becuase they can't
510 -- be reconstructed from context. For example:
511 -- f x = case x of (a,b) -> fw a b x
512 -- fw a b x{=(a,b)} = ...
513 -- The "{=(a,b)}" is an unfolding we can't reconstruct otherwise.
514 simplLamBndr env bndr
515 | not (isId bndr && hasSomeUnfolding old_unf) = simplBinder env bndr -- Normal case
516 | otherwise = seqId id2 `seq` return (env', id2)
518 old_unf = idUnfolding bndr
519 (env', id1) = substIdBndr env bndr
520 id2 = id1 `setIdUnfolding` substUnfolding env old_unf
523 substIdBndr :: SimplEnv -> Id -- Substitition and Id to transform
524 -> (SimplEnv, Id) -- Transformed pair
527 -- * Unique changed if necessary
528 -- * Type substituted
529 -- * Unfolding zapped
530 -- * Rules, worker, lbvar info all substituted
531 -- * Fragile occurrence info zapped
532 -- * The in-scope set extended with the returned Id
533 -- * The substitution extended with a DoneId if unique changed
534 -- In this case, the var in the DoneId is the same as the
537 -- Exactly like CoreSubst.substIdBndr, except that the type of id_subst differs
539 substIdBndr env@(SimplEnv { seInScope = in_scope, seIdSubst = id_subst})
541 = (env { seInScope = in_scope `extendInScopeSet` new_id,
542 seIdSubst = new_subst }, new_id)
544 -- id1 is cloned if necessary
545 id1 = uniqAway in_scope old_id
547 -- id2 has its type zapped
548 id2 = substIdType env id1
550 -- new_id has the final IdInfo
551 subst = mkCoreSubst env
552 new_id = maybeModifyIdInfo (substIdInfo subst (idInfo old_id)) id2
554 -- Extend the substitution if the unique has changed
555 -- See the notes with substTyVarBndr for the delSubstEnv
556 -- Also see Note [Extending the Subst] in CoreSubst
557 new_subst | new_id /= old_id
558 = extendVarEnv id_subst old_id (DoneId new_id)
560 = delVarEnv id_subst old_id
564 ------------------------------------
565 seqTyVar :: TyVar -> ()
566 seqTyVar b = b `seq` ()
569 seqId id = seqType (idType id) `seq`
575 seqIds (id:ids) = seqId id `seq` seqIds ids
578 %************************************************************************
582 %************************************************************************
584 Simplifying let binders
585 ~~~~~~~~~~~~~~~~~~~~~~~
586 Rename the binders if necessary,
589 simplNonRecBndr :: SimplEnv -> InBndr -> SimplM (SimplEnv, OutBndr)
590 simplNonRecBndr env id
591 = do { let (env1, id1) = substLetIdBndr env id
592 ; seqId id1 `seq` return (env1, id1) }
595 simplRecBndrs :: SimplEnv -> [InBndr] -> SimplM SimplEnv
596 simplRecBndrs env@(SimplEnv { seInScope = in_scope, seIdSubst = id_subst }) ids
597 = do { let (env1, ids1) = mapAccumL substLetIdBndr env ids
598 ; seqIds ids1 `seq` return env1 }
601 substLetIdBndr :: SimplEnv -> InBndr -- Env and binder to transform
602 -> (SimplEnv, OutBndr)
603 -- C.f. substIdBndr above
604 -- Clone Id if necessary, substitute its type
605 -- Return an Id with completely zapped IdInfo
606 -- [addLetIdInfo, below, will restore its IdInfo]
607 -- Augment the subtitution
608 -- if the unique changed, *or*
609 -- if there's interesting occurrence info
611 substLetIdBndr env@(SimplEnv { seInScope = in_scope, seIdSubst = id_subst }) old_id
612 = (env { seInScope = in_scope `extendInScopeSet` new_id,
613 seIdSubst = new_subst }, new_id)
615 id1 = uniqAway in_scope old_id
616 id2 = substIdType env id1
617 new_id = setIdInfo id2 vanillaIdInfo
619 -- Extend the substitution if the unique has changed,
620 -- or there's some useful occurrence information
621 -- See the notes with substTyVarBndr for the delSubstEnv
622 new_subst | new_id /= old_id
623 = extendVarEnv id_subst old_id (DoneId new_id)
625 = delVarEnv id_subst old_id
628 Add IdInfo back onto a let-bound Id
629 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
630 We must transfer the IdInfo of the original binder to the new binder.
631 This is crucial, to preserve
635 etc. To do this we must apply the current substitution,
636 which incorporates earlier substitutions in this very letrec group.
638 NB 1. We do this *before* processing the RHS of the binder, so that
639 its substituted rules are visible in its own RHS.
640 This is important. Manuel found cases where he really, really
641 wanted a RULE for a recursive function to apply in that function's
644 NB 2: ARITY. We *do* transfer the arity. This is important, so that
645 the arity of an Id is visible in its own RHS. For example:
646 f = \x. ....g (\y. f y)....
647 We can eta-reduce the arg to g, becuase f is a value. But that
650 This interacts with the 'state hack' too:
655 Can we eta-expand f? Only if we see that f has arity 1, and then we
656 take advantage of the 'state hack' on the result of
657 (f y) :: State# -> (State#, Int) to expand the arity one more.
659 There is a disadvantage though. Making the arity visible in the RHA
660 allows us to eta-reduce
664 which technically is not sound. This is very much a corner case, so
665 I'm not worried about it. Another idea is to ensure that f's arity
666 never decreases; its arity started as 1, and we should never eta-reduce
669 NB 3: OccInfo. It's important that we *do* transer the loop-breaker
670 OccInfo, because that's what stops the Id getting inlined infinitely,
671 in the body of the letrec.
673 NB 4: does no harm for non-recursive bindings
675 NB 5: we can't do the addLetIdInfo part before *all* the RHSs because
680 Here, we'll do postInlineUnconditionally on f, and we must "see" that
681 when substituting in h's RULE.
684 addLetIdInfo :: SimplEnv -> InBndr -> OutBndr -> (SimplEnv, OutBndr)
685 addLetIdInfo env in_id out_id
686 = (modifyInScope env out_id final_id, final_id)
688 final_id = out_id `setIdInfo` new_info
689 subst = mkCoreSubst env
690 old_info = idInfo in_id
691 new_info = case substIdInfo subst old_info of
693 Just new_info -> new_info
695 substIdInfo :: CoreSubst.Subst -> IdInfo -> Maybe IdInfo
700 -- Keep only 'robust' OccInfo
703 -- Seq'ing on the returned IdInfo is enough to cause all the
704 -- substitutions to happen completely
706 substIdInfo subst info
707 | nothing_to_do = Nothing
708 | otherwise = Just (info `setOccInfo` (if keep_occ then old_occ else NoOccInfo)
709 `setSpecInfo` CoreSubst.substSpec subst old_rules
710 `setWorkerInfo` CoreSubst.substWorker subst old_wrkr
711 `setUnfoldingInfo` noUnfolding)
712 -- setSpecInfo does a seq
713 -- setWorkerInfo does a seq
715 nothing_to_do = keep_occ &&
716 isEmptySpecInfo old_rules &&
717 not (workerExists old_wrkr) &&
718 not (hasUnfolding (unfoldingInfo info))
720 keep_occ = not (isFragileOcc old_occ)
721 old_occ = occInfo info
722 old_rules = specInfo info
723 old_wrkr = workerInfo info
726 substIdType :: SimplEnv -> Id -> Id
727 substIdType env@(SimplEnv { seInScope = in_scope, seTvSubst = tv_env}) id
728 | isEmptyVarEnv tv_env || isEmptyVarSet (tyVarsOfType old_ty) = id
729 | otherwise = Id.setIdType id (Type.substTy (TvSubst in_scope tv_env) old_ty)
730 -- The tyVarsOfType is cheaper than it looks
731 -- because we cache the free tyvars of the type
732 -- in a Note in the id's type itself
737 substUnfolding env NoUnfolding = NoUnfolding
738 substUnfolding env (OtherCon cons) = OtherCon cons
739 substUnfolding env (CompulsoryUnfolding rhs) = CompulsoryUnfolding (substExpr env rhs)
740 substUnfolding env (CoreUnfolding rhs t v w g) = CoreUnfolding (substExpr env rhs) t v w g
744 %************************************************************************
746 Impedence matching to type substitution
748 %************************************************************************
751 substTy :: SimplEnv -> Type -> Type
752 substTy (SimplEnv { seInScope = in_scope, seTvSubst = tv_env }) ty
753 = Type.substTy (TvSubst in_scope tv_env) ty
755 substTyVarBndr :: SimplEnv -> TyVar -> (SimplEnv, TyVar)
756 substTyVarBndr env@(SimplEnv { seInScope = in_scope, seTvSubst = tv_env }) tv
757 = case Type.substTyVarBndr (TvSubst in_scope tv_env) tv of
758 (TvSubst in_scope' tv_env', tv')
759 -> (env { seInScope = in_scope', seTvSubst = tv_env'}, tv')
761 -- When substituting in rules etc we can get CoreSubst to do the work
762 -- But CoreSubst uses a simpler form of IdSubstEnv, so we must impedence-match
763 -- here. I think the this will not usually result in a lot of work;
764 -- the substitutions are typically small, and laziness will avoid work in many cases.
766 mkCoreSubst :: SimplEnv -> CoreSubst.Subst
767 mkCoreSubst (SimplEnv { seInScope = in_scope, seTvSubst = tv_env, seIdSubst = id_env })
768 = mk_subst tv_env id_env
770 mk_subst tv_env id_env = CoreSubst.mkSubst in_scope tv_env (mapVarEnv fiddle id_env)
772 fiddle (DoneEx e) = e
773 fiddle (DoneId v) = Var v
774 fiddle (ContEx tv id e) = CoreSubst.substExpr (mk_subst tv id) e
776 substExpr :: SimplEnv -> CoreExpr -> CoreExpr
778 | isEmptySimplSubst env = expr
779 | otherwise = CoreSubst.substExpr (mkCoreSubst env) expr