2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
4 \section{Tidying up Core}
12 #include "HsVersions.h"
14 import CmdLineOpts ( DynFlags, DynFlag(..), opt_OmitInterfacePragmas )
16 import CoreUnfold ( noUnfolding, mkTopUnfolding, okToUnfoldInHiFile )
17 import CoreUtils ( exprArity )
18 import CoreFVs ( ruleSomeFreeVars, exprSomeFreeVars )
19 import CoreLint ( showPass, endPass )
22 import Var ( Id, Var )
23 import Id ( idType, idInfo, idName, isExportedId,
24 mkId, isLocalId, omitIfaceSigForId
26 import IdInfo ( IdInfo, mkIdInfo, vanillaIdInfo,
27 IdFlavour(..), flavourInfo, ppFlavourInfo,
28 specInfo, setSpecInfo,
30 inlinePragInfo, setInlinePragInfo, isNeverInlinePrag,
31 strictnessInfo, setStrictnessInfo,
32 isBottomingStrictness,
33 unfoldingInfo, setUnfoldingInfo,
34 occInfo, isLoopBreaker,
35 workerInfo, setWorkerInfo, WorkerInfo(..),
36 ArityInfo(..), setArityInfo
38 import Name ( getOccName, nameOccName, globaliseName, setNameOcc,
39 localiseName, mkLocalName, isGlobalName
41 import OccName ( TidyOccEnv, initTidyOccEnv, tidyOccName )
42 import Type ( tidyTopType, tidyType, tidyTyVar )
43 import Module ( Module, moduleName )
44 import HscTypes ( PersistentCompilerState( pcs_PRS ), PersistentRenamerState( prsOrig ),
45 OrigNameEnv( origNames ), OrigNameNameEnv
48 import FiniteMap ( lookupFM, addToFM )
49 import Maybes ( maybeToBool, orElse )
50 import ErrUtils ( showPass )
51 import SrcLoc ( noSrcLoc )
52 import UniqFM ( mapUFM )
54 import List ( partition )
55 import Util ( mapAccumL )
60 %************************************************************************
62 \subsection{What goes on}
64 %************************************************************************
70 Step 1: Figure out external Ids
71 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
72 First we figure out which Ids are "external" Ids. An
73 "external" Id is one that is visible from outside the compilation
75 a) the user exported ones
76 b) ones mentioned in the unfoldings, workers,
77 or rules of externally-visible ones
78 This exercise takes a sweep of the bindings bottom to top. Actually,
79 in Step 2 we're also going to need to know which Ids should be
80 exported with their unfoldings, so we produce not an IdSet but an
84 Step 2: Tidy the program
85 ~~~~~~~~~~~~~~~~~~~~~~~~
86 Next we traverse the bindings top to bottom. For each top-level
89 - Make all external Ids have Global names and vice versa
90 This is used by the code generator to decide whether
91 to make the label externally visible
93 - Give external ids a "tidy" occurrence name. This means
94 we can print them in interface files without confusing
95 "x" (unique 5) with "x" (unique 10).
97 - Give external Ids the same Unique as they had before
98 if the name is in the renamer's name cache
100 - Clone all local Ids. This means that Tidy Core has the property
101 that all Ids are unique, rather than the weaker guarantee of
102 no clashes which the simplifier provides.
104 - Give the Id its final IdInfo; in ptic,
105 * Its flavour becomes ConstantId, reflecting the fact that
106 from now on we regard it as a constant, not local, Id
107 * its unfolding, if it should have one
109 Finally, substitute these new top-level binders consistently
110 throughout, including in unfoldings. We also tidy binders in
111 RHSs, so that they print nicely in interfaces.
114 tidyCorePgm :: DynFlags -> Module
115 -> PersistentCompilerState
116 -> [CoreBind] -> [IdCoreRule]
117 -> IO (PersistentCompilerState, [CoreBind], [IdCoreRule])
118 tidyCorePgm dflags mod pcs binds_in orphans_in
119 = do { showPass dflags "Tidy Core"
121 ; let ext_ids = findExternalSet binds_in orphans_in
123 ; us <- mkSplitUniqSupply 't' -- for "tidy"
125 ; let ((us1, orig_env', occ_env, subst_env), binds_out)
126 = mapAccumL (tidyTopBind mod ext_ids)
127 (init_tidy_env us) binds_in
129 ; let (orphans_out, _)
130 = initUs us1 (tidyIdRules (occ_env,subst_env) orphans_in)
132 ; let prs' = prs { prsOrig = orig { origNames = orig_env' } }
133 pcs' = pcs { pcs_PRS = prs' }
135 ; endPass dflags "Tidy Core" Opt_D_dump_simpl binds_out
137 ; return (pcs', binds_out, orphans_out)
140 -- We also make sure to avoid any exported binders. Consider
141 -- f{-u1-} = 1 -- Local decl
143 -- f{-u2-} = 2 -- Exported decl
145 -- The second exported decl must 'get' the name 'f', so we
146 -- have to put 'f' in the avoids list before we get to the first
147 -- decl. tidyTopId then does a no-op on exported binders.
150 orig_env = origNames orig
152 init_tidy_env us = (us, orig_env, initTidyOccEnv avoids, emptyVarEnv)
153 avoids = [getOccName bndr | bndr <- bindersOfBinds binds_in,
154 isGlobalName (idName bndr)]
158 %************************************************************************
160 \subsection{Step 1: finding externals}
162 %************************************************************************
165 findExternalSet :: [CoreBind] -> [IdCoreRule]
166 -> IdEnv Bool -- True <=> show unfolding
167 -- Step 1 from the notes above
168 findExternalSet binds orphan_rules
169 = foldr find init_needed binds
171 orphan_rule_ids :: IdSet
172 orphan_rule_ids = unionVarSets [ ruleSomeFreeVars isIdAndLocal rule
173 | (_, rule) <- orphan_rules]
174 init_needed :: IdEnv Bool
175 init_needed = mapUFM (\_ -> False) orphan_rule_ids
176 -- The mapUFM is a bit cheesy. It is a cheap way
177 -- to turn the set of orphan_rule_ids, which we use to initialise
178 -- the sweep, into a mapping saying 'don't expose unfolding'
179 -- (When we come to the binding site we may change our mind, of course.)
181 find (NonRec id rhs) needed
182 | need_id needed id = addExternal (id,rhs) needed
184 find (Rec prs) needed = find_prs prs needed
186 -- For a recursive group we have to look for a fixed point
188 | null needed_prs = needed
189 | otherwise = find_prs other_prs new_needed
191 (needed_prs, other_prs) = partition (need_pr needed) prs
192 new_needed = foldr addExternal needed needed_prs
194 -- The 'needed' set contains the Ids that are needed by earlier
195 -- interface file emissions. If the Id isn't in this set, and isn't
196 -- exported, there's no need to emit anything
197 need_id needed_set id = id `elemVarEnv` needed_set || isExportedId id
198 need_pr needed_set (id,rhs) = need_id needed_set id
200 isIdAndLocal id = isId id && isLocalId id
202 addExternal :: (Id,CoreExpr) -> IdEnv Bool -> IdEnv Bool
203 -- The Id is needed; extend the needed set
204 -- with it and its dependents (free vars etc)
205 addExternal (id,rhs) needed
206 = extendVarEnv (foldVarSet add_occ needed new_needed_ids)
209 add_occ id needed = extendVarEnv needed id False
210 -- "False" because we don't know we need the Id's unfolding
211 -- We'll override it later when we find the binding site
213 new_needed_ids | opt_OmitInterfacePragmas = emptyVarSet
214 | otherwise = worker_ids `unionVarSet`
215 unfold_ids `unionVarSet`
219 dont_inline = isNeverInlinePrag (inlinePragInfo idinfo)
220 loop_breaker = isLoopBreaker (occInfo idinfo)
221 bottoming_fn = isBottomingStrictness (strictnessInfo idinfo)
222 spec_ids = rulesRhsFreeVars (specInfo idinfo)
223 worker_info = workerInfo idinfo
225 -- Stuff to do with the Id's unfolding
226 -- The simplifier has put an up-to-date unfolding
227 -- in the IdInfo, but the RHS will do just as well
228 unfolding = unfoldingInfo idinfo
229 rhs_is_small = not (neverUnfold unfolding)
231 -- We leave the unfolding there even if there is a worker
232 -- In GHCI the unfolding is used by importers
233 -- When writing an interface file, we omit the unfolding
234 -- if there is a worker
235 show_unfold = not bottoming_fn && -- Not necessary
238 rhs_is_small && -- Small enough
239 okToUnfoldInHiFile rhs -- No casms etc
241 unfold_ids | show_unfold = exprSomeFreeVars isIdAndLocal rhs
242 | otherwise = emptyVarSet
244 worker_ids = case worker_info of
245 HasWorker work_id _ -> unitVarSet work_id
246 otherwise -> emptyVarSet
250 %************************************************************************
252 \subsection{Step 2: top-level tidying}
254 %************************************************************************
258 type TopTidyEnv = (UniqSupply, OrigNameNameEnv, TidyOccEnv, VarEnv Var)
260 -- TopTidyEnv: when tidying we need to know
261 -- * orig_env: Any pre-ordained Names. These may have arisen because the
262 -- renamer read in an interface file mentioning M.$wf, say,
263 -- and assigned it unique r77. If, on this compilation, we've
264 -- invented an Id whose name is $wf (but with a different unique)
265 -- we want to rename it to have unique r77, so that we can do easy
266 -- comparisons with stuff from the interface file
268 -- * occ_env: The TidyOccEnv, which tells us which local occurrences
271 -- * subst_env: A Var->Var mapping that substitutes the new Var for the old
273 -- * uniqsuppy: so we can clone any Ids with non-preordained names.
279 tidyTopBind :: Module
280 -> IdEnv Bool -- Domain = Ids that should be external
281 -- True <=> their unfolding is external too
282 -> TopTidyEnv -> CoreBind
283 -> (TopTidyEnv, CoreBind)
285 tidyTopBind mod ext_ids env (NonRec bndr rhs)
286 = ((us2,orig,occ,subst) , NonRec bndr' rhs')
288 tidy_env = (occ,subst)
289 ((us1,orig,occ,subst), bndr') = tidyTopBinder mod ext_ids tidy_env rhs' env bndr
290 (rhs',us2) = initUs us1 (tidyExpr tidy_env rhs)
292 tidyTopBind mod ext_ids env (Rec prs)
293 = (final_env, Rec prs')
295 (final_env@(_,_,occ,subst), prs') = mapAccumL do_one env prs
296 final_tidy_env = (occ,subst)
298 do_one env (bndr,rhs)
299 = ((us',orig,occ,subst), (bndr',rhs'))
301 ((us,orig,occ,subst), bndr') = tidyTopBinder mod ext_ids final_tidy_env rhs' env bndr
302 (rhs', us') = initUs us (tidyExpr final_tidy_env rhs)
304 tidyTopBinder :: Module -> IdEnv Bool
305 -> TidyEnv -> CoreExpr -- The TidyEnv is used to tidy the IdInfo
306 -- The expr is the already-tided RHS
307 -- Both are knot-tied: don't look at them!
308 -> TopTidyEnv -> Id -> (TopTidyEnv, Id)
309 tidyTopBinder mod ext_ids tidy_env rhs
310 env@(us, orig_env2, occ_env2, subst_env2) id
312 | omitIfaceSigForId id -- Don't mess with constructors,
313 = (env, id) -- record selectors, and the like
316 -- This function is the heart of Step 2
317 -- The second env is the one to use for the IdInfo
318 -- It's necessary because when we are dealing with a recursive
319 -- group, a variable late in the group might be mentioned
320 -- in the IdInfo of one early in the group
322 -- The rhs is already tidied
324 = ((us_r, orig_env', occ_env', subst_env'), id')
326 (us_l, us_r) = splitUniqSupply us
328 (orig_env', occ_env', name') = tidyTopName mod orig_env2 occ_env2
331 ty' = tidyTopType (idType id)
332 idinfo' = tidyIdInfo us_l tidy_env
333 is_external unfold_info arity_info id
335 id' = mkId name' ty' idinfo'
336 subst_env' = extendVarEnv subst_env2 id id'
338 maybe_external = lookupVarEnv ext_ids id
339 is_external = maybeToBool maybe_external
341 -- Expose an unfolding if ext_ids tells us to
342 show_unfold = maybe_external `orElse` False
343 unfold_info | show_unfold = mkTopUnfolding rhs
344 | otherwise = noUnfolding
346 arity_info = exprArity rhs
349 tidyIdInfo us tidy_env is_external unfold_info arity_info id
350 | opt_OmitInterfacePragmas || not is_external
351 -- No IdInfo if the Id isn't external, or if we don't have -O
352 = mkIdInfo new_flavour
353 `setStrictnessInfo` strictnessInfo core_idinfo
354 `setArityInfo` ArityExactly arity_info
355 -- Keep strictness and arity info; it's used by the code generator
358 = let (rules', _) = initUs us (tidyRules tidy_env (specInfo core_idinfo))
361 `setCprInfo` cprInfo core_idinfo
362 `setStrictnessInfo` strictnessInfo core_idinfo
363 `setInlinePragInfo` inlinePragInfo core_idinfo
364 `setUnfoldingInfo` unfold_info
365 `setWorkerInfo` tidyWorker tidy_env (workerInfo core_idinfo)
367 `setArityInfo` ArityExactly arity_info
368 -- this is the final IdInfo, it must agree with the
369 -- code finally generated (i.e. NO more transformations
372 core_idinfo = idInfo id
374 -- A DFunId must stay a DFunId, so that we can gather the
375 -- DFunIds up later. Other local things become ConstantIds.
376 new_flavour = case flavourInfo core_idinfo of
377 VanillaId -> ConstantId
378 ExportedId -> ConstantId
379 ConstantId -> ConstantId -- e.g. Default methods
380 DictFunId -> DictFunId
381 flavour -> pprTrace "tidyIdInfo" (ppr id <+> ppFlavourInfo flavour)
384 -- This is where we set names to local/global based on whether they really are
385 -- externally visible (see comment at the top of this module). If the name
386 -- was previously local, we have to give it a unique occurrence name if
387 -- we intend to globalise it.
388 tidyTopName mod orig_env occ_env external name
389 | global && internal = (orig_env, occ_env, localiseName name)
391 | local && internal = (orig_env, occ_env', setNameOcc name occ')
392 -- Even local, internal names must get a unique occurrence, because
393 -- if we do -split-objs we globalise the name later, n the code generator
395 | global && external = (orig_env, occ_env, name)
396 -- Global names are assumed to have been allocated by the renamer,
397 -- so they already have the "right" unique
399 | local && external = case lookupFM orig_env key of
400 Just orig -> (orig_env, occ_env', orig)
401 Nothing -> (addToFM orig_env key global_name, occ_env', global_name)
402 -- If we want to globalise a currently-local name, check
403 -- whether we have already assigned a unique for it.
404 -- If so, use it; if not, extend the table
407 (occ_env', occ') = tidyOccName occ_env (nameOccName name)
408 key = (moduleName mod, occ')
409 global_name = globaliseName (setNameOcc name occ') mod
410 global = isGlobalName name
412 internal = not external
414 tidyIdRules :: TidyEnv -> [IdCoreRule] -> UniqSM [IdCoreRule]
415 tidyIdRules env [] = returnUs []
416 tidyIdRules env ((fn,rule) : rules)
417 = tidyRule env rule `thenUs` \ rule ->
418 tidyIdRules env rules `thenUs` \ rules ->
419 returnUs ((tidyVarOcc env fn, rule) : rules)
421 tidyWorker tidy_env (HasWorker work_id wrap_arity)
422 = HasWorker (tidyVarOcc tidy_env work_id) wrap_arity
423 tidyWorker tidy_env NoWorker
426 tidyRules :: TidyEnv -> CoreRules -> UniqSM CoreRules
427 tidyRules env (Rules rules fvs)
428 = mapUs (tidyRule env) rules `thenUs` \ rules ->
429 returnUs (Rules rules (foldVarSet tidy_set_elem emptyVarSet fvs))
431 tidy_set_elem var new_set = extendVarSet new_set (tidyVarOcc env var)
433 tidyRule :: TidyEnv -> CoreRule -> UniqSM CoreRule
434 tidyRule env rule@(BuiltinRule _) = returnUs rule
435 tidyRule env (Rule name vars tpl_args rhs)
436 = tidyBndrs env vars `thenUs` \ (env', vars) ->
437 mapUs (tidyExpr env') tpl_args `thenUs` \ tpl_args ->
438 tidyExpr env' rhs `thenUs` \ rhs ->
439 returnUs (Rule name vars tpl_args rhs)
442 %************************************************************************
444 \subsection{Step 2: inner tidying
446 %************************************************************************
451 -> UniqSM (TidyEnv, CoreBind)
452 tidyBind env (NonRec bndr rhs)
453 = tidyBndrWithRhs env (bndr,rhs) `thenUs` \ (env', bndr') ->
454 tidyExpr env' rhs `thenUs` \ rhs' ->
455 returnUs (env', NonRec bndr' rhs')
457 tidyBind env (Rec prs)
458 = mapAccumLUs tidyBndrWithRhs env prs `thenUs` \ (env', bndrs') ->
459 mapUs (tidyExpr env') (map snd prs) `thenUs` \ rhss' ->
460 returnUs (env', Rec (zip bndrs' rhss'))
462 tidyExpr env (Var v) = returnUs (Var (tidyVarOcc env v))
463 tidyExpr env (Type ty) = returnUs (Type (tidyType env ty))
464 tidyExpr env (Lit lit) = returnUs (Lit lit)
466 tidyExpr env (App f a)
467 = tidyExpr env f `thenUs` \ f ->
468 tidyExpr env a `thenUs` \ a ->
471 tidyExpr env (Note n e)
472 = tidyExpr env e `thenUs` \ e ->
473 returnUs (Note (tidyNote env n) e)
475 tidyExpr env (Let b e)
476 = tidyBind env b `thenUs` \ (env', b') ->
477 tidyExpr env' e `thenUs` \ e ->
480 tidyExpr env (Case e b alts)
481 = tidyExpr env e `thenUs` \ e ->
482 tidyBndr env b `thenUs` \ (env', b) ->
483 mapUs (tidyAlt env') alts `thenUs` \ alts ->
484 returnUs (Case e b alts)
486 tidyExpr env (Lam b e)
487 = tidyBndr env b `thenUs` \ (env', b) ->
488 tidyExpr env' e `thenUs` \ e ->
492 tidyAlt env (con, vs, rhs)
493 = tidyBndrs env vs `thenUs` \ (env', vs) ->
494 tidyExpr env' rhs `thenUs` \ rhs ->
495 returnUs (con, vs, rhs)
497 tidyNote env (Coerce t1 t2) = Coerce (tidyType env t1) (tidyType env t2)
498 tidyNote env note = note
502 %************************************************************************
504 \subsection{Tidying up non-top-level binders}
506 %************************************************************************
509 tidyVarOcc (_, var_env) v = case lookupVarEnv var_env v of
513 -- tidyBndr is used for lambda and case binders
514 tidyBndr :: TidyEnv -> Var -> UniqSM (TidyEnv, Var)
516 | isTyVar var = returnUs (tidyTyVar env var)
517 | otherwise = tidyId env var vanillaIdInfo
519 tidyBndrs :: TidyEnv -> [Var] -> UniqSM (TidyEnv, [Var])
520 tidyBndrs env vars = mapAccumLUs tidyBndr env vars
522 -- tidyBndrWithRhs is used for let binders
523 tidyBndrWithRhs :: TidyEnv -> (Var, CoreExpr) -> UniqSM (TidyEnv, Var)
524 tidyBndrWithRhs env (id,rhs)
525 = tidyId env id idinfo
527 idinfo = vanillaIdInfo `setArityInfo` ArityExactly (exprArity rhs)
528 -- NB: This throws away the IdInfo of the Id, which we
529 -- no longer need. That means we don't need to
530 -- run over it with env, nor renumber it.
532 tidyId :: TidyEnv -> Id -> IdInfo -> UniqSM (TidyEnv, Id)
533 tidyId env@(tidy_env, var_env) id idinfo
534 = -- Non-top-level variables
535 getUniqueUs `thenUs` \ uniq ->
537 -- Give the Id a fresh print-name, *and* rename its type
538 -- The SrcLoc isn't important now,
539 -- though we could extract it from the Id
540 name' = mkLocalName uniq occ' noSrcLoc
541 (tidy_env', occ') = tidyOccName tidy_env (getOccName id)
542 ty' = tidyType (tidy_env,var_env) (idType id)
543 id' = mkId name' ty' idinfo
544 var_env' = extendVarEnv var_env id id'
546 returnUs ((tidy_env', var_env'), id')