2 % (c) The GRASP/AQUA Project, Glasgow University, 1993-1996
4 \section[StrictAnal]{``Simple'' Mycroft-style strictness analyser}
6 The original version(s) of all strictness-analyser code (except the
7 Semantique analyser) was written by Andy Gill.
10 #include "HsVersions.h"
12 module StrictAnal ( saWwTopBinds, saTopBinds ) where
16 import CmdLineOpts ( opt_AllStrict, opt_NumbersStrict,
17 opt_D_dump_stranal, opt_D_simplifier_stats
20 import Id ( idType, addIdStrictness, isWrapperId,
21 getIdDemandInfo, addIdDemandInfo,
22 GenId{-instance Outputable-}, SYN_IE(Id)
24 import IdInfo ( mkStrictnessInfo, mkBottomStrictnessInfo,
25 mkDemandInfo, willBeDemanded, DemandInfo
27 import PprCore ( pprCoreBinding, pprBigCoreBinder )
28 import PprStyle ( PprStyle(..) )
29 import PprType ( GenType{-instance Outputable-}, GenTyVar{-ditto-} )
30 import Pretty ( Doc, hcat, ptext, int, char, vcat )
33 import TyVar ( GenTyVar{-instance Eq-} )
34 import WorkWrap -- "back-end" of strictness analyser
35 import Unique ( Unique{-instance Eq -} )
36 import UniqSupply ( UniqSupply )
37 import Util ( zipWith4Equal, pprTrace, panic )
40 %************************************************************************
42 \subsection[Thoughts]{Random thoughts}
44 %************************************************************************
46 A note about worker-wrappering. If we have
49 f = let v = <expensive>
52 and we deduce that f is strict, it is nevertheless NOT safe to worker-wapper to
54 f = \x -> case x of Int x# -> fw x#
55 fw = \x# -> let x = Int x#
60 because this obviously loses laziness, since now <expensive>
61 is done each time. Alas.
63 WATCH OUT! This can mean that something is unboxed only to be
64 boxed again. For example
68 Here g is strict, and *will* split into worker-wrapper. A call to
69 g, with the wrapper inlined will then be
71 case arg of Int a# -> gw a#
73 Now g calls f, which has no wrapper, so it has to box it.
75 gw = \a# -> f (Int a#)
80 %************************************************************************
82 \subsection[iface-StrictAnal]{Interface to the outside world}
84 %************************************************************************
87 saWwTopBinds :: UniqSupply
93 strflags = (opt_AllStrict, opt_NumbersStrict)
95 -- mark each binder with its strictness
96 #ifndef OMIT_STRANAL_STATS
97 (binds_w_strictness, sa_stats)
98 = sa_top_binds strflags binds nullSaStats
101 = sa_top_binds strflags binds
104 -- possibly show what we decided about strictness...
105 (if opt_D_dump_stranal
106 then pprTrace "Strictness:\n" (vcat (
107 map (pprCoreBinding PprDebug) binds_w_strictness))
110 -- possibly show how many things we marked as demanded...
111 ((if opt_D_simplifier_stats
112 #ifndef OMIT_STRANAL_STATS
113 then pp_stats sa_stats
119 -- create worker/wrappers, and mark binders with their
120 -- "strictness info" [which encodes their
121 -- worker/wrapper-ness]
122 (workersAndWrappers binds_w_strictness us))
123 #ifndef OMIT_STRANAL_STATS
125 pp_stats (SaStats tlam dlam tc dc tlet dlet)
126 = pprTrace "Binders marked demanded: "
127 (hcat [ptext SLIT("Lambda vars: "), int IBOX(dlam), char '/', int IBOX(tlam),
128 ptext SLIT("; Case vars: "), int IBOX(dc), char '/', int IBOX(tc),
129 ptext SLIT("; Let vars: "), int IBOX(dlet), char '/', int IBOX(tlet)
134 %************************************************************************
136 \subsection[saBinds]{Strictness analysis of bindings}
138 %************************************************************************
140 [Some of the documentation about types, etc., in \tr{SaLib} may be
141 helpful for understanding this module.]
143 @saTopBinds@ tags each binder in the program with its @Demand@.
144 That tells how each binder is {\em used}; if @Strict@, then the binder
145 is sure to be evaluated to HNF; if @NonStrict@ it may or may not be;
146 if @Absent@, then it certainly is not used. [DATED; ToDo: update]
148 (The above info is actually recorded for posterity in each binder's
149 IdInfo, notably its @DemandInfo@.)
151 We proceed by analysing the bindings top-to-bottom, building up an
152 environment which maps @Id@s to their abstract values (i.e., an
153 @AbsValEnv@ maps an @Id@ to its @AbsVal@).
156 saTopBinds :: StrAnalFlags -> [CoreBinding] -> [CoreBinding] -- exported
157 sa_top_binds :: StrAnalFlags -> [CoreBinding] -> SaM [CoreBinding] -- not exported
159 saTopBinds strflags binds
160 #ifndef OMIT_STRANAL_STATS
161 = fst (sa_top_binds strflags binds nullSaStats)
163 = sa_top_binds strflags binds
166 sa_top_binds strflags binds
168 starting_abs_env = nullAbsValEnv strflags
170 do_it starting_abs_env starting_abs_env binds
172 do_it _ _ [] = returnSa []
173 do_it senv aenv (b:bs)
174 = saTopBind senv aenv b `thenSa` \ (senv2, aenv2, new_b) ->
175 do_it senv2 aenv2 bs `thenSa` \ new_bs ->
176 returnSa (new_b : new_bs)
179 @saTopBind@ is only used for the top level. We don't add any demand
180 info to these ids because we can't work it out. In any case, it
181 doesn't do us any good to know whether top-level binders are sure to
182 be used; we can't turn top-level @let@s into @case@s.
185 saTopBind :: StrictEnv -> AbsenceEnv
187 -> SaM (StrictEnv, AbsenceEnv, CoreBinding)
189 saTopBind str_env abs_env (NonRec binder rhs)
190 = saExpr str_env abs_env rhs `thenSa` \ new_rhs ->
192 strflags = getStrAnalFlags str_env
194 str_rhs = absEval StrAnal rhs str_env
195 abs_rhs = absEval AbsAnal rhs abs_env
197 widened_str_rhs = widen StrAnal str_rhs
198 widened_abs_rhs = widen AbsAnal abs_rhs
199 -- The widening above is done for efficiency reasons.
200 -- See notes on Let case in SaAbsInt.lhs
203 = addStrictnessInfoToId
205 widened_str_rhs widened_abs_rhs
209 -- Augment environments with a mapping of the
210 -- binder to its abstract values, computed by absEval
211 new_str_env = addOneToAbsValEnv str_env binder widened_str_rhs
212 new_abs_env = addOneToAbsValEnv abs_env binder widened_abs_rhs
214 returnSa (new_str_env, new_abs_env, NonRec new_binder new_rhs)
216 saTopBind str_env abs_env (Rec pairs)
218 strflags = getStrAnalFlags str_env
219 (binders,rhss) = unzip pairs
220 str_rhss = fixpoint StrAnal binders rhss str_env
221 abs_rhss = fixpoint AbsAnal binders rhss abs_env
222 -- fixpoint returns widened values
223 new_str_env = growAbsValEnvList str_env (binders `zip` str_rhss)
224 new_abs_env = growAbsValEnvList abs_env (binders `zip` abs_rhss)
225 new_binders = zipWith4Equal "saTopBind" (addStrictnessInfoToId strflags)
226 str_rhss abs_rhss binders rhss
228 mapSa (saExpr new_str_env new_abs_env) rhss `thenSa` \ new_rhss ->
230 new_pairs = new_binders `zip` new_rhss
232 returnSa (new_str_env, new_abs_env, Rec new_pairs)
235 %************************************************************************
237 \subsection[saExpr]{Strictness analysis of an expression}
239 %************************************************************************
241 @saExpr@ computes the strictness of an expression within a given
245 saExpr :: StrictEnv -> AbsenceEnv -> CoreExpr -> SaM CoreExpr
247 saExpr _ _ e@(Var _) = returnSa e
248 saExpr _ _ e@(Lit _) = returnSa e
249 saExpr _ _ e@(Con _ _) = returnSa e
250 saExpr _ _ e@(Prim _ _) = returnSa e
252 saExpr str_env abs_env (Lam (ValBinder arg) body)
253 = saExpr str_env abs_env body `thenSa` \ new_body ->
255 new_arg = addDemandInfoToId str_env abs_env body arg
257 tickLambda new_arg `thenSa_` -- stats
258 returnSa (Lam (ValBinder new_arg) new_body)
260 saExpr str_env abs_env (Lam other_binder expr)
261 = saExpr str_env abs_env expr `thenSa` \ new_expr ->
262 returnSa (Lam other_binder new_expr)
264 saExpr str_env abs_env (App fun arg)
265 = saExpr str_env abs_env fun `thenSa` \ new_fun ->
266 returnSa (App new_fun arg)
268 saExpr str_env abs_env (SCC cc expr)
269 = saExpr str_env abs_env expr `thenSa` \ new_expr ->
270 returnSa (SCC cc new_expr)
272 saExpr str_env abs_env (Coerce c ty expr)
273 = saExpr str_env abs_env expr `thenSa` \ new_expr ->
274 returnSa (Coerce c ty new_expr)
276 saExpr str_env abs_env (Case expr (AlgAlts alts deflt))
277 = saExpr str_env abs_env expr `thenSa` \ new_expr ->
278 saDefault str_env abs_env deflt `thenSa` \ new_deflt ->
279 mapSa sa_alt alts `thenSa` \ new_alts ->
280 returnSa (Case new_expr (AlgAlts new_alts new_deflt))
282 sa_alt (con, binders, rhs)
283 = saExpr str_env abs_env rhs `thenSa` \ new_rhs ->
285 new_binders = addDemandInfoToIds str_env abs_env rhs binders
287 tickCases new_binders `thenSa_` -- stats
288 returnSa (con, new_binders, new_rhs)
290 saExpr str_env abs_env (Case expr (PrimAlts alts deflt))
291 = saExpr str_env abs_env expr `thenSa` \ new_expr ->
292 saDefault str_env abs_env deflt `thenSa` \ new_deflt ->
293 mapSa sa_alt alts `thenSa` \ new_alts ->
294 returnSa (Case new_expr (PrimAlts new_alts new_deflt))
297 = saExpr str_env abs_env rhs `thenSa` \ new_rhs ->
298 returnSa (lit, new_rhs)
300 saExpr str_env abs_env (Let (NonRec binder rhs) body)
301 = -- Analyse the RHS in the environment at hand
302 saExpr str_env abs_env rhs `thenSa` \ new_rhs ->
304 strflags = getStrAnalFlags str_env
306 -- Bind this binder to the abstract value of the RHS; analyse
307 -- the body of the `let' in the extended environment.
308 str_rhs_val = absEval StrAnal rhs str_env
309 abs_rhs_val = absEval AbsAnal rhs abs_env
311 widened_str_rhs = widen StrAnal str_rhs_val
312 widened_abs_rhs = widen AbsAnal abs_rhs_val
313 -- The widening above is done for efficiency reasons.
314 -- See notes on Let case in SaAbsInt.lhs
316 new_str_env = addOneToAbsValEnv str_env binder widened_str_rhs
317 new_abs_env = addOneToAbsValEnv abs_env binder widened_abs_rhs
319 -- Now determine the strictness of this binder; use that info
320 -- to record DemandInfo/StrictnessInfo in the binder.
321 new_binder = addStrictnessInfoToId strflags
322 widened_str_rhs widened_abs_rhs
323 (addDemandInfoToId str_env abs_env body binder)
326 tickLet new_binder `thenSa_` -- stats
327 saExpr new_str_env new_abs_env body `thenSa` \ new_body ->
328 returnSa (Let (NonRec new_binder new_rhs) new_body)
330 saExpr str_env abs_env (Let (Rec pairs) body)
332 strflags = getStrAnalFlags str_env
333 (binders,rhss) = unzip pairs
334 str_vals = fixpoint StrAnal binders rhss str_env
335 abs_vals = fixpoint AbsAnal binders rhss abs_env
336 -- fixpoint returns widened values
337 new_str_env = growAbsValEnvList str_env (binders `zip` str_vals)
338 new_abs_env = growAbsValEnvList abs_env (binders `zip` abs_vals)
340 saExpr new_str_env new_abs_env body `thenSa` \ new_body ->
341 mapSa (saExpr new_str_env new_abs_env) rhss `thenSa` \ new_rhss ->
343 -- new_binders = addDemandInfoToIds new_str_env new_abs_env body binders
344 -- DON'T add demand info in a Rec!
345 -- a) it's useless: we can't do let-to-case
346 -- b) it's incorrect. Consider
347 -- letrec x = ...y...
350 -- When we ask whether y is demanded we'll bind y to bottom and
351 -- evaluate the body of the letrec. But that will result in our
352 -- deciding that y is absent, which is plain wrong!
353 -- It's much easier simply not to do this.
355 improved_binders = zipWith4Equal "saExpr" (addStrictnessInfoToId strflags)
356 str_vals abs_vals binders rhss
358 whiter_than_white_binders = launder improved_binders
360 new_pairs = whiter_than_white_binders `zip` new_rhss
362 returnSa (Let (Rec new_pairs) new_body)
364 launder me = {-still-} me
368 saDefault str_env abs_env NoDefault = returnSa NoDefault
370 saDefault str_env abs_env (BindDefault bdr rhs)
371 = saExpr str_env abs_env rhs `thenSa` \ new_rhs ->
373 new_bdr = addDemandInfoToId str_env abs_env rhs bdr
375 tickCases [new_bdr] `thenSa_` -- stats
376 returnSa (BindDefault new_bdr new_rhs)
380 %************************************************************************
382 \subsection[computeInfos]{Add computed info to binders}
384 %************************************************************************
386 Important note (Sept 93). @addStrictnessInfoToId@ is used only for
387 let(rec) bound variables, and is use to attach the strictness (not
388 demand) info to the binder. We are careful to restrict this
389 strictness info to the lambda-bound arguments which are actually
390 visible, at the top level, lest we accidentally lose laziness by
391 eagerly looking for an "extra" argument. So we "dig for lambdas" in a
392 rather syntactic way.
394 A better idea might be to have some kind of arity analysis to
395 tell how many args could safely be grabbed.
398 addStrictnessInfoToId
400 -> AbsVal -- Abstract strictness value
401 -> AbsVal -- Ditto absence
403 -> CoreExpr -- Its RHS
404 -> Id -- Augmented with strictness
406 addStrictnessInfoToId strflags str_val abs_val binder body
409 = binder `addIdStrictness` mkBottomStrictnessInfo
412 = case (collectBinders body) of
413 (_, _, [], rhs) -> binder
414 (_, _, lambda_bounds, rhs) -> binder `addIdStrictness`
415 mkStrictnessInfo strictness Nothing
417 tys = map idType lambda_bounds
418 strictness = findStrictness strflags tys str_val abs_val
422 addDemandInfoToId :: StrictEnv -> AbsenceEnv
423 -> CoreExpr -- The scope of the id
425 -> Id -- Id augmented with Demand info
427 addDemandInfoToId str_env abs_env expr binder
428 = binder `addIdDemandInfo` (mkDemandInfo (findDemand str_env abs_env expr binder))
430 addDemandInfoToIds :: StrictEnv -> AbsenceEnv -> CoreExpr -> [Id] -> [Id]
432 addDemandInfoToIds str_env abs_env expr binders
433 = map (addDemandInfoToId str_env abs_env expr) binders
436 %************************************************************************
438 \subsection{Monad used herein for stats}
440 %************************************************************************
444 = SaStats FAST_INT FAST_INT -- total/marked-demanded lambda-bound
445 FAST_INT FAST_INT -- total/marked-demanded case-bound
446 FAST_INT FAST_INT -- total/marked-demanded let-bound
447 -- (excl. top-level; excl. letrecs)
449 nullSaStats = SaStats ILIT(0) ILIT(0) ILIT(0) ILIT(0) ILIT(0) ILIT(0)
451 thenSa :: SaM a -> (a -> SaM b) -> SaM b
452 thenSa_ :: SaM a -> SaM b -> SaM b
453 returnSa :: a -> SaM a
455 {-# INLINE thenSa #-}
456 {-# INLINE thenSa_ #-}
457 {-# INLINE returnSa #-}
459 tickLambda :: Id -> SaM ()
460 tickCases :: [Id] -> SaM ()
461 tickLet :: Id -> SaM ()
463 #ifndef OMIT_STRANAL_STATS
464 type SaM a = SaStats -> (a, SaStats)
466 thenSa expr cont stats
467 = case (expr stats) of { (result, stats1) ->
470 thenSa_ expr cont stats
471 = case (expr stats) of { (_, stats1) ->
474 returnSa x stats = (x, stats)
476 tickLambda var (SaStats tlam dlam tc dc tlet dlet)
477 = case (tick_demanded var (0,0)) of { (IBOX(tot), IBOX(demanded)) ->
478 ((), SaStats (tlam _ADD_ tot) (dlam _ADD_ demanded) tc dc tlet dlet) }
480 tickCases vars (SaStats tlam dlam tc dc tlet dlet)
481 = case (foldr tick_demanded (0,0) vars) of { (IBOX(tot), IBOX(demanded)) ->
482 ((), SaStats tlam dlam (tc _ADD_ tot) (dc _ADD_ demanded) tlet dlet) }
484 tickLet var (SaStats tlam dlam tc dc tlet dlet)
485 = case (tick_demanded var (0,0)) of { (IBOX(tot),IBOX(demanded)) ->
486 ((), SaStats tlam dlam tc dc (tlet _ADD_ tot) (dlet _ADD_ demanded)) }
488 tick_demanded var (tot, demanded)
490 if (willBeDemanded (getIdDemandInfo var))
494 #else {-OMIT_STRANAL_STATS-}
498 thenSa expr cont = cont expr
500 thenSa_ expr cont = cont
504 tickLambda var = panic "OMIT_STRANAL_STATS: tickLambda"
505 tickCases vars = panic "OMIT_STRANAL_STATS: tickCases"
506 tickLet var = panic "OMIT_STRANAL_STATS: tickLet"
508 #endif {-OMIT_STRANAL_STATS-}
510 mapSa :: (a -> SaM b) -> [a] -> SaM [b]
512 mapSa f [] = returnSa []
514 = f x `thenSa` \ r ->
515 mapSa f xs `thenSa` \ rs ->