From d56631cb57511f95eece9e61972e142a0d9e812c Mon Sep 17 00:00:00 2001 From: "simonpj@microsoft.com" Date: Fri, 5 Dec 2008 10:32:52 +0000 Subject: [PATCH] Comments only in OccurAnal --- compiler/simplCore/OccurAnal.lhs | 55 +++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/compiler/simplCore/OccurAnal.lhs b/compiler/simplCore/OccurAnal.lhs index b92239e..6af776a 100644 --- a/compiler/simplCore/OccurAnal.lhs +++ b/compiler/simplCore/OccurAnal.lhs @@ -171,8 +171,8 @@ However things are made quite a bit more complicated by RULES. Remember ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ We avoid infinite inlinings by choosing loop breakers, and ensuring that a loop breaker cuts each loop. But what is a - "loop"? In particular, a RULES is like an equation for 'f' that - is *always* inlined if it are applicable. We do *not* disable + "loop"? In particular, a RULE is like an equation for 'f' that + is *always* inlined if it is applicable. We do *not* disable rules for loop-breakers. It's up to whoever makes the rules to make sure that the rules themselves alwasys terminate. See Note [Rules for recursive functions] in Simplify.lhs @@ -237,8 +237,9 @@ However things are made quite a bit more complicated by RULES. Remember * Note [Rule dependency info] ~~~~~~~~~~~~~~~~~~~~~~~~~~~ The VarSet in a SpecInfo is used for dependency analysis in the - occurrence analyser. We must track free vars in *both* lhs and rhs. Why both? - Consider + occurrence analyser. We must track free vars in *both* lhs and rhs. + Hence use of idRuleVars, rather than idRuleRhsVars in addRuleUsage. + Why both? Consider x = y RULE f x = 4 Then if we substitute y for x, we'd better do so in the @@ -509,7 +510,7 @@ reOrderCycle (bind : binds) -- bad choice for loop breaker | is_con_app rhs = 3 -- Data types help with cases - -- Note [conapp] + -- Note [Constructor applictions] -- If an Id is marked "never inline" then it makes a great loop breaker -- The only reason for not checking that here is that it is rare @@ -560,22 +561,24 @@ reOrderCycle (bind : binds) is_con_app _ = False makeLoopBreaker :: Bool -> Id -> Id --- Set the loop-breaker flag --- See Note [Weak loop breakers] +-- Set the loop-breaker flag: see Note [Weak loop breakers] makeLoopBreaker weak bndr = setIdOccInfo bndr (IAmALoopBreaker weak) \end{code} -Note [Worker inline loop] -~~~~~~~~~~~~~~~~~~~~~~~~ -Never choose a wrapper as the loop breaker! Because -wrappers get auto-generated inlinings when importing, and -that can lead to an infinite inlining loop. For example: +Note [INLINE pragmas] +~~~~~~~~~~~~~~~~~~~~~ +Never choose a function with an INLINE pramga as the loop breaker! +If such a function is mutually-recursive with a non-INLINE thing, +then the latter should be the loop-breaker. + +A particular case is wrappers generated by the demand analyser. +If you make then into a loop breaker you may get an infinite +inlining loop. For example: rec { $wfoo x = ....foo x.... {-loop brk-} foo x = ...$wfoo x... } - The interface file sees the unfolding for $wfoo, and sees that foo is strict (and hence it gets an auto-generated wrapper). Result: an infinite inlining in the importing scope. So be a bit careful if you @@ -584,6 +587,22 @@ nofib/spectral/minimax. If the repTree wrapper is chosen as the loop breaker then compiling Game.hs goes into an infinite loop (this happened when we gave is_con_app a lower score than inline candidates). +Note [Constructor applications] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +It's really really important to inline dictionaries. Real +example (the Enum Ordering instance from GHC.Base): + + rec f = \ x -> case d of (p,q,r) -> p x + g = \ x -> case d of (p,q,r) -> q x + d = (v, f, g) + +Here, f and g occur just once; but we can't inline them into d. +On the other hand we *could* simplify those case expressions if +we didn't stupidly choose d as the loop breaker. +But we won't because constructor args are marked "Many". +Inlining dictionaries is really essential to unravelling +the loops in static numeric dictionaries, see GHC.Float. + Note [Closure conversion] ~~~~~~~~~~~~~~~~~~~~~~~~~ We treat (\x. C p q) as a high-score candidate in the letrec scoring algorithm. @@ -657,10 +676,14 @@ addRuleUsage :: UsageDetails -> Id -> UsageDetails -- Add the usage from RULES in Id to the usage addRuleUsage usage id = foldVarSet add usage (idRuleVars id) + -- idRuleVars here: see Note [Rule dependency info] where - add v u = addOneOcc u v NoOccInfo -- Give a non-committal binder info - -- (i.e manyOcc) because many copies - -- of the specialised thing can appear + add v u = addOneOcc u v NoOccInfo + -- Give a non-committal binder info (i.e manyOcc) because + -- a) Many copies of the specialised thing can appear + -- b) We don't want to substitute a BIG expression inside a RULE + -- even if that's the only occurrence of the thing + -- (Same goes for INLINE.) \end{code} Expressions -- 1.7.10.4