`[source] `_ compiler/simplCore/SimplCore.hs =============================== Note [Inline in InitialPhase] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ `[note link] `__ In GHC 8 and earlier we did not inline anything in the InitialPhase. But that is confusing for users because when they say INLINE they expect the function to inline right away. So now we do inlining immediately, even in the InitialPhase, assuming that the Id's Activation allows it. This is a surprisingly big deal. Compiler performance improved a lot when I made this change: :: perf/compiler/T5837.run T5837 [stat too good] (normal) perf/compiler/parsing001.run parsing001 [stat too good] (normal) perf/compiler/T12234.run T12234 [stat too good] (optasm) perf/compiler/T9020.run T9020 [stat too good] (optasm) perf/compiler/T3064.run T3064 [stat too good] (normal) perf/compiler/T9961.run T9961 [stat too good] (normal) perf/compiler/T13056.run T13056 [stat too good] (optasm) perf/compiler/T9872d.run T9872d [stat too good] (normal) perf/compiler/T783.run T783 [stat too good] (normal) perf/compiler/T12227.run T12227 [stat too good] (normal) perf/should_run/lazy-bs-alloc.run lazy-bs-alloc [stat too good] (normal) perf/compiler/T1969.run T1969 [stat too good] (normal) perf/compiler/T9872a.run T9872a [stat too good] (normal) perf/compiler/T9872c.run T9872c [stat too good] (normal) perf/compiler/T9872b.run T9872b [stat too good] (normal) perf/compiler/T9872d.run T9872d [stat too good] (normal) .. Note [RULEs enabled in SimplGently] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ `[note link] `__ RULES are enabled when doing "gentle" simplification. Two reasons: * We really want the class-op cancellation to happen: op (df d1 d2) --> $cop3 d1 d2 because this breaks the mutual recursion between 'op' and 'df' * I wanted the RULE lift String ===> ... to work in Template Haskell when simplifying splices, so we get simpler code for literal strings But watch out: list fusion can prevent floating. So use phase control to switch off those rules until after floating. Note [Messing up the exported Id's RULES] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ `[note link] `__ We must be careful about discarding (obviously) or even merging the RULES on the exported Id. The example that went bad on me at one stage was this one: :: iterate :: (a -> a) -> a -> [a] [Exported] iterate = iterateList .. :: iterateFB c f x = x `c` iterateFB c f (f x) iterateList f x = x : iterateList f (f x) [Not exported] .. :: {-# RULES "iterate" forall f x. iterate f x = build (\c _n -> iterateFB c f x) "iterateFB" iterateFB (:) = iterateList #-} .. This got shorted out to: :: iterateList :: (a -> a) -> a -> [a] iterateList = iterate .. :: iterateFB c f x = x `c` iterateFB c f (f x) iterate f x = x : iterate f (f x) .. :: {-# RULES "iterate" forall f x. iterate f x = build (\c _n -> iterateFB c f x) "iterateFB" iterateFB (:) = iterate #-} .. And now we get an infinite loop in the rule system iterate f x -> build (\cn -> iterateFB c f x) -> iterateFB (:) f x -> iterate f x Old "solution": use rule switching-off pragmas to get rid of iterateList in the first place But in principle the user *might* want rules that only apply to the Id he says. And inline pragmas are similar {-# NOINLINE f #-} f = local local = Then we do not want to get rid of the NOINLINE. Hence hasShortableIdinfo. Note [Rules and indirection-zapping] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ `[note link] `__ Problem: what if x_exported has a RULE that mentions something in ...bindings...? Then the things mentioned can be out of scope! Solution a) Make sure that in this pass the usage-info from x_exported is available for ...bindings... b) If there are any such RULES, rec-ify the entire top-level. It'll get sorted out next time round Other remarks ~~~~~~~~~~~~~ If more than one exported thing is equal to a local thing (i.e., the local thing really is shared), then we do one only: \begin{verbatim} x_local = .... x_exported1 = x_local x_exported2 = x_local ==> x_exported1 = .... x_exported2 = x_exported1 \end{verbatim} We rely on prior eta reduction to simplify things like \begin{verbatim} x_exported = /\ tyvars -> x_local tyvars ==> x_exported = x_local \end{verbatim} Hence,there's a possibility of leaving unchanged something like this: \begin{verbatim} x_local = .... x_exported1 = x_local Int \end{verbatim} By the time we've thrown away the types in STG land this could be eliminated. But I don't think it's very common and it's dangerous to do this fiddling in STG land because we might elminate a binding that's mentioned in the unfolding for something. Note [Indirection zapping and ticks] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ `[note link] `__ Unfortunately this is another place where we need a special case for ticks. The following happens quite regularly: :: x_local = x_exported = tick x_local .. Which we want to become: :: x_exported = tick .. As it makes no sense to keep the tick and the expression on separate bindings. Note however that that this might increase the ticks scoping over the execution of x_local, so we can only do this for floatable ticks. More often than not, other references will be unfoldings of x_exported, and therefore carry the tick anyway. Note [Transferring IdInfo] ~~~~~~~~~~~~~~~~~~~~~~~~~~ `[note link] `__ If we have lcl_id = e; exp_id = lcl_id and lcl_id has useful IdInfo, we don't want to discard it by going gbl_id = e; lcl_id = gbl_id Instead, transfer IdInfo from lcl_id to exp_id, specifically * (Stable) unfolding * Strictness * Rules * Inline pragma Overwriting, rather than merging, seems to work ok. We also zap the InlinePragma on the lcl_id. It might originally have had a NOINLINE, which we have now transferred; and we really want the lcl_id to inline now that its RHS is trivial!