summaryrefslogtreecommitdiff
path: root/compiler/stranal
diff options
context:
space:
mode:
authorNicolas Frisby <nicolas.frisby@gmail.com>2013-04-11 12:48:11 +0100
committerNicolas Frisby <nicolas.frisby@gmail.com>2013-04-11 18:47:57 +0100
commitaf12cf66d1a416a135cb98b86717aba2cd247e1a (patch)
tree8e17ace160216f6aab960132c8bd3629dbaf1849 /compiler/stranal
parent155d943cbbe0ee8c3443bb76c74dff99355b55aa (diff)
downloadhaskell-af12cf66d1a416a135cb98b86717aba2cd247e1a.tar.gz
ignore RealWorld in size_expr; flag to keep w/w from creating sharing
size_expr now ignores RealWorld lambdas, arguments, and applications. Worker-wrapper previously removed all lambdas from a function, if they were all unused. Removing *all* value lambdas is no longer allowed. Instead (\_ -> E) will become (\_void -> E), where it used to become E. The previous behavior can be recovered via the new -ffun-to-thunk flag. Nofib notables: ---------------------------------------------------------------- Program O2 O2 newly ignoring RealWorld and not turning function closures into thunks ---------------------------------------------------------------- Allocations comp_lab_zift 333090392% -5.0% reverse-complem 155188304% -3.2% rewrite 15380888% +4.0% boyer2 3901064% +7.5% rewrite previously benefited from fortunate LoopBreaker choice that is now disrupted. A function in boyer2 goes from $wonewayunify1 size 700 to size 650, thus gets inlined into rewritelemmas, thus exposing a parameter scrutinisation, thus allowing SpecConstr, which unfortunately involves reboxing. Run Time fannkuch-redux 7.89% -15.9% hpg 0.25% +5.6% wang 0.21% +5.8% /shrug
Diffstat (limited to 'compiler/stranal')
-rw-r--r--compiler/stranal/WwLib.lhs24
1 files changed, 20 insertions, 4 deletions
diff --git a/compiler/stranal/WwLib.lhs b/compiler/stranal/WwLib.lhs
index fb9396e5ea..810db2069b 100644
--- a/compiler/stranal/WwLib.lhs
+++ b/compiler/stranal/WwLib.lhs
@@ -140,7 +140,7 @@ mkWwBodies dflags fun_ty demands res_info one_shots
-- Do CPR w/w. See Note [Always do CPR w/w]
; (wrap_fn_cpr, work_fn_cpr, cpr_res_ty) <- mkWWcpr res_ty res_info
- ; let (work_lam_args, work_call_args) = mkWorkerArgs work_args all_one_shots cpr_res_ty
+ ; let (work_lam_args, work_call_args) = mkWorkerArgs dflags work_args all_one_shots cpr_res_ty
; return ([idDemandInfo v | v <- work_call_args, isId v],
wrap_fn_args . wrap_fn_cpr . wrap_fn_str . applyToVars work_call_args . Var,
mkLams work_lam_args. work_fn_str . work_fn_cpr . work_fn_args) }
@@ -184,23 +184,39 @@ add a void argument. E.g.
We use the state-token type which generates no code.
\begin{code}
-mkWorkerArgs :: [Var]
+mkWorkerArgs :: DynFlags -> [Var]
-> Bool -- Whether all arguments are one-shot
-> Type -- Type of body
-> ([Var], -- Lambda bound args
[Var]) -- Args at call site
-mkWorkerArgs args all_one_shot res_ty
- | any isId args || not (isUnLiftedType res_ty)
+mkWorkerArgs dflags args all_one_shot res_ty
+ | any isId args || not needsAValueLambda
= (args, args)
| otherwise
= (args ++ [newArg], args ++ [realWorldPrimId])
where
+ needsAValueLambda =
+ isUnLiftedType res_ty
+ || not (gopt Opt_FunToThunk dflags)
+ -- see Note [Protecting the last value argument]
+
-- see Note [All One-Shot Arguments of a Worker]
newArg = if all_one_shot
then setOneShotLambda voidArgId
else voidArgId
\end{code}
+Note [Protecting the last value argument]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If the user writes (\_ -> E), they might be intentionally disallowing
+the sharing of E. Since absence analysis and worker-wrapper are keen
+to remove such unused arguments, we add in a void argument to prevent
+the function from becoming a thunk.
+
+The user can avoid that argument with the -ffun-to-thunk
+flag. However, removing all the value argus may introduce space leaks.
+
Note [All One-Shot Arguments of a Worker]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~