2 % (c) The GRASP/AQUA Project, Glasgow University, 1993-1995
4 \section[SimplStg]{Driver for simplifying @STG@ programs}
7 #include "HsVersions.h"
9 module SimplStg ( stg2stg ) where
12 IMPORT_1_3(IO(hPutStr,stderr))
16 import LambdaLift ( liftProgram )
17 import Name ( isLocallyDefined )
18 import UniqSet ( UniqSet(..), mapUniqSet )
19 import SCCfinal ( stgMassageForProfiling )
20 import StgLint ( lintStgBindings )
21 import StgStats ( showStgStats )
22 import StgVarInfo ( setStgVarInfo )
23 import UpdAnal ( updateAnalyse )
25 import CmdLineOpts ( opt_SccGroup, --Not used:opt_EnsureSplittableC,
26 opt_StgDoLetNoEscapes, opt_D_verbose_stg2stg,
30 import Id ( nullIdEnv, lookupIdEnv, addOneToIdEnv,
31 growIdEnvList, isNullIdEnv, SYN_IE(IdEnv),
33 GenId{-instance Eq/Outputable -}
35 import Maybes ( maybeToBool )
36 import PprType ( GenType{-instance Outputable-} )
37 import Pretty ( ppShow, ppAbove, ppAboves, ppStr, ppPStr )
38 import UniqSupply ( splitUniqSupply )
39 import Util ( mapAccumL, panic, assertPanic )
44 stg2stg :: [StgToDo] -- spec of what stg-to-stg passes to do
45 -> FAST_STRING -- module name (profiling only)
46 -> PprStyle -- printing style (for debugging only)
47 -> UniqSupply -- a name supply
48 -> [StgBinding] -- input...
50 ([StgBinding], -- output program...
51 ([CostCentre], -- local cost-centres that need to be decl'd
52 [CostCentre])) -- "extern" cost-centres
54 stg2stg stg_todos module_name ppr_style us binds
55 = case (splitUniqSupply us) of { (us4now, us4later) ->
57 (if do_verbose_stg2stg then
58 hPutStr stderr "VERBOSE STG-TO-STG:\n" >>
59 hPutStr stderr (ppShow 1000
60 (ppAbove (ppPStr SLIT("*** Core2Stg:"))
61 (ppAboves (map (ppr ppr_style) (setStgVarInfo False binds)))
65 -- Do the main business!
66 foldl_mn do_stg_pass (binds, us4now, ([],[])) stg_todos
67 >>= \ (processed_binds, _, cost_centres) ->
69 -- Do essential wind-up
71 {- Nuked for now SLPJ Dec 96
73 -- Essential wind-up: part (a), saturate RHSs
74 -- This must occur *after* elimIndirections, because elimIndirections
75 -- can change things' arities. Consider:
77 -- x_global = \a -> x_local a
78 -- Then elimIndirections will change the program to
80 -- and lo and behold x_global's arity has changed!
81 case (satStgRhs processed_binds us4later) of { saturated_binds ->
84 -- Essential wind-up: part (b), do setStgVarInfo. It has to
85 -- happen regardless, because the code generator uses its
88 -- Why does it have to happen last? Because earlier passes
89 -- may move things around, which would change the live-var
90 -- info. Also, setStgVarInfo decides about let-no-escape
91 -- things, which in turn do a better job if arities are
92 -- correct, which is done by satStgRhs.
96 Done in Core now. Nuke soon. SLPJ Nov 96
98 No, STG passes may introduce toplevel bindings which
99 have to be globalised here (later than Core anyway) -- SOF 2/97
101 Yes, lambda lifting now does the Right Thing.
104 -- ToDo: provide proper flag control!
106 = if not do_unlocalising
108 else snd (unlocaliseStgBinds unlocal_tag nullIdEnv processed_binds)
112 return (setStgVarInfo do_let_no_escapes processed_binds, cost_centres)
115 do_let_no_escapes = opt_StgDoLetNoEscapes
116 do_verbose_stg2stg = opt_D_verbose_stg2stg
119 (do_unlocalising, unlocal_tag)
120 = case opt_EnsureSplittableC of
121 Just tag -> (True, _PK_ tag)
122 Nothing -> (False, panic "tag")
124 grp_name = case (opt_SccGroup) of
126 Nothing -> module_name -- default: module name
129 stg_linter = if False --LATER: opt_DoStgLinting (ToDo)
130 then lintStgBindings ppr_style
131 else ( \ whodunnit binds -> binds )
133 -------------------------------------------
134 do_stg_pass (binds, us, ccs) to_do
136 (us1, us2) = splitUniqSupply us
139 StgDoStaticArgs -> panic "STG static argument transformation deleted"
141 StgDoUpdateAnalysis ->
142 ASSERT(null (fst ccs) && null (snd ccs))
144 -- NB We have to do setStgVarInfo first! (There's one
145 -- place free-var info is used) But no let-no-escapes,
146 -- because update analysis doesn't care.
147 end_pass us2 "UpdAnal" ccs (updateAnalyse (setStgVarInfo False binds))
150 trace (showStgStats binds)
151 end_pass us2 "StgStats" ccs binds
154 _scc_ "StgLambdaLift"
155 -- NB We have to do setStgVarInfo first!
157 binds3 = liftProgram module_name us1 (setStgVarInfo do_let_no_escapes binds)
159 end_pass us2 "LambdaLift" ccs binds3
161 StgDoMassageForProfiling ->
164 (collected_CCs, binds3)
165 = stgMassageForProfiling module_name grp_name us1 binds
167 end_pass us2 "ProfMassage" collected_CCs binds3
169 end_pass us2 what ccs binds2
170 = -- report verbosely, if required
171 (if do_verbose_stg2stg then
172 hPutStr stderr (ppShow 1000
173 (ppAbove (ppStr ("*** "++what++":"))
174 (ppAboves (map (ppr ppr_style) binds2))
178 linted_binds = stg_linter what binds2
180 return (linted_binds, us2, ccs)
181 -- return: processed binds
182 -- UniqueSupply for the next guy to use
183 -- cost-centres to be declared/registered (specialised)
184 -- add to description of what's happened (reverse order)
186 -- here so it can be inlined...
187 foldl_mn f z [] = return z
188 foldl_mn f z (x:xs) = f z x >>= \ zz ->
192 %************************************************************************
194 \subsection[SimplStg-unlocalise]{Unlocalisation in STG code}
196 %************************************************************************
198 The idea of all this ``unlocalise'' stuff is that in certain (prelude
199 only) modules we split up the .hc file into lots of separate little
200 files, which are separately compiled by the C compiler. That gives
201 lots of little .o files. The idea is that if you happen to mention
202 one of them you don't necessarily pull them all in. (Pulling in a
203 piece you don't need can be v bad, because it may mention other pieces
204 you don't need either, and so on.)
206 Sadly, splitting up .hc files means that local names (like s234) are
207 now globally visible, which can lead to clashes between two .hc
208 files. So unlocaliseWhatnot goes through making all the local things
209 into global things, essentially by giving them full names so when they
210 are printed they'll have their module name too. Pretty revolting
214 type UnlocalEnv = IdEnv Id
216 lookup_uenv :: UnlocalEnv -> Id -> Id
217 lookup_uenv env id = case lookupIdEnv env id of
219 Just new_id -> new_id
220 unlocaliseStgBinds :: FAST_STRING
223 -> (UnlocalEnv, [StgBinding])
224 unlocaliseStgBinds mod uenv [] = (uenv, [])
225 unlocaliseStgBinds mod uenv (b : bs) =
226 case unlocal_top_bind mod uenv b of { (new_uenv, new_b) ->
227 case unlocaliseStgBinds mod new_uenv bs of { (uenv3, new_bs) ->
228 (uenv3, new_b : new_bs)
232 unlocal_top_bind :: FAST_STRING
235 -> (UnlocalEnv, StgBinding)
236 unlocal_top_bind mod uenv bind@(StgNonRec binder _) =
239 case lookupIdEnv uenv binder of
243 new_env = addOneToIdEnv uenv binder new_global
244 new_global = setIdVisibility mod binder
246 (new_uenv, renameTopStgBind (lookup_uenv new_uenv) bind)
248 unlocal_top_bind mod uenv bind@(StgRec pairs) =
250 new_env binder uenv =
251 case lookupIdEnv uenv binder of
255 env' = addOneToIdEnv uenv binder new_global
256 new_global = setIdVisibility mod binder
258 uenv' = foldr (new_env) uenv (map (fst) pairs)
260 (uenv', renameTopStgBind (lookup_uenv uenv') bind)
264 @renameTopStgBind@ renames top level binders and all occurrences thereof.
267 renameTopStgBind :: (Id -> Id) -> StgBinding -> StgBinding
268 renameTopStgBind fn (StgNonRec b rhs) = StgNonRec (fn b) (mapStgBindeesRhs fn rhs)
269 renameTopStgBind fn (StgRec pairs) = StgRec [ (fn b, mapStgBindeesRhs fn r) | (b, r) <- pairs ]
272 This utility function simply applies the given function to every
273 bindee in the program.
276 mapStgBindeesBind :: (Id -> Id) -> StgBinding -> StgBinding
277 mapStgBindeesBind fn (StgNonRec b rhs) = StgNonRec b (mapStgBindeesRhs fn rhs)
278 mapStgBindeesBind fn (StgRec pairs) = StgRec [ (b, mapStgBindeesRhs fn r) | (b, r) <- pairs ]
281 mapStgBindeesRhs :: (Id -> Id) -> StgRhs -> StgRhs
282 mapStgBindeesRhs fn (StgRhsClosure cc bi fvs u args expr)
288 (mapStgBindeesExpr fn expr)
290 mapStgBindeesRhs fn (StgRhsCon cc con atoms)
291 = StgRhsCon cc con (map (mapStgBindeesArg fn) atoms)
294 mapStgBindeesExpr :: (Id -> Id) -> StgExpr -> StgExpr
296 mapStgBindeesExpr fn (StgApp f args lvs)
297 = StgApp (mapStgBindeesArg fn f)
298 (map (mapStgBindeesArg fn) args)
301 mapStgBindeesExpr fn (StgCon con atoms lvs)
302 = StgCon con (map (mapStgBindeesArg fn) atoms) (mapUniqSet fn lvs)
304 mapStgBindeesExpr fn (StgPrim op atoms lvs)
305 = StgPrim op (map (mapStgBindeesArg fn) atoms) (mapUniqSet fn lvs)
307 mapStgBindeesExpr fn (StgLet bind expr)
308 = StgLet (mapStgBindeesBind fn bind) (mapStgBindeesExpr fn expr)
310 mapStgBindeesExpr fn (StgLetNoEscape lvs rhss_lvs bind body)
311 = StgLetNoEscape (mapUniqSet fn lvs) (mapUniqSet fn rhss_lvs)
312 (mapStgBindeesBind fn bind) (mapStgBindeesExpr fn body)
314 mapStgBindeesExpr fn (StgSCC ty label expr)
315 = StgSCC ty label (mapStgBindeesExpr fn expr)
317 mapStgBindeesExpr fn (StgCase expr lvs1 lvs2 uniq alts)
318 = StgCase (mapStgBindeesExpr fn expr)
322 (mapStgBindeesAlts alts)
324 mapStgBindeesAlts (StgAlgAlts ty alts deflt)
325 = StgAlgAlts ty (map mapStgBindeesBoxed_alt alts) (mapStgBindeesDeflt deflt)
327 mapStgBindeesBoxed_alt (c,ps,use_mask,expr) = (c,ps,use_mask,mapStgBindeesExpr fn expr)
329 mapStgBindeesAlts (StgPrimAlts ty alts deflt)
330 = StgPrimAlts ty (map mapStgBindeesunboxed_alt alts) (mapStgBindeesDeflt deflt)
332 mapStgBindeesunboxed_alt (l,expr) = (l,mapStgBindeesExpr fn expr)
334 mapStgBindeesDeflt StgNoDefault = StgNoDefault
335 mapStgBindeesDeflt (StgBindDefault b used expr) = StgBindDefault b used (mapStgBindeesExpr fn expr)
338 mapStgBindeesArg :: (Id -> Id) -> StgArg -> StgArg
339 mapStgBindeesArg fn a@(StgLitArg _) = a
340 mapStgBindeesArg fn a@(StgConArg _) = a
341 mapStgBindeesArg fn a@(StgVarArg id) = StgVarArg (fn id)