[commit: ghc] master: Never apply worker/wrapper to DFuns (c48595e)
git at git.haskell.org
git at git.haskell.org
Wed Dec 21 14:06:35 UTC 2016
Repository : ssh://git@git.haskell.org/ghc
On branch : master
Link : http://ghc.haskell.org/trac/ghc/changeset/c48595eef2bca6d91ec0a649839f8066f269e6a4/ghc
>---------------------------------------------------------------
commit c48595eef2bca6d91ec0a649839f8066f269e6a4
Author: Simon Peyton Jones <simonpj at microsoft.com>
Date: Wed Dec 21 12:22:00 2016 +0000
Never apply worker/wrapper to DFuns
While fixing Trac #12444 I found an occasion on which we applied
worker/wrapper to a DFunId. This is bad: it destroys the magic
DFunUnfolding.
This patch is a minor refactoring that stops this corner case
happening, and tidies up the code a bit too.
>---------------------------------------------------------------
c48595eef2bca6d91ec0a649839f8066f269e6a4
compiler/coreSyn/CoreUnfold.hs | 74 ++++++++++++++++++++++++------------------
compiler/stranal/WorkWrap.hs | 10 ++----
2 files changed, 46 insertions(+), 38 deletions(-)
diff --git a/compiler/coreSyn/CoreUnfold.hs b/compiler/coreSyn/CoreUnfold.hs
index 7faee63..a601539 100644
--- a/compiler/coreSyn/CoreUnfold.hs
+++ b/compiler/coreSyn/CoreUnfold.hs
@@ -944,40 +944,52 @@ smallEnoughToInline _ _
= False
----------------
-certainlyWillInline :: DynFlags -> Unfolding -> Maybe Unfolding
+
+certainlyWillInline :: DynFlags -> IdInfo -> Maybe Unfolding
-- Sees if the unfolding is pretty certain to inline
-- If so, return a *stable* unfolding for it, that will always inline
-certainlyWillInline dflags unf@(CoreUnfolding { uf_guidance = guidance, uf_tmpl = expr })
- = case guidance of
- UnfNever -> Nothing
- UnfWhen {} -> Just (unf { uf_src = InlineStable })
-
- -- The UnfIfGoodArgs case seems important. If we w/w small functions
- -- binary sizes go up by 10%! (This is with SplitObjs.) I'm not totally
- -- sure whyy.
- UnfIfGoodArgs { ug_size = size, ug_args = args }
- | not (null args) -- See Note [certainlyWillInline: be careful of thunks]
- , let arity = length args
- , size - (10 * (arity + 1)) <= ufUseThreshold dflags
- -> Just (unf { uf_src = InlineStable
- , uf_guidance = UnfWhen { ug_arity = arity
- , ug_unsat_ok = unSaturatedOk
- , ug_boring_ok = inlineBoringOk expr } })
- -- Note the "unsaturatedOk". A function like f = \ab. a
- -- will certainly inline, even if partially applied (f e), so we'd
- -- better make sure that the transformed inlining has the same property
-
- _ -> Nothing
-
-certainlyWillInline _ unf@(DFunUnfolding {})
- = Just unf
-
-certainlyWillInline _ _
- = Nothing
+certainlyWillInline dflags fn_info
+ = case unfoldingInfo fn_info of
+ CoreUnfolding { uf_tmpl = e, uf_guidance = g }
+ | loop_breaker -> Nothing -- Won't inline, so try w/w
+ | otherwise -> do_cunf e g -- Depends on size, so look at that
-{-
-Note [certainlyWillInline: be careful of thunks]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ DFunUnfolding {} -> Just fn_unf -- Don't w/w DFuns; it never makes sense
+ -- to do so, and even if it is currently a
+ -- loop breaker, it may not be later
+
+ _other_unf -> Nothing
+
+ where
+ loop_breaker = isStrongLoopBreaker (occInfo fn_info)
+ fn_unf = unfoldingInfo fn_info
+
+ do_cunf :: CoreExpr -> UnfoldingGuidance -> Maybe Unfolding
+ do_cunf _ UnfNever = Nothing
+ do_cunf _ (UnfWhen {}) = Just (fn_unf { uf_src = InlineStable })
+ -- INLINE functions have UnfWhen
+
+ -- The UnfIfGoodArgs case seems important. If we w/w small functions
+ -- binary sizes go up by 10%! (This is with SplitObjs.)
+ -- I'm not totally sure why.
+ -- INLINABLE functions come via this path
+ -- See Note [certainlyWillInline: INLINABLE]
+ do_cunf expr (UnfIfGoodArgs { ug_size = size, ug_args = args })
+ | not (null args) -- See Note [certainlyWillInline: be careful of thunks]
+ , let arity = length args
+ , size - (10 * (arity + 1)) <= ufUseThreshold dflags
+ = Just (fn_unf { uf_src = InlineStable
+ , uf_guidance = UnfWhen { ug_arity = arity
+ , ug_unsat_ok = unSaturatedOk
+ , ug_boring_ok = inlineBoringOk expr } })
+ -- Note the "unsaturatedOk". A function like f = \ab. a
+ -- will certainly inline, even if partially applied (f e), so we'd
+ -- better make sure that the transformed inlining has the same property
+ | otherwise
+ = Nothing
+
+{- Note [certainlyWillInline: be careful of thunks]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Don't claim that thunks will certainly inline, because that risks work
duplication. Even if the work duplication is not great (eg is_cheap
holds), it can make a big difference in an inner loop In Trac #5623 we
diff --git a/compiler/stranal/WorkWrap.hs b/compiler/stranal/WorkWrap.hs
index 2db3a71..d50bb22 100644
--- a/compiler/stranal/WorkWrap.hs
+++ b/compiler/stranal/WorkWrap.hs
@@ -289,12 +289,10 @@ tryWW dflags fam_envs is_rec fn_id rhs
-- being inlined at a call site.
= return [ (new_fn_id, rhs) ]
- | not loop_breaker
- , Just stable_unf <- certainlyWillInline dflags fn_unf
+ | Just stable_unf <- certainlyWillInline dflags fn_info
= return [ (fn_id `setIdUnfolding` stable_unf, rhs) ]
- -- Note [Don't w/w inline small non-loop-breaker, or INLINE, things]
- -- NB: use idUnfolding because we don't want to apply
- -- this criterion to a loop breaker!
+ -- See Note [Don't w/w INLINE things]
+ -- See Note [Don't w/w inline small non-loop-breaker things]
| is_fun
= splitFun dflags fam_envs new_fn_id fn_info wrap_dmds res_info rhs
@@ -306,10 +304,8 @@ tryWW dflags fam_envs is_rec fn_id rhs
= return [ (new_fn_id, rhs) ]
where
- loop_breaker = isStrongLoopBreaker (occInfo fn_info)
fn_info = idInfo fn_id
inline_act = inlinePragmaActivation (inlinePragInfo fn_info)
- fn_unf = unfoldingInfo fn_info
(wrap_dmds, res_info) = splitStrictSig (strictnessInfo fn_info)
new_fn_id = zapIdUsedOnceInfo (zapIdUsageEnvInfo fn_id)
More information about the ghc-commits
mailing list