2 % (c) The AQUA Project, Glasgow University, 1993-1998
4 \section[SimplMonad]{The simplifier Monad}
8 InId, InBind, InExpr, InAlt, InArg, InType, InBinder,
9 OutId, OutBind, OutExpr, OutAlt, OutArg, OutType, OutBinder,
10 OutExprStuff, OutStuff,
12 -- The continuation type
13 SimplCont(..), DupFlag(..), contIsDupable, contResultType,
17 initSmpl, returnSmpl, thenSmpl, thenSmpl_,
18 mapSmpl, mapAndUnzipSmpl, mapAccumLSmpl,
21 getUniqueSmpl, getUniquesSmpl,
25 SimplCount, TickType(..), TickCounts,
27 getSimplCount, zeroSimplCount, pprSimplCount,
28 plusSimplCount, isZeroSimplCount,
31 SwitchChecker, getSwitchChecker, getSimplIntSwitch,
34 getEnclosingCC, setEnclosingCC,
38 getInScope, setInScope, extendInScope, extendInScopes, modifyInScope,
39 emptySubstEnv, getSubstEnv, setSubstEnv, zapSubstEnv,
40 extendIdSubst, extendTySubst,
42 getSimplBinderStuff, setSimplBinderStuff,
46 #include "HsVersions.h"
48 import Id ( Id, mkSysLocal, idMustBeINLINEd )
49 import IdInfo ( InlinePragInfo(..) )
50 import Demand ( Demand )
52 import CoreUtils ( IdSubst, SubstCoreExpr, coreExprType, coreAltsType )
53 import CostCentre ( CostCentreStack, subsumedCCS )
57 import Type ( Type, TyVarSubst, funResultTy, fullSubstTy, applyTy )
58 import UniqSupply ( uniqsFromSupply, uniqFromSupply, splitUniqSupply,
61 import CmdLineOpts ( SimplifierSwitch(..), SwitchResult(..), intSwitchSet )
62 import Unique ( Unique )
63 import Maybes ( expectJust )
64 import Util ( zipWithEqual )
67 infixr 9 `thenSmpl`, `thenSmpl_`
70 %************************************************************************
72 \subsection[Simplify-types]{Type declarations}
74 %************************************************************************
77 type InBinder = CoreBndr
78 type InId = Id -- Not yet cloned
79 type InType = Type -- Ditto
80 type InBind = CoreBind
81 type InExpr = CoreExpr
85 type OutBinder = CoreBndr
86 type OutId = Id -- Cloned
87 type OutType = Type -- Cloned
88 type OutBind = CoreBind
89 type OutExpr = CoreExpr
93 type SwitchChecker = SimplifierSwitch -> SwitchResult
97 %************************************************************************
99 \subsection{The continuation data type}
101 %************************************************************************
104 type OutExprStuff = OutStuff (InScopeEnv, OutExpr)
105 type OutStuff a = ([OutBind], a)
106 -- We return something equivalent to (let b in e), but
107 -- in pieces to avoid the quadratic blowup when floating
108 -- incrementally. Comments just before simplExprB in Simplify.lhs
110 data SimplCont -- Strict contexts
118 InExpr SubstEnv -- The argument, as yet unsimplified,
119 SimplCont -- and its subst-env
122 InId [InAlt] SubstEnv -- The case binder, alts, and subst-env
125 | ArgOf DupFlag -- An arbitrary strict context: the argument
126 (OutExpr -> SimplM OutExprStuff) -- of a strict function, or a primitive-arg fn
128 OutType -- Type of the result of the whole thing
130 instance Outputable SimplCont where
131 ppr Stop = ptext SLIT("Stop")
132 ppr (ApplyTo dup arg se cont) = (ptext SLIT("ApplyTo") <+> ppr dup <+> ppr arg) $$ ppr cont
133 ppr (ArgOf dup cont_fn _) = ptext SLIT("ArgOf...") <+> ppr dup
134 ppr (Select dup bndr alts se cont) = (ptext SLIT("Select") <+> ppr dup <+> ppr bndr) $$
135 (nest 4 (ppr alts)) $$ ppr cont
136 ppr (CoerceIt dup ty se cont) = (ptext SLIT("CoerceIt") <+> ppr dup <+> ppr ty) $$ ppr cont
138 data DupFlag = OkToDup | NoDup
140 instance Outputable DupFlag where
141 ppr OkToDup = ptext SLIT("ok")
142 ppr NoDup = ptext SLIT("nodup")
144 contIsDupable :: SimplCont -> Bool
145 contIsDupable Stop = True
146 contIsDupable (ApplyTo OkToDup _ _ _) = True
147 contIsDupable (ArgOf OkToDup _ _) = True
148 contIsDupable (Select OkToDup _ _ _ _) = True
149 contIsDupable (CoerceIt OkToDup _ _ _) = True
150 contIsDupable other = False
152 contResultType :: InScopeEnv -> Type -> SimplCont -> Type
153 contResultType in_scope e_ty cont
157 go e_ty (ApplyTo _ (Type ty) se cont) = go (applyTy e_ty (simpl se ty)) cont
158 go e_ty (ApplyTo _ val_arg _ cont) = go (funResultTy e_ty) cont
159 go e_ty (ArgOf _ fun cont_ty) = cont_ty
160 go e_ty (CoerceIt _ ty se cont) = go (simpl se ty) cont
161 go e_ty (Select _ _ alts se cont) = go (simpl se (coreAltsType alts)) cont
163 simpl (ty_subst, _) ty = fullSubstTy ty_subst in_scope ty
167 %************************************************************************
169 \subsection{Monad plumbing}
171 %************************************************************************
173 For the simplifier monad, we want to {\em thread} a unique supply and a counter.
174 (Command-line switches move around through the explicitly-passed SimplEnv.)
177 type SimplM result -- We thread the unique supply because
178 = SimplEnv -- constantly splitting it is rather expensive
181 -> (result, UniqSupply, SimplCount)
185 seChkr :: SwitchChecker,
186 seCC :: CostCentreStack, -- The enclosing CCS (when profiling)
187 seSubst :: SubstEnv, -- The current substitution
188 seInScope :: InScopeEnv -- Says what's in scope and gives info about it
193 initSmpl :: SwitchChecker
194 -> UniqSupply -- No init count; set to 0
198 initSmpl chkr us m = case m (emptySimplEnv chkr) us zeroSimplCount of
199 (result, _, count) -> (result, count)
202 {-# INLINE thenSmpl #-}
203 {-# INLINE thenSmpl_ #-}
204 {-# INLINE returnSmpl #-}
206 returnSmpl :: a -> SimplM a
207 returnSmpl e env us sc = (e, us, sc)
209 thenSmpl :: SimplM a -> (a -> SimplM b) -> SimplM b
210 thenSmpl_ :: SimplM a -> SimplM b -> SimplM b
212 thenSmpl m k env us0 sc0
213 = case (m env us0 sc0) of
214 (m_result, us1, sc1) -> k m_result env us1 sc1
216 thenSmpl_ m k env us0 sc0
217 = case (m env us0 sc0) of
218 (_, us1, sc1) -> k env us1 sc1
223 mapSmpl :: (a -> SimplM b) -> [a] -> SimplM [b]
224 mapAndUnzipSmpl :: (a -> SimplM (b, c)) -> [a] -> SimplM ([b],[c])
226 mapSmpl f [] = returnSmpl []
228 = f x `thenSmpl` \ x' ->
229 mapSmpl f xs `thenSmpl` \ xs' ->
232 mapAndUnzipSmpl f [] = returnSmpl ([],[])
233 mapAndUnzipSmpl f (x:xs)
234 = f x `thenSmpl` \ (r1, r2) ->
235 mapAndUnzipSmpl f xs `thenSmpl` \ (rs1, rs2) ->
236 returnSmpl (r1:rs1, r2:rs2)
238 mapAccumLSmpl f acc [] = returnSmpl (acc, [])
239 mapAccumLSmpl f acc (x:xs) = f acc x `thenSmpl` \ (acc', x') ->
240 mapAccumLSmpl f acc' xs `thenSmpl` \ (acc'', xs') ->
241 returnSmpl (acc'', x':xs')
245 %************************************************************************
247 \subsection{The unique supply}
249 %************************************************************************
252 getUniqueSmpl :: SimplM Unique
253 getUniqueSmpl env us sc = case splitUniqSupply us of
254 (us1, us2) -> (uniqFromSupply us1, us2, sc)
256 getUniquesSmpl :: Int -> SimplM [Unique]
257 getUniquesSmpl n env us sc = case splitUniqSupply us of
258 (us1, us2) -> (uniqsFromSupply n us1, us2, sc)
262 %************************************************************************
264 \subsection{Counting up what we've done}
266 %************************************************************************
269 doTickSmpl :: (SimplCount -> SimplCount) -> SimplM ()
270 doTickSmpl f env us sc = sc' `seq` ((), us, sc')
274 getSimplCount :: SimplM SimplCount
275 getSimplCount env us sc = (sc, us, sc)
279 The assoc list isn't particularly costly, because we only use
280 the number of ticks in ``real life.''
282 The right thing to do, if you want that to go fast, is thread
283 a mutable array through @SimplM@.
287 = SimplCount !TickCounts
290 type TickCounts = [(TickType, Int)] -- Assoc list of all diff kinds of ticks
291 -- Kept in increasing order of TickType
294 type UnfoldingHistory = (Int, -- N
295 [Id], -- Last N unfoldings
296 [Id]) -- The MaxUnfoldHistory unfoldings before that
299 = PreInlineUnconditionally
300 | PostInlineUnconditionally
317 deriving (Eq, Ord, Show)
319 pprSimplCount :: SimplCount -> SDoc
320 pprSimplCount (SimplCount stuff (_, unf1, unf2))
321 = vcat (map ppr_item stuff)
322 $$ (text "Most recent unfoldings (most recent at top):"
323 $$ nest 4 (vcat (map ppr (unf1 ++ unf2))))
325 ppr_item (t,n) = text (show t) <+> char '\t' <+> ppr n
327 zeroSimplCount :: SimplCount
328 zeroSimplCount = SimplCount [] (0, [], [])
330 isZeroSimplCount :: SimplCount -> Bool
331 isZeroSimplCount (SimplCount [] _) = True
332 isZeroSimplCount (SimplCount [(LeavesExamined,_)] _) = True
333 isZeroSimplCount other = False
335 -- incTick is careful to be pretty strict, so we don't
336 -- get a huge buildup of thunks
337 incTick :: TickType -> FAST_INT -> TickCounts -> TickCounts
338 incTick tick_type n []
339 = [(tick_type, IBOX(n))]
341 incTick tick_type n (x@(ttype, I# cnt#) : xs)
342 = case tick_type `compare` ttype of
344 (tick_type, IBOX(n)) : x : xs
348 incd -> (ttype, IBOX(incd)) : xs
353 rest = incTick tick_type n xs
355 -- Second argument is more recent stuff
356 plusSimplCount :: SimplCount -> SimplCount -> SimplCount
357 plusSimplCount (SimplCount tc1 uh1) (SimplCount tc2 uh2)
358 = SimplCount (plusTickCounts tc1 tc2) (plusUnfolds uh1 uh2)
360 plusTickCounts :: TickCounts -> TickCounts -> TickCounts
361 plusTickCounts ts1 [] = ts1
362 plusTickCounts [] ts2 = ts2
363 plusTickCounts ((tt1,n1) : ts1) ((tt2,n2) : ts2)
364 = case tt1 `compare` tt2 of
365 LT -> (tt1,n1) : plusTickCounts ts1 ((tt2,n2) : ts2)
366 EQ -> (tt1,n1+n2) : plusTickCounts ts1 ts2
367 GT -> (tt2,n2) : plusTickCounts ((tt1,n1) : ts1) ts2
369 -- Second argument is the more recent stuff
370 plusUnfolds uh1 (0, h2, t2) = uh1 -- Nothing recent
371 plusUnfolds (n1, h1, t1) (n2, h2, []) = (n2, h2, (h1++t1)) -- Small amount recent
372 plusUnfolds (n1, h1, t1) uh2 = uh2 -- Decent batch recent
376 Counting-related monad functions:
379 tick :: TickType -> SimplM ()
384 f (SimplCount stuff unf) = SimplCount (incTick tick_type ILIT(1) stuff) unf
386 maxUnfoldHistory :: Int
387 maxUnfoldHistory = 20
389 tickUnfold :: Id -> SimplM ()
393 f (SimplCount stuff (n_unf, unf1, unf2))
394 | n_unf >= maxUnfoldHistory = SimplCount new_stuff (1, [id], unf1)
395 | otherwise = SimplCount new_stuff (n_unf+1, id:unf1, unf2)
397 new_stuff = incTick UnfoldingDone ILIT(1) stuff
401 %************************************************************************
403 \subsubsection{Command-line switches}
405 %************************************************************************
408 getSwitchChecker :: SimplM SwitchChecker
409 getSwitchChecker env us sc = (seChkr env, us, sc)
411 getSimplIntSwitch :: SwitchChecker -> (Int-> SimplifierSwitch) -> Int
412 getSimplIntSwitch chkr switch
413 = expectJust "getSimplIntSwitch" (intSwitchSet chkr switch)
417 @switchOffInlining@ is used to prepare the environment for simplifying
418 the RHS of an Id that's marked with an INLINE pragma. It is going to
419 be inlined wherever they are used, and then all the inlining will take
420 effect. Meanwhile, there isn't much point in doing anything to the
421 as-yet-un-INLINEd rhs. Furthremore, it's very important to switch off
423 (a) not doing so will inline a worker straight back into its wrapper!
425 and (b) Consider the following example
430 in ...g...g...g...g...g...
432 Now, if that's the ONLY occurrence of f, it will be inlined inside g,
433 and thence copied multiple times when g is inlined.
435 Andy disagrees! Example:
436 all xs = foldr (&&) True xs
437 any p = all . map p {-# INLINE any #-}
439 Problem: any won't get deforested, and so if it's exported and
440 the importer doesn't use the inlining, (eg passes it as an arg)
441 then we won't get deforestation at all.
442 We havn't solved this problem yet!
444 We prepare the envt by simply modifying the in_scope_env, which has all the
445 unfolding info. At one point we did it by modifying the chkr so that
446 it said "EssentialUnfoldingsOnly", but that prevented legitmate, and
447 important, simplifications happening in the body of the RHS.
451 We *don't* prevent inlining from happening for identifiers
452 that are marked as IMustBeINLINEd. An example of where
453 doing this is crucial is:
455 class Bar a => Foo a where
461 If `f' needs to peer inside Foo's superclass, Bar, it refers
462 to the appropriate super class selector, which is marked as
463 must-inlineable. We don't generate any code for a superclass
464 selector, so failing to inline it in the RHS of `f' will
465 leave a reference to a non-existent id, with bad consequences.
467 ALSO NOTE that we do all this by modifing the inline-pragma,
468 not by zapping the unfolding. The latter may still be useful for
469 knowing when something is evaluated.
471 June 98 update: I've gone back to dealing with this by adding
472 the EssentialUnfoldingsOnly switch. That doesn't stop essential
473 unfoldings, nor inlineUnconditionally stuff; and the thing's going
474 to be inlined at every call site anyway. Running over the whole
475 environment seems like wild overkill.
478 switchOffInlining :: SimplM a -> SimplM a
479 switchOffInlining m env@(SimplEnv { seChkr = sw_chkr }) us sc
480 = m (env { seChkr = new_chkr }) us sc
482 new_chkr EssentialUnfoldingsOnly = SwBool True
483 new_chkr other = sw_chkr other
487 %************************************************************************
489 \subsubsection{The ``enclosing cost-centre''}
491 %************************************************************************
494 getEnclosingCC :: SimplM CostCentreStack
495 getEnclosingCC env us sc = (seCC env, us, sc)
497 setEnclosingCC :: CostCentreStack -> SimplM a -> SimplM a
498 setEnclosingCC cc m env us sc = m (env { seCC = cc }) us sc
502 %************************************************************************
504 \subsubsection{The @SimplEnv@ type}
506 %************************************************************************
509 type SubstEnv = (TyVarSubst, IdSubst)
510 -- The range of these substitutions is OutType and OutExpr resp
512 -- The substitution is idempotent
513 -- It *must* be applied; things in its domain simply aren't
514 -- bound in the result.
516 -- The substitution usually maps an Id to its clone,
517 -- but if the orig defn is a let-binding, and
518 -- the RHS of the let simplifies to an atom,
519 -- we just add the binding to the substitution and elide the let.
521 type InScopeEnv = IdOrTyVarSet
522 -- Domain includes *all* in-scope TyVars and Ids
524 -- The elements of the set may have better IdInfo than the
525 -- occurrences of in-scope Ids, and (more important) they will
526 -- have a correctly-substituted type. So we use a lookup in this
527 -- set to replace occurrences
529 -- INVARIANT: If t is in the in-scope set, it certainly won't be
530 -- in the domain of the SubstEnv, and vice versa
535 emptySubstEnv :: SubstEnv
536 emptySubstEnv = (emptyVarEnv, emptyVarEnv)
538 emptySimplEnv :: SwitchChecker -> SimplEnv
540 emptySimplEnv sw_chkr
541 = SimplEnv { seChkr = sw_chkr, seCC = subsumedCCS,
542 seSubst = emptySubstEnv,
543 seInScope = emptyVarSet }
545 -- The top level "enclosing CC" is "SUBSUMED".
547 getTyEnv :: SimplM (TyVarSubst, InScopeEnv)
548 getTyEnv (SimplEnv {seSubst = (ty_subst,_), seInScope = in_scope}) us sc
549 = ((ty_subst, in_scope), us, sc)
551 getValEnv :: SimplM (IdSubst, InScopeEnv)
552 getValEnv (SimplEnv {seSubst = (_, id_subst), seInScope = in_scope}) us sc
553 = ((id_subst, in_scope), us, sc)
555 getInScope :: SimplM InScopeEnv
556 getInScope env us sc = (seInScope env, us, sc)
558 setInScope :: InScopeEnv -> SimplM a -> SimplM a
559 setInScope in_scope m env us sc = m (env {seInScope = in_scope}) us sc
561 extendInScope :: CoreBndr -> SimplM a -> SimplM a
562 extendInScope v m env@(SimplEnv {seInScope = in_scope}) us sc
563 = m (env {seInScope = extendVarSet in_scope v}) us sc
565 extendInScopes :: [CoreBndr] -> SimplM a -> SimplM a
566 extendInScopes vs m env@(SimplEnv {seInScope = in_scope}) us sc
567 = m (env {seInScope = foldl extendVarSet in_scope vs}) us sc
569 modifyInScope :: CoreBndr -> SimplM a -> SimplM a
570 modifyInScope v m env us sc
572 | not (v `elemVarSet` seInScope env )
573 = pprTrace "modifyInScope: not in scope:" (ppr v)
577 = extendInScope v m env us sc
579 getSubstEnv :: SimplM SubstEnv
580 getSubstEnv env us sc = (seSubst env, us, sc)
582 setSubstEnv :: SubstEnv -> SimplM a -> SimplM a
583 setSubstEnv subst_env m env us sc = m (env {seSubst = subst_env}) us sc
585 extendIdSubst :: Id -> SubstCoreExpr -> SimplM a -> SimplM a
586 extendIdSubst id expr m env@(SimplEnv {seSubst = (ty_subst, id_subst)}) us sc
587 = m (env { seSubst = (ty_subst, extendVarEnv id_subst id expr) }) us sc
589 extendTySubst :: TyVar -> OutType -> SimplM a -> SimplM a
590 extendTySubst tv ty m env@(SimplEnv {seSubst = (ty_subst, id_subst)}) us sc
591 = m (env { seSubst = (extendVarEnv ty_subst tv ty, id_subst) }) us sc
593 zapSubstEnv :: SimplM a -> SimplM a
594 zapSubstEnv m env us sc = m (env {seSubst = emptySubstEnv}) us sc
596 getSimplBinderStuff :: SimplM (TyVarSubst, IdSubst, InScopeEnv, UniqSupply)
597 getSimplBinderStuff (SimplEnv {seSubst = (ty_subst, id_subst), seInScope = in_scope}) us sc
598 = ((ty_subst, id_subst, in_scope, us), us, sc)
600 setSimplBinderStuff :: (TyVarSubst, IdSubst, InScopeEnv, UniqSupply)
601 -> SimplM a -> SimplM a
602 setSimplBinderStuff (ty_subst, id_subst, in_scope, us) m env _ sc
603 = m (env {seSubst = (ty_subst, id_subst), seInScope = in_scope}) us sc
608 newId :: Type -> (Id -> SimplM a) -> SimplM a
609 -- Extends the in-scope-env too
610 newId ty m env@(SimplEnv {seInScope = in_scope}) us sc
611 = case splitUniqSupply us of
612 (us1, us2) -> m v (env {seInScope = extendVarSet in_scope v}) us2 sc
614 v = mkSysLocal SLIT("s") (uniqFromSupply us1) ty
616 newIds :: [Type] -> ([Id] -> SimplM a) -> SimplM a
617 newIds tys m env@(SimplEnv {seInScope = in_scope}) us sc
618 = case splitUniqSupply us of
619 (us1, us2) -> m vs (env {seInScope = foldl extendVarSet in_scope vs}) us2 sc
621 vs = zipWithEqual "newIds" (mkSysLocal SLIT("s"))
622 (uniqsFromSupply (length tys) us1) tys