summaryrefslogtreecommitdiff
path: root/compiler/GHC/Core/Opt/SpecConstr.hs
diff options
context:
space:
mode:
authorSebastian Graf <sebastian.graf@kit.edu>2022-02-28 14:52:36 +0100
committerSebastian Graf <sebastian.graf@kit.edu>2022-03-11 16:03:01 +0100
commit81e5434c6597414b036e54e4c2ad9cff420d02a4 (patch)
tree2d8f8207640d4074ccfbc484eda1185f5fc7c052 /compiler/GHC/Core/Opt/SpecConstr.hs
parent844cf1e14fe031c9ed7597b00a1183ad9b1ccc0a (diff)
downloadhaskell-wip/T21150.tar.gz
Worker/wrapper: Preserve float barriers (#21150)wip/T21150
Issue #21150 shows that worker/wrapper allocated a worker function for a function with multiple calls that said "called at most once" when the first argument was absent. That's bad! This patch makes it so that WW preserves at least one non-one-shot value lambda (see `Note [Preserving float barriers]`) by passing around `void#` in place of absent arguments. Fixes #21150. Since the fix is pretty similar to `Note [Protecting the last value argument]`, I put the logic in `mkWorkerArgs`. There I realised (#21204) that `-ffun-to-thunk` is basically useless with `-ffull-laziness`, so I deprecated the flag, simplified and split into `needsVoidWorkerArg`/`addVoidWorkerArg`. SpecConstr is another client of that API. Fixes #21204. Metric Decrease: T14683
Diffstat (limited to 'compiler/GHC/Core/Opt/SpecConstr.hs')
-rw-r--r--compiler/GHC/Core/Opt/SpecConstr.hs27
1 files changed, 16 insertions, 11 deletions
diff --git a/compiler/GHC/Core/Opt/SpecConstr.hs b/compiler/GHC/Core/Opt/SpecConstr.hs
index 14fe9bec00..d973c75570 100644
--- a/compiler/GHC/Core/Opt/SpecConstr.hs
+++ b/compiler/GHC/Core/Opt/SpecConstr.hs
@@ -30,7 +30,7 @@ import GHC.Core.Utils
import GHC.Core.Unfold
import GHC.Core.FVs ( exprsFreeVarsList )
import GHC.Core.Opt.Monad
-import GHC.Core.Opt.WorkWrap.Utils ( isWorkerSmallEnough, mkWorkerArgs )
+import GHC.Core.Opt.WorkWrap.Utils
import GHC.Core.DataCon
import GHC.Core.Coercion hiding( substCo )
import GHC.Core.Rules
@@ -1771,20 +1771,25 @@ spec_one env fn arg_bndrs body (call_pat, rule_number)
-- And build the results
; let spec_body_ty = exprType spec_body
- (spec_lam_args1, spec_sig, spec_arity, spec_join_arity)
+ (spec_lam_args1, spec_sig, spec_arity1, spec_join_arity1)
= calcSpecInfo fn call_pat extra_bndrs
-- Annotate the variables with the strictness information from
-- the function (see Note [Strictness information in worker binders])
- (spec_lam_args, spec_call_args,_) = mkWorkerArgs fn False
- spec_lam_args1 []
- spec_body_ty
- -- mkWorkerArgs: usual w/w hack to avoid generating
- -- a spec_rhs of unlifted type and no args.
- -- Unlike W/W we don't turn functions into strict workers
- -- immediately here instead letting tidy handle this.
- -- For this reason we can ignore the cbv marks.
- -- See Note [Strict Worker Ids]. See Note [Tag Inference].
+ (spec_lam_args, spec_call_args, spec_arity, spec_join_arity)
+ | needsVoidWorkerArg fn arg_bndrs spec_lam_args1
+ , (spec_lam_args, spec_call_args, _) <- addVoidWorkerArg spec_lam_args1 []
+ -- needsVoidWorkerArg: usual w/w hack to avoid generating
+ -- a spec_rhs of unlifted type and no args.
+ -- Unlike W/W we don't turn functions into strict workers
+ -- immediately here instead letting tidy handle this.
+ -- For this reason we can ignore the cbv marks.
+ -- See Note [Strict Worker Ids]. See Note [Tag Inference].
+ , !spec_arity <- spec_arity1 + 1
+ , !spec_join_arity <- fmap (+ 1) spec_join_arity1
+ = (spec_lam_args, spec_call_args, spec_arity, spec_join_arity)
+ | otherwise
+ = (spec_lam_args1, spec_lam_args1, spec_arity1, spec_join_arity1)
spec_id = mkLocalId spec_name Many
(mkLamTypes spec_lam_args spec_body_ty)