summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2020-01-03 19:55:09 +0000
committerBen Gamari <ben@smart-cactus.org>2020-01-03 20:02:30 +0000
commitf0fb2004a8a60d270c72cce259461649ae769732 (patch)
treeb21b1224cc0ba9cf4fe24012df80913c7eab449f
parent83edba07e4fe23eb29158d4ddd6f6e25773d6f9a (diff)
downloadhaskell-wip/workaround-T17615.tar.gz
CoreUnfold: Temporary workaround for #17615wip/workaround-T17615
This is an awful but temporary workaround for #17615, where the case analysis from the 'ufVeryAggressive' selector causes the entire 'DynFlags' to be unpacked into local bindings (due to binder swap). This results in a tremendous amount of stack spillage, severely bloating the code generated for 'callSiteInline'. The right solution here is likely to fix binder swap to avoid this terrible behavior (since there are likely other instances of this as well) but this case was serious enough that it showed up in a CPU profile and consequently I wanted to fix it for 8.10.
-rw-r--r--compiler/coreSyn/CoreUnfold.hs21
1 files changed, 19 insertions, 2 deletions
diff --git a/compiler/coreSyn/CoreUnfold.hs b/compiler/coreSyn/CoreUnfold.hs
index 6535d37307..2bb2b598f3 100644
--- a/compiler/coreSyn/CoreUnfold.hs
+++ b/compiler/coreSyn/CoreUnfold.hs
@@ -1287,6 +1287,23 @@ traceInline dflags inline_id str doc result
| otherwise
= result
+-- | This is an awful but temporary workaround for #17615, where the
+-- case analysis from the 'ufVeryAggressive' selector causes the entire
+-- 'DynFlags' to be unpacked into local bindings (due to binder swap). This
+-- results in a tremendous amount of stack spillage, severely bloating the code
+-- generated for 'callSiteInline'.
+--
+-- The right solution here is likely to fix binder swap to avoid this terrible
+-- behavior (since there are likely other instances of this as well) but this
+-- case was serious enough that it showed up in a CPU profile and consequently
+-- I wanted to fix it for 8.10.
+--
+-- The workaround avoids the binder swap transformation by preventing
+-- 'ufVeryAggressive' from inlining into 'callSiteInline'.
+very_aggressive :: DynFlags -> Bool
+very_aggressive = ufVeryAggressive
+{-# NOINLINE very_aggressive #-}
+
tryUnfolding :: DynFlags -> Id -> Bool -> [ArgSummary] -> CallCtxt
-> CoreExpr -> Bool -> Bool -> UnfoldingGuidance
-> Maybe CoreExpr
@@ -1297,7 +1314,7 @@ tryUnfolding dflags id lone_variable
UnfNever -> traceInline dflags id str (text "UnfNever") Nothing
UnfWhen { ug_arity = uf_arity, ug_unsat_ok = unsat_ok, ug_boring_ok = boring_ok }
- | enough_args && (boring_ok || some_benefit || ufVeryAggressive dflags)
+ | enough_args && (boring_ok || some_benefit || very_aggressive dflags)
-- See Note [INLINE for small functions (3)]
-> traceInline dflags id str (mk_doc some_benefit empty True) (Just unf_template)
| otherwise
@@ -1307,7 +1324,7 @@ tryUnfolding dflags id lone_variable
enough_args = (n_val_args >= uf_arity) || (unsat_ok && n_val_args > 0)
UnfIfGoodArgs { ug_args = arg_discounts, ug_res = res_discount, ug_size = size }
- | ufVeryAggressive dflags
+ | very_aggressive dflags
-> traceInline dflags id str (mk_doc some_benefit extra_doc True) (Just unf_template)
| is_wf && some_benefit && small_enough
-> traceInline dflags id str (mk_doc some_benefit extra_doc True) (Just unf_template)