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,
11 -- The continuation type
12 SimplCont(..), DupFlag(..), contIsDupable,
16 initSmpl, returnSmpl, thenSmpl, thenSmpl_,
17 mapSmpl, mapAndUnzipSmpl, mapAccumLSmpl,
20 getUniqueSmpl, getUniquesSmpl,
24 SimplCount, TickType(..), TickCounts,
26 getSimplCount, zeroSimplCount, pprSimplCount,
27 plusSimplCount, isZeroSimplCount,
30 SwitchChecker, getSwitchChecker, getSimplIntSwitch,
33 getEnclosingCC, setEnclosingCC,
37 getInScope, setInScope, extendInScope, extendInScopes, modifyInScope,
38 emptySubstEnv, getSubstEnv, setSubstEnv, zapSubstEnv,
39 extendIdSubst, extendTySubst,
41 getSimplBinderStuff, setSimplBinderStuff,
45 #include "HsVersions.h"
47 import Id ( Id, mkSysLocal, idMustBeINLINEd )
48 import IdInfo ( InlinePragInfo(..) )
50 import CoreUtils ( IdSubst, SubstCoreExpr )
51 import CostCentre ( CostCentreStack, subsumedCCS )
55 import Type ( Type, TyVarSubst )
56 import UniqSupply ( uniqsFromSupply, uniqFromSupply, splitUniqSupply,
59 import CmdLineOpts ( SimplifierSwitch(..), SwitchResult(..), intSwitchSet )
60 import Unique ( Unique )
61 import Maybes ( expectJust )
62 import Util ( zipWithEqual )
65 infixr 9 `thenSmpl`, `thenSmpl_`
68 %************************************************************************
70 \subsection[Simplify-types]{Type declarations}
72 %************************************************************************
75 type InBinder = CoreBndr
76 type InId = Id -- Not yet cloned
77 type InType = Type -- Ditto
78 type InBind = CoreBind
79 type InExpr = CoreExpr
83 type OutBinder = CoreBndr
84 type OutId = Id -- Cloned
85 type OutType = Type -- Cloned
86 type OutBind = CoreBind
87 type OutExpr = CoreExpr
91 type SwitchChecker = SimplifierSwitch -> SwitchResult
95 %************************************************************************
97 \subsection{The continuation data type}
99 %************************************************************************
110 InExpr SubstEnv -- The argument, as yet unsimplified,
111 SimplCont -- and its subst-env
114 InId [InAlt] SubstEnv -- The case binder, alts, and subst-env
117 instance Outputable SimplCont where
118 ppr Stop = ptext SLIT("Stop")
119 ppr (ApplyTo dup arg se cont) = (ptext SLIT("ApplyTo") <+> ppr dup <+> ppr arg) $$ ppr cont
120 ppr (Select dup bndr alts se cont) = (ptext SLIT("Select") <+> ppr dup <+> ppr bndr) $$
121 (nest 4 (ppr alts)) $$ ppr cont
122 ppr (CoerceIt dup ty se cont) = (ptext SLIT("CoerceIt") <+> ppr dup <+> ppr ty) $$ ppr cont
124 data DupFlag = OkToDup | NoDup
126 instance Outputable DupFlag where
127 ppr OkToDup = ptext SLIT("ok")
128 ppr NoDup = ptext SLIT("nodup")
130 contIsDupable :: SimplCont -> Bool
131 contIsDupable Stop = True
132 contIsDupable (ApplyTo OkToDup _ _ _) = True
133 contIsDupable (Select OkToDup _ _ _ _) = True
134 contIsDupable (CoerceIt OkToDup _ _ _) = True
135 contIsDupable other = False
139 %************************************************************************
141 \subsection{Monad plumbing}
143 %************************************************************************
145 For the simplifier monad, we want to {\em thread} a unique supply and a counter.
146 (Command-line switches move around through the explicitly-passed SimplEnv.)
149 type SimplM result -- We thread the unique supply because
150 = SimplEnv -- constantly splitting it is rather expensive
153 -> (result, UniqSupply, SimplCount)
157 seChkr :: SwitchChecker,
158 seCC :: CostCentreStack, -- The enclosing CCS (when profiling)
159 seSubst :: SubstEnv, -- The current substitution
160 seInScope :: InScopeEnv -- Says what's in scope and gives info about it
165 initSmpl :: SwitchChecker
166 -> UniqSupply -- No init count; set to 0
170 initSmpl chkr us m = case m (emptySimplEnv chkr) us zeroSimplCount of
171 (result, _, count) -> (result, count)
174 {-# INLINE thenSmpl #-}
175 {-# INLINE thenSmpl_ #-}
176 {-# INLINE returnSmpl #-}
178 returnSmpl :: a -> SimplM a
179 returnSmpl e env us sc = (e, us, sc)
181 thenSmpl :: SimplM a -> (a -> SimplM b) -> SimplM b
182 thenSmpl_ :: SimplM a -> SimplM b -> SimplM b
184 thenSmpl m k env us0 sc0
185 = case (m env us0 sc0) of
186 (m_result, us1, sc1) -> k m_result env us1 sc1
188 thenSmpl_ m k env us0 sc0
189 = case (m env us0 sc0) of
190 (_, us1, sc1) -> k env us1 sc1
195 mapSmpl :: (a -> SimplM b) -> [a] -> SimplM [b]
196 mapAndUnzipSmpl :: (a -> SimplM (b, c)) -> [a] -> SimplM ([b],[c])
198 mapSmpl f [] = returnSmpl []
200 = f x `thenSmpl` \ x' ->
201 mapSmpl f xs `thenSmpl` \ xs' ->
204 mapAndUnzipSmpl f [] = returnSmpl ([],[])
205 mapAndUnzipSmpl f (x:xs)
206 = f x `thenSmpl` \ (r1, r2) ->
207 mapAndUnzipSmpl f xs `thenSmpl` \ (rs1, rs2) ->
208 returnSmpl (r1:rs1, r2:rs2)
210 mapAccumLSmpl f acc [] = returnSmpl (acc, [])
211 mapAccumLSmpl f acc (x:xs) = f acc x `thenSmpl` \ (acc', x') ->
212 mapAccumLSmpl f acc' xs `thenSmpl` \ (acc'', xs') ->
213 returnSmpl (acc'', x':xs')
217 %************************************************************************
219 \subsection{The unique supply}
221 %************************************************************************
224 getUniqueSmpl :: SimplM Unique
225 getUniqueSmpl env us sc = case splitUniqSupply us of
226 (us1, us2) -> (uniqFromSupply us1, us2, sc)
228 getUniquesSmpl :: Int -> SimplM [Unique]
229 getUniquesSmpl n env us sc = case splitUniqSupply us of
230 (us1, us2) -> (uniqsFromSupply n us1, us2, sc)
234 %************************************************************************
236 \subsection{Counting up what we've done}
238 %************************************************************************
241 doTickSmpl :: (SimplCount -> SimplCount) -> SimplM ()
242 doTickSmpl f env us sc = sc' `seq` ((), us, sc')
246 getSimplCount :: SimplM SimplCount
247 getSimplCount env us sc = (sc, us, sc)
251 The assoc list isn't particularly costly, because we only use
252 the number of ticks in ``real life.''
254 The right thing to do, if you want that to go fast, is thread
255 a mutable array through @SimplM@.
259 = SimplCount !TickCounts
262 type TickCounts = [(TickType, Int)] -- Assoc list of all diff kinds of ticks
263 -- Kept in increasing order of TickType
266 type UnfoldingHistory = (Int, -- N
267 [Id], -- Last N unfoldings
268 [Id]) -- The MaxUnfoldHistory unfoldings before that
271 = PreInlineUnconditionally
272 | PostInlineUnconditionally
289 deriving (Eq, Ord, Show)
291 pprSimplCount :: SimplCount -> SDoc
292 pprSimplCount (SimplCount stuff (_, unf1, unf2))
293 = vcat (map ppr_item stuff)
294 $$ (text "Most recent unfoldings (most recent at top):"
295 $$ nest 4 (vcat (map ppr (unf1 ++ unf2))))
297 ppr_item (t,n) = text (show t) <+> char '\t' <+> ppr n
299 zeroSimplCount :: SimplCount
300 zeroSimplCount = SimplCount [] (0, [], [])
302 isZeroSimplCount :: SimplCount -> Bool
303 isZeroSimplCount (SimplCount [] _) = True
304 isZeroSimplCount (SimplCount [(LeavesExamined,_)] _) = True
305 isZeroSimplCount other = False
307 -- incTick is careful to be pretty strict, so we don't
308 -- get a huge buildup of thunks
309 incTick :: TickType -> FAST_INT -> TickCounts -> TickCounts
310 incTick tick_type n []
311 = [(tick_type, IBOX(n))]
313 incTick tick_type n (x@(ttype, I# cnt#) : xs)
314 = case tick_type `compare` ttype of
316 (tick_type, IBOX(n)) : x : xs
320 incd -> (ttype, IBOX(incd)) : xs
325 rest = incTick tick_type n xs
327 -- Second argument is more recent stuff
328 plusSimplCount :: SimplCount -> SimplCount -> SimplCount
329 plusSimplCount (SimplCount tc1 uh1) (SimplCount tc2 uh2)
330 = SimplCount (plusTickCounts tc1 tc2) (plusUnfolds uh1 uh2)
332 plusTickCounts :: TickCounts -> TickCounts -> TickCounts
333 plusTickCounts ts1 [] = ts1
334 plusTickCounts [] ts2 = ts2
335 plusTickCounts ((tt1,n1) : ts1) ((tt2,n2) : ts2)
336 = case tt1 `compare` tt2 of
337 LT -> (tt1,n1) : plusTickCounts ts1 ((tt2,n2) : ts2)
338 EQ -> (tt1,n1+n2) : plusTickCounts ts1 ts2
339 GT -> (tt2,n2) : plusTickCounts ((tt1,n1) : ts1) ts2
341 -- Second argument is the more recent stuff
342 plusUnfolds uh1 (0, h2, t2) = uh1 -- Nothing recent
343 plusUnfolds (n1, h1, t1) (n2, h2, []) = (n2, h2, (h1++t1)) -- Small amount recent
344 plusUnfolds (n1, h1, t1) uh2 = uh2 -- Decent batch recent
348 Counting-related monad functions:
351 tick :: TickType -> SimplM ()
356 f (SimplCount stuff unf) = SimplCount (incTick tick_type ILIT(1) stuff) unf
358 maxUnfoldHistory :: Int
359 maxUnfoldHistory = 20
361 tickUnfold :: Id -> SimplM ()
365 f (SimplCount stuff (n_unf, unf1, unf2))
366 | n_unf >= maxUnfoldHistory = SimplCount new_stuff (1, [id], unf1)
367 | otherwise = SimplCount new_stuff (n_unf+1, id:unf1, unf2)
369 new_stuff = incTick UnfoldingDone ILIT(1) stuff
373 %************************************************************************
375 \subsubsection{Command-line switches}
377 %************************************************************************
380 getSwitchChecker :: SimplM SwitchChecker
381 getSwitchChecker env us sc = (seChkr env, us, sc)
383 getSimplIntSwitch :: SwitchChecker -> (Int-> SimplifierSwitch) -> Int
384 getSimplIntSwitch chkr switch
385 = expectJust "getSimplIntSwitch" (intSwitchSet chkr switch)
389 @switchOffInlining@ is used to prepare the environment for simplifying
390 the RHS of an Id that's marked with an INLINE pragma. It is going to
391 be inlined wherever they are used, and then all the inlining will take
392 effect. Meanwhile, there isn't much point in doing anything to the
393 as-yet-un-INLINEd rhs. Furthremore, it's very important to switch off
395 (a) not doing so will inline a worker straight back into its wrapper!
397 and (b) Consider the following example
402 in ...g...g...g...g...g...
404 Now, if that's the ONLY occurrence of f, it will be inlined inside g,
405 and thence copied multiple times when g is inlined.
407 Andy disagrees! Example:
408 all xs = foldr (&&) True xs
409 any p = all . map p {-# INLINE any #-}
411 Problem: any won't get deforested, and so if it's exported and
412 the importer doesn't use the inlining, (eg passes it as an arg)
413 then we won't get deforestation at all.
414 We havn't solved this problem yet!
416 We prepare the envt by simply modifying the in_scope_env, which has all the
417 unfolding info. At one point we did it by modifying the chkr so that
418 it said "EssentialUnfoldingsOnly", but that prevented legitmate, and
419 important, simplifications happening in the body of the RHS.
423 We *don't* prevent inlining from happening for identifiers
424 that are marked as IMustBeINLINEd. An example of where
425 doing this is crucial is:
427 class Bar a => Foo a where
433 If `f' needs to peer inside Foo's superclass, Bar, it refers
434 to the appropriate super class selector, which is marked as
435 must-inlineable. We don't generate any code for a superclass
436 selector, so failing to inline it in the RHS of `f' will
437 leave a reference to a non-existent id, with bad consequences.
439 ALSO NOTE that we do all this by modifing the inline-pragma,
440 not by zapping the unfolding. The latter may still be useful for
441 knowing when something is evaluated.
443 June 98 update: I've gone back to dealing with this by adding
444 the EssentialUnfoldingsOnly switch. That doesn't stop essential
445 unfoldings, nor inlineUnconditionally stuff; and the thing's going
446 to be inlined at every call site anyway. Running over the whole
447 environment seems like wild overkill.
450 switchOffInlining :: SimplM a -> SimplM a
451 switchOffInlining m env@(SimplEnv { seChkr = sw_chkr }) us sc
452 = m (env { seChkr = new_chkr }) us sc
454 new_chkr EssentialUnfoldingsOnly = SwBool True
455 new_chkr other = sw_chkr other
459 %************************************************************************
461 \subsubsection{The ``enclosing cost-centre''}
463 %************************************************************************
466 getEnclosingCC :: SimplM CostCentreStack
467 getEnclosingCC env us sc = (seCC env, us, sc)
469 setEnclosingCC :: CostCentreStack -> SimplM a -> SimplM a
470 setEnclosingCC cc m env us sc = m (env { seCC = cc }) us sc
474 %************************************************************************
476 \subsubsection{The @SimplEnv@ type}
478 %************************************************************************
481 type SubstEnv = (TyVarSubst, IdSubst)
482 -- The range of these substitutions is OutType and OutExpr resp
484 -- The substitution is idempotent
485 -- It *must* be applied; things in its domain simply aren't
486 -- bound in the result.
488 -- The substitution usually maps an Id to its clone,
489 -- but if the orig defn is a let-binding, and
490 -- the RHS of the let simplifies to an atom,
491 -- we just add the binding to the substitution and elide the let.
493 type InScopeEnv = IdOrTyVarSet
494 -- Domain includes *all* in-scope TyVars and Ids
496 -- The elements of the set may have better IdInfo than the
497 -- occurrences of in-scope Ids, and (more important) they will
498 -- have a correctly-substituted type. So we use a lookup in this
499 -- set to replace occurrences
501 -- INVARIANT: If t is in the in-scope set, it certainly won't be
502 -- in the domain of the SubstEnv, and vice versa
507 emptySubstEnv :: SubstEnv
508 emptySubstEnv = (emptyVarEnv, emptyVarEnv)
510 emptySimplEnv :: SwitchChecker -> SimplEnv
512 emptySimplEnv sw_chkr
513 = SimplEnv { seChkr = sw_chkr, seCC = subsumedCCS,
514 seSubst = emptySubstEnv,
515 seInScope = emptyVarSet }
517 -- The top level "enclosing CC" is "SUBSUMED".
519 getTyEnv :: SimplM (TyVarSubst, InScopeEnv)
520 getTyEnv (SimplEnv {seSubst = (ty_subst,_), seInScope = in_scope}) us sc
521 = ((ty_subst, in_scope), us, sc)
523 getValEnv :: SimplM (IdSubst, InScopeEnv)
524 getValEnv (SimplEnv {seSubst = (_, id_subst), seInScope = in_scope}) us sc
525 = ((id_subst, in_scope), us, sc)
527 getInScope :: SimplM InScopeEnv
528 getInScope env us sc = (seInScope env, us, sc)
530 setInScope :: InScopeEnv -> SimplM a -> SimplM a
531 setInScope in_scope m env us sc = m (env {seInScope = in_scope}) us sc
533 extendInScope :: CoreBndr -> SimplM a -> SimplM a
534 extendInScope v m env@(SimplEnv {seInScope = in_scope}) us sc
535 = m (env {seInScope = extendVarSet in_scope v}) us sc
537 extendInScopes :: [CoreBndr] -> SimplM a -> SimplM a
538 extendInScopes vs m env@(SimplEnv {seInScope = in_scope}) us sc
539 = m (env {seInScope = foldl extendVarSet in_scope vs}) us sc
541 modifyInScope :: CoreBndr -> SimplM a -> SimplM a
542 modifyInScope v m env us sc
544 | not (v `elemVarSet` seInScope env )
545 = pprTrace "modifyInScope: not in scope:" (ppr v)
549 = extendInScope v m env us sc
551 getSubstEnv :: SimplM SubstEnv
552 getSubstEnv env us sc = (seSubst env, us, sc)
554 setSubstEnv :: SubstEnv -> SimplM a -> SimplM a
555 setSubstEnv subst_env m env us sc = m (env {seSubst = subst_env}) us sc
557 extendIdSubst :: Id -> SubstCoreExpr -> SimplM a -> SimplM a
558 extendIdSubst id expr m env@(SimplEnv {seSubst = (ty_subst, id_subst)}) us sc
559 = m (env { seSubst = (ty_subst, extendVarEnv id_subst id expr) }) us sc
561 extendTySubst :: TyVar -> OutType -> SimplM a -> SimplM a
562 extendTySubst tv ty m env@(SimplEnv {seSubst = (ty_subst, id_subst)}) us sc
563 = m (env { seSubst = (extendVarEnv ty_subst tv ty, id_subst) }) us sc
565 zapSubstEnv :: SimplM a -> SimplM a
566 zapSubstEnv m env us sc = m (env {seSubst = emptySubstEnv}) us sc
568 getSimplBinderStuff :: SimplM (TyVarSubst, IdSubst, InScopeEnv, UniqSupply)
569 getSimplBinderStuff (SimplEnv {seSubst = (ty_subst, id_subst), seInScope = in_scope}) us sc
570 = ((ty_subst, id_subst, in_scope, us), us, sc)
572 setSimplBinderStuff :: (TyVarSubst, IdSubst, InScopeEnv, UniqSupply)
573 -> SimplM a -> SimplM a
574 setSimplBinderStuff (ty_subst, id_subst, in_scope, us) m env _ sc
575 = m (env {seSubst = (ty_subst, id_subst), seInScope = in_scope}) us sc
580 newId :: Type -> (Id -> SimplM a) -> SimplM a
581 -- Extends the in-scope-env too
582 newId ty m env@(SimplEnv {seInScope = in_scope}) us sc
583 = case splitUniqSupply us of
584 (us1, us2) -> m v (env {seInScope = extendVarSet in_scope v}) us2 sc
586 v = mkSysLocal (uniqFromSupply us1) ty
588 newIds :: [Type] -> ([Id] -> SimplM a) -> SimplM a
589 newIds tys m env@(SimplEnv {seInScope = in_scope}) us sc
590 = case splitUniqSupply us of
591 (us1, us2) -> m vs (env {seInScope = foldl extendVarSet in_scope vs}) us2 sc
593 vs = zipWithEqual "newIds" mkSysLocal (uniqsFromSupply (length tys) us1) tys