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 CostCentre ( CostCentre )
20 import SCCfinal ( stgMassageForProfiling )
21 import StgLint ( lintStgBindings )
22 import StgStats ( showStgStats )
23 import StgVarInfo ( setStgVarInfo )
24 import UpdAnal ( updateAnalyse )
26 import CmdLineOpts ( opt_SccGroup, --Not used:opt_EnsureSplittableC,
27 opt_StgDoLetNoEscapes, opt_D_verbose_stg2stg,
31 import Id ( nullIdEnv, lookupIdEnv, addOneToIdEnv,
32 growIdEnvList, isNullIdEnv, SYN_IE(IdEnv),
34 GenId{-instance Eq/Outputable -}, SYN_IE(Id)
36 import Maybes ( maybeToBool )
37 import PprType ( GenType{-instance Outputable-} )
38 import PprStyle ( PprStyle )
39 import Pretty ( Doc, ($$), vcat, text, ptext )
40 import UniqSupply ( splitUniqSupply, UniqSupply )
41 import Util ( mapAccumL, panic, assertPanic )
42 #if __GLASGOW_HASKELL__ >= 202
43 import Outputable ( Outputable(..) )
48 stg2stg :: [StgToDo] -- spec of what stg-to-stg passes to do
49 -> FAST_STRING -- module name (profiling only)
50 -> PprStyle -- printing style (for debugging only)
51 -> UniqSupply -- a name supply
52 -> [StgBinding] -- input...
54 ([StgBinding], -- output program...
55 ([CostCentre], -- local cost-centres that need to be decl'd
56 [CostCentre])) -- "extern" cost-centres
58 stg2stg stg_todos module_name ppr_style us binds
59 = case (splitUniqSupply us) of { (us4now, us4later) ->
61 (if do_verbose_stg2stg then
62 hPutStr stderr "VERBOSE STG-TO-STG:\n" >>
64 (($$) (ptext SLIT("*** Core2Stg:"))
65 (vcat (map (ppr ppr_style) (setStgVarInfo False binds)))
69 -- Do the main business!
70 foldl_mn do_stg_pass (binds, us4now, ([],[])) stg_todos
71 >>= \ (processed_binds, _, cost_centres) ->
73 -- Do essential wind-up
75 {- Nuked for now SLPJ Dec 96
77 -- Essential wind-up: part (a), saturate RHSs
78 -- This must occur *after* elimIndirections, because elimIndirections
79 -- can change things' arities. Consider:
81 -- x_global = \a -> x_local a
82 -- Then elimIndirections will change the program to
84 -- and lo and behold x_global's arity has changed!
85 case (satStgRhs processed_binds us4later) of { saturated_binds ->
88 -- Essential wind-up: part (b), do setStgVarInfo. It has to
89 -- happen regardless, because the code generator uses its
92 -- Why does it have to happen last? Because earlier passes
93 -- may move things around, which would change the live-var
94 -- info. Also, setStgVarInfo decides about let-no-escape
95 -- things, which in turn do a better job if arities are
96 -- correct, which is done by satStgRhs.
100 Done in Core now. Nuke soon. SLPJ Nov 96
102 No, STG passes may introduce toplevel bindings which
103 have to be globalised here (later than Core anyway) -- SOF 2/97
105 Yes, lambda lifting now does the Right Thing.
108 -- ToDo: provide proper flag control!
110 = if not do_unlocalising
112 else snd (unlocaliseStgBinds unlocal_tag nullIdEnv processed_binds)
116 return (setStgVarInfo do_let_no_escapes processed_binds, cost_centres)
119 do_let_no_escapes = opt_StgDoLetNoEscapes
120 do_verbose_stg2stg = opt_D_verbose_stg2stg
123 (do_unlocalising, unlocal_tag)
124 = case opt_EnsureSplittableC of
125 Just tag -> (True, _PK_ tag)
126 Nothing -> (False, panic "tag")
128 grp_name = case (opt_SccGroup) of
130 Nothing -> module_name -- default: module name
133 stg_linter = if False --LATER: opt_DoStgLinting (ToDo)
134 then lintStgBindings ppr_style
135 else ( \ whodunnit binds -> binds )
137 -------------------------------------------
138 do_stg_pass (binds, us, ccs) to_do
140 (us1, us2) = splitUniqSupply us
143 StgDoStaticArgs -> panic "STG static argument transformation deleted"
145 StgDoUpdateAnalysis ->
146 ASSERT(null (fst ccs) && null (snd ccs))
148 -- NB We have to do setStgVarInfo first! (There's one
149 -- place free-var info is used) But no let-no-escapes,
150 -- because update analysis doesn't care.
151 end_pass us2 "UpdAnal" ccs (updateAnalyse (setStgVarInfo False binds))
154 trace (showStgStats binds)
155 end_pass us2 "StgStats" ccs binds
158 _scc_ "StgLambdaLift"
159 -- NB We have to do setStgVarInfo first!
161 binds3 = liftProgram module_name us1 (setStgVarInfo do_let_no_escapes binds)
163 end_pass us2 "LambdaLift" ccs binds3
165 StgDoMassageForProfiling ->
168 (collected_CCs, binds3)
169 = stgMassageForProfiling module_name grp_name us1 binds
171 end_pass us2 "ProfMassage" collected_CCs binds3
173 end_pass us2 what ccs binds2
174 = -- report verbosely, if required
175 (if do_verbose_stg2stg then
177 (($$) (text ("*** "++what++":"))
178 (vcat (map (ppr ppr_style) binds2))
182 linted_binds = stg_linter what binds2
184 return (linted_binds, us2, ccs)
185 -- return: processed binds
186 -- UniqueSupply for the next guy to use
187 -- cost-centres to be declared/registered (specialised)
188 -- add to description of what's happened (reverse order)
190 -- here so it can be inlined...
191 foldl_mn f z [] = return z
192 foldl_mn f z (x:xs) = f z x >>= \ zz ->
196 %************************************************************************
198 \subsection[SimplStg-unlocalise]{Unlocalisation in STG code}
200 %************************************************************************
202 The idea of all this ``unlocalise'' stuff is that in certain (prelude
203 only) modules we split up the .hc file into lots of separate little
204 files, which are separately compiled by the C compiler. That gives
205 lots of little .o files. The idea is that if you happen to mention
206 one of them you don't necessarily pull them all in. (Pulling in a
207 piece you don't need can be v bad, because it may mention other pieces
208 you don't need either, and so on.)
210 Sadly, splitting up .hc files means that local names (like s234) are
211 now globally visible, which can lead to clashes between two .hc
212 files. So unlocaliseWhatnot goes through making all the local things
213 into global things, essentially by giving them full names so when they
214 are printed they'll have their module name too. Pretty revolting
218 type UnlocalEnv = IdEnv Id
220 lookup_uenv :: UnlocalEnv -> Id -> Id
221 lookup_uenv env id = case lookupIdEnv env id of
223 Just new_id -> new_id
224 unlocaliseStgBinds :: FAST_STRING
227 -> (UnlocalEnv, [StgBinding])
228 unlocaliseStgBinds mod uenv [] = (uenv, [])
229 unlocaliseStgBinds mod uenv (b : bs) =
230 case unlocal_top_bind mod uenv b of { (new_uenv, new_b) ->
231 case unlocaliseStgBinds mod new_uenv bs of { (uenv3, new_bs) ->
232 (uenv3, new_b : new_bs)
236 unlocal_top_bind :: FAST_STRING
239 -> (UnlocalEnv, StgBinding)
240 unlocal_top_bind mod uenv bind@(StgNonRec binder _) =
243 case lookupIdEnv uenv binder of
247 new_env = addOneToIdEnv uenv binder new_global
248 new_global = setIdVisibility mod binder
250 (new_uenv, renameTopStgBind (lookup_uenv new_uenv) bind)
252 unlocal_top_bind mod uenv bind@(StgRec pairs) =
254 new_env binder uenv =
255 case lookupIdEnv uenv binder of
259 env' = addOneToIdEnv uenv binder new_global
260 new_global = setIdVisibility mod binder
262 uenv' = foldr (new_env) uenv (map (fst) pairs)
264 (uenv', renameTopStgBind (lookup_uenv uenv') bind)
268 @renameTopStgBind@ renames top level binders and all occurrences thereof.
271 renameTopStgBind :: (Id -> Id) -> StgBinding -> StgBinding
272 renameTopStgBind fn (StgNonRec b rhs) = StgNonRec (fn b) (mapStgBindeesRhs fn rhs)
273 renameTopStgBind fn (StgRec pairs) = StgRec [ (fn b, mapStgBindeesRhs fn r) | (b, r) <- pairs ]
276 This utility function simply applies the given function to every
277 bindee in the program.
280 mapStgBindeesBind :: (Id -> Id) -> StgBinding -> StgBinding
281 mapStgBindeesBind fn (StgNonRec b rhs) = StgNonRec b (mapStgBindeesRhs fn rhs)
282 mapStgBindeesBind fn (StgRec pairs) = StgRec [ (b, mapStgBindeesRhs fn r) | (b, r) <- pairs ]
285 mapStgBindeesRhs :: (Id -> Id) -> StgRhs -> StgRhs
286 mapStgBindeesRhs fn (StgRhsClosure cc bi fvs u args expr)
292 (mapStgBindeesExpr fn expr)
294 mapStgBindeesRhs fn (StgRhsCon cc con atoms)
295 = StgRhsCon cc con (map (mapStgBindeesArg fn) atoms)
298 mapStgBindeesExpr :: (Id -> Id) -> StgExpr -> StgExpr
300 mapStgBindeesExpr fn (StgApp f args lvs)
301 = StgApp (mapStgBindeesArg fn f)
302 (map (mapStgBindeesArg fn) args)
305 mapStgBindeesExpr fn (StgCon con atoms lvs)
306 = StgCon con (map (mapStgBindeesArg fn) atoms) (mapUniqSet fn lvs)
308 mapStgBindeesExpr fn (StgPrim op atoms lvs)
309 = StgPrim op (map (mapStgBindeesArg fn) atoms) (mapUniqSet fn lvs)
311 mapStgBindeesExpr fn (StgLet bind expr)
312 = StgLet (mapStgBindeesBind fn bind) (mapStgBindeesExpr fn expr)
314 mapStgBindeesExpr fn (StgLetNoEscape lvs rhss_lvs bind body)
315 = StgLetNoEscape (mapUniqSet fn lvs) (mapUniqSet fn rhss_lvs)
316 (mapStgBindeesBind fn bind) (mapStgBindeesExpr fn body)
318 mapStgBindeesExpr fn (StgSCC ty label expr)
319 = StgSCC ty label (mapStgBindeesExpr fn expr)
321 mapStgBindeesExpr fn (StgCase expr lvs1 lvs2 uniq alts)
322 = StgCase (mapStgBindeesExpr fn expr)
326 (mapStgBindeesAlts alts)
328 mapStgBindeesAlts (StgAlgAlts ty alts deflt)
329 = StgAlgAlts ty (map mapStgBindeesBoxed_alt alts) (mapStgBindeesDeflt deflt)
331 mapStgBindeesBoxed_alt (c,ps,use_mask,expr) = (c,ps,use_mask,mapStgBindeesExpr fn expr)
333 mapStgBindeesAlts (StgPrimAlts ty alts deflt)
334 = StgPrimAlts ty (map mapStgBindeesunboxed_alt alts) (mapStgBindeesDeflt deflt)
336 mapStgBindeesunboxed_alt (l,expr) = (l,mapStgBindeesExpr fn expr)
338 mapStgBindeesDeflt StgNoDefault = StgNoDefault
339 mapStgBindeesDeflt (StgBindDefault b used expr) = StgBindDefault b used (mapStgBindeesExpr fn expr)
342 mapStgBindeesArg :: (Id -> Id) -> StgArg -> StgArg
343 mapStgBindeesArg fn a@(StgLitArg _) = a
344 mapStgBindeesArg fn a@(StgConArg _) = a
345 mapStgBindeesArg fn a@(StgVarArg id) = StgVarArg (fn id)