import PrelNames ( buildIdKey, foldrIdKey, runSTRepIdKey, augmentIdKey )
import Unique ( Unique )
import UniqFM ( keysUFM, intersectsUFM )
-import Util ( mapAndUnzip, mapAccumL )
+import Util ( mapAndUnzip )
import Outputable
+
+import Data.List
\end{code}
\begin{code}
occAnalBind env (Rec pairs) body_usage
- = foldr (_scc_ "occAnalBind.dofinal" do_final_bind) (body_usage, []) sccs
+ = foldr ({-# SCC "occAnalBind.dofinal" #-} do_final_bind) (body_usage, []) sccs
where
analysed_pairs :: [Details]
analysed_pairs = [ (bndr, rhs_usage, rhs')
]
sccs :: [SCC (Node Details)]
- sccs = _scc_ "occAnalBind.scc" stronglyConnCompR edges
+ sccs = {-# SCC "occAnalBind.scc" #-} stronglyConnCompR edges
---- stuff for dependency analysis of binds -------------------------------
edges :: [Node Details]
- edges = _scc_ "occAnalBind.assoc"
+ edges = {-# SCC "occAnalBind.assoc" #-}
[ (details, idUnique id, edges_from id rhs_usage)
| details@(id, rhs_usage, rhs) <- analysed_pairs
]
-- which has n**2 cost, and this meant that edges_from alone
-- consumed 10% of total runtime!
edges_from :: Id -> UsageDetails -> [Unique]
- edges_from bndr rhs_usage = _scc_ "occAnalBind.edges_from"
+ edges_from bndr rhs_usage = {-# SCC "occAnalBind.edges_from" #-}
keysUFM (addRuleUsage rhs_usage bndr)
---- Stuff to "re-constitute" bindings from dependency-analysis info ------
-- Also vital to avoid risk of divergence:
-- Note [Recursive rules]
- | is_con_app rhs = 2 -- Data types help with cases
- -- This used to have a lower score than inlineCandidate, but
- -- it's *really* helpful if dictionaries get inlined fast,
- -- so I'm experimenting with giving higher priority to data-typed things
+ | inlineCandidate bndr rhs = 2 -- Likely to be inlined
+ -- Note [Inline candidates]
- | inlineCandidate bndr rhs = 1 -- Likely to be inlined
+ | is_con_app rhs = 1 -- Data types help with cases
| otherwise = 0
rules_only = bndrs `intersectsUFM` rhs_usg
\end{code}
+Note [Inline candidates]
+~~~~~~~~~~~~~~~~~~~~~~~~
+At one point I gave is_con_app a higher score than inline-candidate,
+on the grounds that "it's *really* helpful if dictionaries get inlined fast".
+However a nofib run revealed no change if they were swapped so that
+inline-candidate has the higher score. And it's important that it does,
+else you can get a bad worker-wrapper split thus:
+ rec {
+ $wfoo x = ....foo x....
+
+ {-loop brk-} foo x = ...$wfoo x...
+ }
+But we *want* the wrapper to be inlined! If it isn't, 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 change this. A
+good example is Tree.repTree in nofib/spectral/minimax. If is_con_app
+has the higher score, then compiling Game.hs goes into an infinite loop.
+
Note [Recursive rules]
~~~~~~~~~~~~~~~~~~~~~~
Consider this group, which is typical of what SpecConstr builds: