2 % (c) The AQUA Project, Glasgow University, 1994-1998
4 \section[CoreUnfold]{Core-syntax unfoldings}
6 Unfoldings (which can travel across module boundaries) are in Core
7 syntax (namely @CoreExpr@s).
9 The type @Unfolding@ sits ``above'' simply-Core-expressions
10 unfoldings, capturing ``higher-level'' things we know about a binding,
11 usually things that the simplifier found out (e.g., ``it's a
12 literal''). In the corner of a @CoreUnfolding@ unfolding, you will
13 find, unsurprisingly, a Core expression.
17 Unfolding, UnfoldingGuidance, -- types
19 noUnfolding, mkUnfolding, seqUnfolding,
20 mkOtherCon, otherCons,
21 unfoldingTemplate, maybeUnfoldingTemplate,
22 isEvaldUnfolding, isCheapUnfolding,
23 hasUnfolding, hasSomeUnfolding,
25 couldBeSmallEnoughToInline,
26 certainlySmallEnoughToInline,
29 calcUnfoldingGuidance,
31 callSiteInline, blackListed
34 #include "HsVersions.h"
36 import CmdLineOpts ( opt_UF_CreationThreshold,
38 opt_UF_ScrutConDiscount,
39 opt_UF_FunAppDiscount,
40 opt_UF_PrimArgDiscount,
42 opt_UF_CheapOp, opt_UF_DearOp, opt_UF_NoRepLit,
43 opt_UnfoldCasms, opt_PprStyle_Debug,
47 import PprCore ( pprCoreExpr )
48 import OccurAnal ( occurAnalyseGlobalExpr )
50 import CoreUtils ( coreExprType, exprIsTrivial, exprIsValue, exprIsCheap )
51 import Id ( Id, idType, idUnique, isId, getIdWorkerInfo,
52 getIdSpecialisation, getInlinePragma, getIdUnfolding
55 import Name ( isLocallyDefined )
56 import Const ( Con(..), isLitLitLit, isWHNFCon )
57 import PrimOp ( PrimOp(..), primOpIsDupable )
58 import IdInfo ( ArityInfo(..), InlinePragInfo(..), OccInfo(..), workerExists )
59 import TyCon ( tyConFamilySize )
60 import Type ( splitAlgTyConApp_maybe, splitFunTy_maybe, isUnLiftedType )
61 import Const ( isNoRepLit )
62 import Unique ( Unique, buildIdKey, augmentIdKey, runSTRepIdKey )
63 import Maybes ( maybeToBool )
65 import Util ( isIn, lengthExceeds )
68 #if __GLASGOW_HASKELL__ >= 404
69 import GlaExts ( fromInt )
73 %************************************************************************
75 \subsection{@Unfolding@ and @UnfoldingGuidance@ types}
77 %************************************************************************
83 | OtherCon [Con] -- It ain't one of these
84 -- (OtherCon xs) also indicates that something has been evaluated
85 -- and hence there's no point in re-evaluating it.
86 -- OtherCon [] is used even for non-data-type values
87 -- to indicated evaluated-ness. Notably:
88 -- data C = C !(Int -> Int)
89 -- case x of { C f -> ... }
90 -- Here, f gets an OtherCon [] unfolding.
92 | CoreUnfolding -- An unfolding with redundant cached information
93 CoreExpr -- Template; binder-info is correct
94 Bool -- exprIsCheap template (cached); it won't duplicate (much) work
95 -- if you inline this in more than one place
96 Bool -- exprIsValue template (cached); it is ok to discard a `seq` on
98 UnfoldingGuidance -- Tells about the *size* of the template.
100 seqUnfolding :: Unfolding -> ()
101 seqUnfolding (CoreUnfolding e b1 b2 g)
102 = seqExpr e `seq` b1 `seq` b2 `seq` seqGuidance g
103 seqUnfolding other = ()
107 noUnfolding = NoUnfolding
108 mkOtherCon = OtherCon
111 = CoreUnfolding (occurAnalyseGlobalExpr expr)
114 (calcUnfoldingGuidance opt_UF_CreationThreshold expr)
116 unfoldingTemplate :: Unfolding -> CoreExpr
117 unfoldingTemplate (CoreUnfolding expr _ _ _) = expr
118 unfoldingTemplate other = panic "getUnfoldingTemplate"
120 maybeUnfoldingTemplate :: Unfolding -> Maybe CoreExpr
121 maybeUnfoldingTemplate (CoreUnfolding expr _ _ _) = Just expr
122 maybeUnfoldingTemplate other = Nothing
124 otherCons (OtherCon cons) = cons
127 isEvaldUnfolding :: Unfolding -> Bool
128 isEvaldUnfolding (OtherCon _) = True
129 isEvaldUnfolding (CoreUnfolding _ _ is_evald _) = is_evald
130 isEvaldUnfolding other = False
132 isCheapUnfolding :: Unfolding -> Bool
133 isCheapUnfolding (CoreUnfolding _ is_cheap _ _) = is_cheap
134 isCheapUnfolding other = False
136 hasUnfolding :: Unfolding -> Bool
137 hasUnfolding (CoreUnfolding _ _ _ _) = True
138 hasUnfolding other = False
140 hasSomeUnfolding :: Unfolding -> Bool
141 hasSomeUnfolding NoUnfolding = False
142 hasSomeUnfolding other = True
144 data UnfoldingGuidance
146 | UnfoldAlways -- There is no "original" definition,
147 -- so you'd better unfold. Or: something
148 -- so cheap to unfold (e.g., 1#) that
149 -- you should do it absolutely always.
151 | UnfoldIfGoodArgs Int -- and "n" value args
153 [Int] -- Discount if the argument is evaluated.
154 -- (i.e., a simplification will definitely
155 -- be possible). One elt of the list per *value* arg.
157 Int -- The "size" of the unfolding; to be elaborated
160 Int -- Scrutinee discount: the discount to substract if the thing is in
161 -- a context (case (thing args) of ...),
162 -- (where there are the right number of arguments.)
164 seqGuidance (UnfoldIfGoodArgs n ns a b) = n `seq` sum ns `seq` a `seq` b `seq` ()
165 seqGuidance other = ()
169 instance Outputable UnfoldingGuidance where
170 ppr UnfoldAlways = ptext SLIT("ALWAYS")
171 ppr UnfoldNever = ptext SLIT("NEVER")
172 ppr (UnfoldIfGoodArgs v cs size discount)
173 = hsep [ ptext SLIT("IF_ARGS"), int v,
174 brackets (hsep (map int cs)),
180 %************************************************************************
182 \subsection[calcUnfoldingGuidance]{Calculate ``unfolding guidance'' for an expression}
184 %************************************************************************
187 calcUnfoldingGuidance
188 :: Int -- bomb out if size gets bigger than this
189 -> CoreExpr -- expression to look at
191 calcUnfoldingGuidance bOMB_OUT_SIZE expr
192 | exprIsTrivial expr -- Often trivial expressions are never bound
193 -- to an expression, but it can happen. For
194 -- example, the Id for a nullary constructor has
195 -- a trivial expression as its unfolding, and
196 -- we want to make sure that we always unfold it.
200 = case collect_val_bndrs expr of { (inline, val_binders, body) ->
201 case (sizeExpr bOMB_OUT_SIZE val_binders body) of
203 TooBig -> UnfoldNever
205 SizeIs size cased_args scrut_discount
208 (map discount_for val_binders)
214 n_val_binders = length val_binders
216 final_size | inline = boxed_size `min` (n_val_binders + 2)
217 | otherwise = boxed_size
218 -- The idea is that if there is an INLINE pragma (inline is True)
219 -- and there's a big body, we give a size of n_val_binders+2. This
220 -- This is enough to defeat the no-size-increase test in callSiteInline;
221 -- we don't want to inline an INLINE thing into a totally boring context
223 -- Sometimes, though, an INLINE thing is smaller than n_val_binders+2.
224 -- A particular case in point is a constructor, which has size 1.
225 -- We want to inline this regardless, hence the `min`
229 | is_fun_ty = num_cases * opt_UF_FunAppDiscount
230 | is_data_ty = num_cases * opt_UF_ScrutConDiscount
231 | otherwise = num_cases * opt_UF_PrimArgDiscount
233 num_cases = foldlBag (\n b' -> if b==b' then n+1 else n) 0 cased_args
234 -- Count occurrences of b in cased_args
236 is_fun_ty = maybeToBool (splitFunTy_maybe arg_ty)
237 (is_data_ty, tycon) = case (splitAlgTyConApp_maybe (idType b)) of
238 Nothing -> (False, panic "discount")
239 Just (tc,_,_) -> (True, tc)
243 collect_val_bndrs e = go False [] e
244 -- We need to be a bit careful about how we collect the
245 -- value binders. In ptic, if we see
246 -- __inline_me (\x y -> e)
247 -- We want to say "2 value binders". Why? So that
248 -- we take account of information given for the arguments
250 go inline rev_vbs (Note InlineMe e) = go True rev_vbs e
251 go inline rev_vbs (Lam b e) | isId b = go inline (b:rev_vbs) e
252 | otherwise = go inline rev_vbs e
253 go inline rev_vbs e = (inline, reverse rev_vbs, e)
257 sizeExpr :: Int -- Bomb out if it gets bigger than this
258 -> [Id] -- Arguments; we're interested in which of these
263 sizeExpr (I# bOMB_OUT_SIZE) args expr
266 size_up (Type t) = sizeZero -- Types cost nothing
267 size_up (Var v) = sizeOne
269 size_up (Note _ body) = size_up body -- Notes cost nothing
271 size_up (App fun (Type t)) = size_up fun
272 size_up (App fun arg) = size_up_app fun [arg]
274 size_up (Con con args) = foldr (addSize . size_up)
275 (size_up_con con args)
278 size_up (Lam b e) | isId b = size_up e `addSizeN` 1
279 | otherwise = size_up e
281 size_up (Let (NonRec binder rhs) body)
282 = nukeScrutDiscount (size_up rhs) `addSize`
283 size_up body `addSizeN`
284 (if isUnLiftedType (idType binder) then 0 else 1)
285 -- For the allocation
286 -- If the binder has an unlifted type there is no allocation
288 size_up (Let (Rec pairs) body)
289 = nukeScrutDiscount rhs_size `addSize`
290 size_up body `addSizeN`
291 length pairs -- For the allocation
293 rhs_size = foldr (addSize . size_up . snd) sizeZero pairs
295 size_up (Case scrut _ alts)
296 = nukeScrutDiscount (size_up scrut) `addSize`
297 arg_discount scrut `addSize`
298 foldr (addSize . size_up_alt) sizeZero alts
299 `addSizeN` 1 -- charge one for the case itself.
301 -- Just charge for the alts that exist, not the ones that might exist
303 -- case (splitAlgTyConApp_maybe (coreExprType scrut)) of
305 -- Just (tc,_,_) -> tyConFamilySize tc
308 size_up_app (App fun arg) args = size_up_app fun (arg:args)
309 size_up_app fun args = foldr (addSize . nukeScrutDiscount . size_up) (fun_discount fun) args
311 -- A function application with at least one value argument
312 -- so if the function is an argument give it an arg-discount
313 -- Also behave specially if the function is a build
314 fun_discount (Var fun) | idUnique fun == buildIdKey = buildSize
315 | idUnique fun == augmentIdKey = augmentSize
316 | fun `is_elem` args = scrutArg fun
317 fun_discount other = sizeZero
320 size_up_alt (con, bndrs, rhs) = size_up rhs
321 -- Don't charge for args, so that wrappers look cheap
324 size_up_con (Literal lit) args | isNoRepLit lit = sizeN opt_UF_NoRepLit
325 | otherwise = sizeOne
327 size_up_con (DataCon dc) args = conSizeN (valArgCount args)
329 size_up_con (PrimOp op) args = foldr addSize (sizeN op_cost) (map arg_discount args)
330 -- Give an arg-discount if a primop is applies to
331 -- one of the function's arguments
333 op_cost | primOpIsDupable op = opt_UF_CheapOp
334 | otherwise = opt_UF_DearOp
336 -- We want to record if we're case'ing, or applying, an argument
337 arg_discount (Var v) | v `is_elem` args = scrutArg v
338 arg_discount other = sizeZero
341 is_elem :: Id -> [Id] -> Bool
342 is_elem = isIn "size_up_scrut"
345 -- These addSize things have to be here because
346 -- I don't want to give them bOMB_OUT_SIZE as an argument
348 addSizeN TooBig _ = TooBig
349 addSizeN (SizeIs n xs d) (I# m)
350 | n_tot -# d <# bOMB_OUT_SIZE = SizeIs n_tot xs d
355 addSize TooBig _ = TooBig
356 addSize _ TooBig = TooBig
357 addSize (SizeIs n1 xs d1) (SizeIs n2 ys d2)
358 | (n_tot -# d_tot) <# bOMB_OUT_SIZE = SizeIs n_tot xys d_tot
363 xys = xs `unionBags` ys
366 Code for manipulating sizes
370 data ExprSize = TooBig
371 | SizeIs Int# -- Size found
372 (Bag Id) -- Arguments cased herein
373 Int# -- Size to subtract if result is scrutinised
374 -- by a case expression
376 sizeZero = SizeIs 0# emptyBag 0#
377 sizeOne = SizeIs 1# emptyBag 0#
378 sizeTwo = SizeIs 2# emptyBag 0#
379 sizeN (I# n) = SizeIs n emptyBag 0#
380 conSizeN (I# n) = SizeIs 1# emptyBag (n +# 1#)
381 -- Treat constructors as size 1, that unfoldAlways responsds 'False'
382 -- when asked about 'x' when x is bound to (C 3#).
383 -- This avoids gratuitous 'ticks' when x itself appears as an
384 -- atomic constructor argument.
386 buildSize = SizeIs (-2#) emptyBag 4#
387 -- We really want to inline applications of build
388 -- build t (\cn -> e) should cost only the cost of e (because build will be inlined later)
389 -- Indeed, we should add a result_discount becuause build is
390 -- very like a constructor. We don't bother to check that the
391 -- build is saturated (it usually is). The "-2" discounts for the \c n,
392 -- The "4" is rather arbitrary.
394 augmentSize = SizeIs (-2#) emptyBag 4#
395 -- Ditto (augment t (\cn -> e) ys) should cost only the cost of
396 -- e plus ys. The -2 accounts for the \cn
398 scrutArg v = SizeIs 0# (unitBag v) 0#
400 nukeScrutDiscount (SizeIs n vs d) = SizeIs n vs 0#
401 nukeScrutDiscount TooBig = TooBig
405 %************************************************************************
407 \subsection[considerUnfolding]{Given all the info, do (not) do the unfolding}
409 %************************************************************************
411 We have very limited information about an unfolding expression: (1)~so
412 many type arguments and so many value arguments expected---for our
413 purposes here, we assume we've got those. (2)~A ``size'' or ``cost,''
414 a single integer. (3)~An ``argument info'' vector. For this, what we
415 have at the moment is a Boolean per argument position that says, ``I
416 will look with great favour on an explicit constructor in this
417 position.'' (4)~The ``discount'' to subtract if the expression
418 is being scrutinised.
420 Assuming we have enough type- and value arguments (if not, we give up
421 immediately), then we see if the ``discounted size'' is below some
422 (semi-arbitrary) threshold. It works like this: for every argument
423 position where we're looking for a constructor AND WE HAVE ONE in our
424 hands, we get a (again, semi-arbitrary) discount [proportion to the
425 number of constructors in the type being scrutinized].
427 If we're in the context of a scrutinee ( \tr{(case <expr > of A .. -> ...;.. )})
428 and the expression in question will evaluate to a constructor, we use
429 the computed discount size *for the result only* rather than
430 computing the argument discounts. Since we know the result of
431 the expression is going to be taken apart, discounting its size
432 is more accurate (see @sizeExpr@ above for how this discount size
435 We use this one to avoid exporting inlinings that we ``couldn't possibly
436 use'' on the other side. Can be overridden w/ flaggery.
437 Just the same as smallEnoughToInline, except that it has no actual arguments.
440 couldBeSmallEnoughToInline :: UnfoldingGuidance -> Bool
441 couldBeSmallEnoughToInline UnfoldNever = False
442 couldBeSmallEnoughToInline other = True
444 certainlySmallEnoughToInline :: UnfoldingGuidance -> Bool
445 certainlySmallEnoughToInline UnfoldNever = False
446 certainlySmallEnoughToInline UnfoldAlways = True
447 certainlySmallEnoughToInline (UnfoldIfGoodArgs _ _ size _) = size <= opt_UF_UseThreshold
450 @okToUnfoldInHifile@ is used when emitting unfolding info into an interface
451 file to determine whether an unfolding candidate really should be unfolded.
452 The predicate is needed to prevent @_casm_@s (+ lit-lits) from being emitted
453 into interface files.
455 The reason for inlining expressions containing _casm_s into interface files
456 is that these fragments of C are likely to mention functions/#defines that
457 will be out-of-scope when inlined into another module. This is not an
458 unfixable problem for the user (just need to -#include the approp. header
459 file), but turning it off seems to the simplest thing to do.
462 okToUnfoldInHiFile :: CoreExpr -> Bool
463 okToUnfoldInHiFile e = opt_UnfoldCasms || go e
465 -- Race over an expression looking for CCalls..
467 go (Con (Literal lit) _) = not (isLitLitLit lit)
468 go (Con (PrimOp op) args) = okToUnfoldPrimOp op && all go args
469 go (Con con args) = True -- con args are always atomic
470 go (App fun arg) = go fun && go arg
471 go (Lam _ body) = go body
472 go (Let binds body) = and (map go (body :rhssOfBind binds))
473 go (Case scrut bndr alts) = and (map go (scrut:rhssOfAlts alts))
474 go (Note _ body) = go body
477 -- ok to unfold a PrimOp as long as it's not a _casm_
478 okToUnfoldPrimOp (CCallOp _ is_casm _ _) = not is_casm
479 okToUnfoldPrimOp _ = True
483 %************************************************************************
485 \subsection{callSiteInline}
487 %************************************************************************
489 This is the key function. It decides whether to inline a variable at a call site
491 callSiteInline is used at call sites, so it is a bit more generous.
492 It's a very important function that embodies lots of heuristics.
493 A non-WHNF can be inlined if it doesn't occur inside a lambda,
494 and occurs exactly once or
495 occurs once in each branch of a case and is small
497 If the thing is in WHNF, there's no danger of duplicating work,
498 so we can inline if it occurs once, or is small
501 callSiteInline :: Bool -- True <=> the Id is black listed
502 -> Bool -- 'inline' note at call site
504 -> [Bool] -- One for each value arg; True if it is interesting
505 -> Bool -- True <=> continuation is interesting
506 -> Maybe CoreExpr -- Unfolding, if any
509 callSiteInline black_listed inline_call id arg_infos interesting_cont
510 = case getIdUnfolding id of {
511 NoUnfolding -> Nothing ;
512 OtherCon _ -> Nothing ;
513 CoreUnfolding unf_template is_cheap _ guidance ->
516 result | yes_or_no = Just unf_template
517 | otherwise = Nothing
519 inline_prag = getInlinePragma id
520 n_val_args = length arg_infos
524 IAmDead -> pprTrace "callSiteInline: dead" (ppr id) False
525 IMustNotBeINLINEd -> False
526 IAmALoopBreaker -> False
527 IMustBeINLINEd -> True -- Overrides absolutely everything, including the black list
528 ICanSafelyBeINLINEd in_lam one_br -> consider in_lam True one_br
529 NoInlinePragInfo -> consider InsideLam False False
531 consider in_lam once once_in_one_branch
532 | black_listed = False
534 | once_in_one_branch -- Be very keen to inline something if this is its unique occurrence; that
535 -- gives a good chance of eliminating the original binding for the thing.
536 -- The only time we hold back is when substituting inside a lambda;
537 -- then if the context is totally uninteresting (not applied, not scrutinised)
538 -- there is no point in substituting because it might just increase allocation.
539 = WARN( case in_lam of { NotInsideLam -> True; other -> False },
540 text "callSiteInline:oneOcc" <+> ppr id )
541 -- If it has one occurrence, not inside a lambda, PreInlineUnconditionally
542 -- should have zapped it already
543 is_cheap && (not (null arg_infos) || interesting_cont)
545 | otherwise -- Occurs (textually) more than once, so look at its size
549 UnfoldIfGoodArgs n_vals_wanted arg_discounts size res_discount
550 | enough_args && size <= (n_vals_wanted + 1)
552 -- Size of call is n_vals_wanted (+1 for the function)
555 InsideLam -> is_cheap
557 | not (or arg_infos || really_interesting_cont || once)
558 -- If it occurs more than once, there must be something interesting
559 -- about some argument, or the result, to make it worth inlining
560 -- We also drop this case if the thing occurs once, although perhaps in
561 -- several branches. In this case we are keener about inlining in the hope
562 -- that we'll be able to drop the allocation for the function altogether.
567 NotInsideLam -> small_enough
568 InsideLam -> is_cheap && small_enough
571 enough_args = n_val_args >= n_vals_wanted
572 really_interesting_cont | n_val_args < n_vals_wanted = False -- Too few args
573 | n_val_args == n_vals_wanted = interesting_cont
574 | otherwise = True -- Extra args
575 -- This rather elaborate defn for really_interesting_cont is important
576 -- Consider an I# = INLINE (\x -> I# {x})
577 -- The unfolding guidance deems it to have size 2, and no arguments.
578 -- So in an application (I# y) we must take the extra arg 'y' as
579 -- evidence of an interesting context!
581 small_enough = (size - discount) <= opt_UF_UseThreshold
582 discount = computeDiscount n_vals_wanted arg_discounts res_discount
583 arg_infos really_interesting_cont
588 if opt_D_dump_inlinings then
589 pprTrace "Considering inlining"
590 (ppr id <+> vcat [text "black listed" <+> ppr black_listed,
591 text "inline prag:" <+> ppr inline_prag,
592 text "arg infos" <+> ppr arg_infos,
593 text "interesting continuation" <+> ppr interesting_cont,
594 text "is cheap" <+> ppr is_cheap,
595 text "guidance" <+> ppr guidance,
596 text "ANSWER =" <+> if yes_or_no then text "YES" else text "NO",
598 text "Unfolding =" <+> pprCoreExpr unf_template
606 computeDiscount :: Int -> [Int] -> Int -> [Bool] -> Bool -> Int
607 computeDiscount n_vals_wanted arg_discounts res_discount arg_infos result_used
608 -- We multiple the raw discounts (args_discount and result_discount)
609 -- ty opt_UnfoldingKeenessFactor because the former have to do with
610 -- *size* whereas the discounts imply that there's some extra
611 -- *efficiency* to be gained (e.g. beta reductions, case reductions)
614 -- we also discount 1 for each argument passed, because these will
615 -- reduce with the lambdas in the function (we count 1 for a lambda
617 = 1 + -- Discount of 1 because the result replaces the call
618 -- so we count 1 for the function itself
619 length (take n_vals_wanted arg_infos) +
620 -- Discount of 1 for each arg supplied, because the
621 -- result replaces the call
622 round (opt_UF_KeenessFactor *
623 fromInt (arg_discount + result_discount))
625 arg_discount = sum (zipWith mk_arg_discount arg_discounts arg_infos)
627 mk_arg_discount discount is_evald | is_evald = discount
630 -- Don't give a result discount unless there are enough args
631 result_discount | result_used = res_discount -- Over-applied, or case scrut
636 %************************************************************************
638 \subsection{Black-listing}
640 %************************************************************************
642 Inlining is controlled by the "Inline phase" number, which is set
643 by the per-simplification-pass '-finline-phase' flag.
645 For optimisation we use phase 1,2 and nothing (i.e. no -finline-phase flag)
646 in that order. The meanings of these are determined by the @blackListed@ function
650 blackListed :: IdSet -- Used in transformation rules
651 -> Maybe Int -- Inline phase
652 -> Id -> Bool -- True <=> blacklisted
654 -- The blackListed function sees whether a variable should *not* be
655 -- inlined because of the inline phase we are in. This is the sole
656 -- place that the inline phase number is looked at.
658 -- ToDo: improve horrible coding style (too much duplication)
660 -- Phase 0: used for 'no imported inlinings please'
661 -- This prevents wrappers getting inlined which in turn is bad for full laziness
662 -- NEW: try using 'not a wrapper' rather than 'not imported' in this phase.
663 -- This allows a little more inlining, which seems to be important, sometimes.
664 -- For example PrelArr.newIntArr gets better.
665 blackListed rule_vars (Just 0)
666 = \v -> let v_uniq = idUnique v
668 -- not (isLocallyDefined v)
669 workerExists (getIdWorkerInfo v)
670 || v `elemVarSet` rule_vars
671 || not (isEmptyCoreRules (getIdSpecialisation v))
672 || v_uniq == runSTRepIdKey
674 -- Phase 1: don't inline any rule-y things or things with specialisations
675 blackListed rule_vars (Just 1)
676 = \v -> let v_uniq = idUnique v
677 in v `elemVarSet` rule_vars
678 || not (isEmptyCoreRules (getIdSpecialisation v))
679 || v_uniq == runSTRepIdKey
681 -- Phase 2: allow build/augment to inline, and specialisations
682 blackListed rule_vars (Just 2)
683 = \v -> let v_uniq = idUnique v
684 in (v `elemVarSet` rule_vars && not (v_uniq == buildIdKey ||
685 v_uniq == augmentIdKey))
686 || v_uniq == runSTRepIdKey
688 -- Otherwise just go for it
689 blackListed rule_vars phase
694 SLPJ 95/04: Why @runST@ must be inlined very late:
698 (a, s') = newArray# 100 [] s
699 (_, s'') = fill_in_array_or_something a x s'
703 If we inline @runST@, we'll get:
706 (a, s') = newArray# 100 [] realWorld#{-NB-}
707 (_, s'') = fill_in_array_or_something a x s'
711 And now the @newArray#@ binding can be floated to become a CAF, which
712 is totally and utterly wrong:
715 (a, s') = newArray# 100 [] realWorld#{-NB-} -- YIKES!!!
718 let (_, s'') = fill_in_array_or_something a x s' in
721 All calls to @f@ will share a {\em single} array!
723 Yet we do want to inline runST sometime, so we can avoid
724 needless code. Solution: black list it until the last moment.