summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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)