summaryrefslogtreecommitdiff
path: root/compiler/stranal/WwLib.hs
diff options
context:
space:
mode:
authorSergei Trofimovich <slyfox@gentoo.org>2016-09-01 17:34:58 +0100
committerSergei Trofimovich <siarheit@google.com>2016-09-01 17:36:37 +0100
commita48de37dcca98e7d477040b0ed298bcd1b3ab303 (patch)
treea668a64334152ab6e62028fb0d4cf5aa81ebc33e /compiler/stranal/WwLib.hs
parentda920f691145175dc310055ae533757e638caab4 (diff)
downloadhaskell-a48de37dcca98e7d477040b0ed298bcd1b3ab303.tar.gz
restore -fmax-worker-args handling (Trac #11565)
maxWorkerArgs handling was accidentally lost 3 years ago in a major update of demand analysis commit 0831a12ea2fc73c33652eeec1adc79fa19700578 Old regression is noticeable as: - code bloat (requires stack reshuffling) - compilation slowdown (more code to optimise/generate) - and increased heap usage (DynFlags unboxing/reboxing?) On a simple compile benchmark this change causes heap allocation drop from 70G don to 67G (ghc perf build). Signed-off-by: Sergei Trofimovich <siarheit@google.com> Reviewers: simonpj, ezyang, goldfire, austin, bgamari Reviewed By: simonpj, ezyang Subscribers: thomie Differential Revision: https://phabricator.haskell.org/D2503 GHC Trac Issues: #11565
Diffstat (limited to 'compiler/stranal/WwLib.hs')
-rw-r--r--compiler/stranal/WwLib.hs30
1 files changed, 29 insertions, 1 deletions
diff --git a/compiler/stranal/WwLib.hs b/compiler/stranal/WwLib.hs
index 0057f6fb78..1a096052db 100644
--- a/compiler/stranal/WwLib.hs
+++ b/compiler/stranal/WwLib.hs
@@ -143,7 +143,7 @@ mkWwBodies dflags fam_envs fun_ty demands res_info
wrapper_body = wrap_fn_args . wrap_fn_cpr . wrap_fn_str . applyToVars work_call_args . Var
worker_body = mkLams work_lam_args. work_fn_str . work_fn_cpr . work_fn_args
- ; if useful1 && not only_one_void_argument || useful2
+ ; if is_small_enough work_args && (useful1 && not only_one_void_argument || useful2)
then return (Just (worker_args_dmds, wrapper_body, worker_body))
else return Nothing
}
@@ -163,6 +163,10 @@ mkWwBodies dflags fam_envs fun_ty demands res_info
= True
| otherwise
= False
+ is_small_enough args = count isId args <= maxWorkerArgs dflags
+ -- See Note [Limit w/w arity]
+ -- We count only Free variables (isId) to skip Type, Kind
+ -- variables which have no runtime representation.
{-
Note [Always do CPR w/w]
@@ -177,6 +181,30 @@ a disaster, because then the enclosing function might say it has the CPR
property, but now doesn't and there a cascade of disaster. A good example
is Trac #5920.
+Note [Limit w/w arity]
+~~~~~~~~~~~~~~~~~~~~~~~~
+Guard against high worker arity as it generates a lot of stack traffic.
+A simplified example is Trac #11565#comment:6
+
+Current strategy is very simple: don't perform w/w transformation at all
+if the result produces a wrapper with arity higher than -fmax-worker-args=.
+
+It is a bit all or nothing, consider
+
+ f (x,y) (a,b,c,d,e ... , z) = rhs
+
+Currently we will remove all w/w ness entirely. But actually we could
+w/w on the (x,y) pair... it's the huge product that is the problem.
+
+Could we instead refrain from w/w on an arg-by-arg basis? Yes, that'd
+solve f. But we can get a lot of args from deeply-nested products:
+
+ g (a, (b, (c, (d, ...)))) = rhs
+
+This is harder to spot on an arg-by-arg basis. Previously mkWwStr was
+given some "fuel" saying how many arguments it could add; when we ran
+out of fuel it would stop w/wing.
+Still not very clever because it had a left-right bias.
************************************************************************
* *