diff options
author | Sebastian Graf <sebastian.graf@kit.edu> | 2022-09-28 16:36:08 +0200 |
---|---|---|
committer | Sebastian Graf <sebastian.graf@kit.edu> | 2022-09-29 17:04:20 +0200 |
commit | 5a535172d13b30c94766751d0bc21a494b8858ed (patch) | |
tree | 6054a3cbc51276b4ad230ca25356b591b4176291 /compiler/GHC/Core/Opt | |
parent | 6a2eec98d9f5c3f5d735042f0d7bb65d0dbb3323 (diff) | |
download | haskell-wip/T22231.tar.gz |
Demand: Format Call SubDemands `Cn(sd)` as `C(n,sd)` (#22231)wip/T22231
Justification in #22231. Short form: In a demand like `1C1(C1(L))`
it was too easy to confuse which `1` belongs to which `C`. Now
that should be more obvious.
Fixes #22231
Diffstat (limited to 'compiler/GHC/Core/Opt')
-rw-r--r-- | compiler/GHC/Core/Opt/Arity.hs | 12 | ||||
-rw-r--r-- | compiler/GHC/Core/Opt/DmdAnal.hs | 14 | ||||
-rw-r--r-- | compiler/GHC/Core/Opt/OccurAnal.hs | 2 | ||||
-rw-r--r-- | compiler/GHC/Core/Opt/Simplify/Utils.hs | 6 | ||||
-rw-r--r-- | compiler/GHC/Core/Opt/WorkWrap.hs | 8 |
5 files changed, 21 insertions, 21 deletions
diff --git a/compiler/GHC/Core/Opt/Arity.hs b/compiler/GHC/Core/Opt/Arity.hs index 77df389dfb..922c79b746 100644 --- a/compiler/GHC/Core/Opt/Arity.hs +++ b/compiler/GHC/Core/Opt/Arity.hs @@ -977,7 +977,7 @@ idDemandOneShots bndr call_arity = idCallArity bndr dmd_one_shots :: [OneShotInfo] - -- If the demand info is Cx(C1(C1(.))) then we know that an + -- If the demand info is C(x,C(1,C(1,.))) then we know that an -- application to one arg is also an application to three dmd_one_shots = argOneShots (idDemandInfo bndr) @@ -1086,10 +1086,10 @@ uses info from both Call Arity and demand analysis. We may have /more/ call demands from the calls than we have lambdas in the binding. E.g. let f1 = \x. g x x in ...(f1 p q r)... - -- Demand on f1 is Cx(C1(C1(L))) + -- Demand on f1 is C(x,C(1,C(1,L))) let f2 = \y. error y in ...(f2 p q r)... - -- Demand on f2 is Cx(C1(C1(L))) + -- Demand on f2 is C(x,C(1,C(1,L))) In both these cases we can eta expand f1 and f2 to arity 3. But /only/ for called-once demands. Suppose we had @@ -2522,11 +2522,11 @@ Let's take the simple example of #21261, where `g` (actually, `f`) is defined as g c = c 1 2 + c 3 4 Then this is how the pieces are put together: - * Demand analysis infers `<SCS(C1(L))>` for `g`'s demand signature + * Demand analysis infers `<SC(S,C(1,L))>` for `g`'s demand signature * When the Simplifier next simplifies the argument in `g (\x y. e x y)`, it looks up the *evaluation context* of the argument in the form of the - sub-demand `CS(C1(L))` and stores it in the 'SimplCont'. + sub-demand `C(S,C(1,L))` and stores it in the 'SimplCont'. (Why does it drop the outer evaluation cardinality of the demand, `S`? Because it's irrelevant! When we simplify an expression, we do so under the assumption that it is currently under evaluation.) @@ -2535,7 +2535,7 @@ Then this is how the pieces are put together: * Then the simplifier takes apart the lambda and simplifies the lambda group and then calls 'tryEtaReduce' when rebuilding the lambda, passing the - evaluation context `CS(C1(L))` along. Then we simply peel off 2 call + evaluation context `C(S,C(1,L))` along. Then we simply peel off 2 call sub-demands `Cn` and see whether all of the n's (here: `S=C_1N` and `1=C_11`) were strict. And strict they are! Thus, it will eta-reduce `\x y. e x y` to `e`. diff --git a/compiler/GHC/Core/Opt/DmdAnal.hs b/compiler/GHC/Core/Opt/DmdAnal.hs index 86775592bb..36c512d656 100644 --- a/compiler/GHC/Core/Opt/DmdAnal.hs +++ b/compiler/GHC/Core/Opt/DmdAnal.hs @@ -157,7 +157,7 @@ Consider a CoreProgram like where e* are exported, but n* are not. Intuitively, we can see that @n1@ is only ever called with two arguments and in every call site, the first component of the result of the call -is evaluated. Thus, we'd like it to have idDemandInfo @LCL(CM(P(1L,A))@. +is evaluated. Thus, we'd like it to have idDemandInfo @LC(L,C(M,P(1L,A))@. NB: We may *not* give e2 a similar annotation, because it is exported and external callers might use it in arbitrary ways, expressed by 'topDmd'. This can then be exploited by Nested CPR and eta-expansion, @@ -671,7 +671,7 @@ There are several wrinkles: values are evaluated even if they are not used. Example from #9254: f :: (() -> (# Int#, () #)) -> () -- Strictness signature is - -- <1C1(P(A,1L))> + -- <1C(1,P(A,1L))> -- I.e. calls k, but discards first component of result f k = case k () of (# _, r #) -> r @@ -1176,10 +1176,10 @@ look a little puzzling. E.g. ( B -> j 4 ) ( C -> \y. blah ) -The entire thing is in a C1(L) context, so j's strictness signature +The entire thing is in a C(1,L) context, so j's strictness signature will be [A]b meaning one absent argument, returns bottom. That seems odd because -there's a \y inside. But it's right because when consumed in a C1(L) +there's a \y inside. But it's right because when consumed in a C(1,L) context the RHS of the join point is indeed bottom. Note [Demand signatures are computed for a threshold arity based on idArity] @@ -1222,12 +1222,12 @@ analyse for more incoming arguments than idArity. Example: then \y -> ... y ... else \y -> ... y ... -We'd analyse `f` under a unary call demand C1(L), corresponding to idArity +We'd analyse `f` under a unary call demand C(1,L), corresponding to idArity being 1. That's enough to look under the manifest lambda and find out how a unary call would use `x`, but not enough to look into the lambdas in the if branches. -On the other hand, if we analysed for call demand C1(C1(L)), we'd get useful +On the other hand, if we analysed for call demand C(1,C(1,L)), we'd get useful strictness info for `y` (and more precise info on `x`) and possibly CPR information, but @@ -2335,7 +2335,7 @@ generator, though. So: This way, correct information finds its way into the module interface (strictness signatures!) and the code generator (single-entry thunks!) -Note that, in contrast, the single-call information (CM(..)) /can/ be +Note that, in contrast, the single-call information (C(M,..)) /can/ be relied upon, as the simplifier tends to be very careful about not duplicating actual function calls. diff --git a/compiler/GHC/Core/Opt/OccurAnal.hs b/compiler/GHC/Core/Opt/OccurAnal.hs index 59158a0e90..bf6393f292 100644 --- a/compiler/GHC/Core/Opt/OccurAnal.hs +++ b/compiler/GHC/Core/Opt/OccurAnal.hs @@ -2368,7 +2368,7 @@ A: Saturated applications: eg f e1 .. en f's strictness signature into e1 .. en, but /only/ if n is enough to saturate the strictness signature. A strictness signature like - f :: C1(C1(L))LS + f :: C(1,C(1,L))LS means that *if f is applied to three arguments* then it will guarantee to call its first argument at most once, and to call the result of that at diff --git a/compiler/GHC/Core/Opt/Simplify/Utils.hs b/compiler/GHC/Core/Opt/Simplify/Utils.hs index 6a143c8be8..2a3a272f50 100644 --- a/compiler/GHC/Core/Opt/Simplify/Utils.hs +++ b/compiler/GHC/Core/Opt/Simplify/Utils.hs @@ -566,10 +566,10 @@ contEvalContext k = case k of ApplyToTy{sc_cont=k} -> contEvalContext k -- ApplyToVal{sc_cont=k} -> mkCalledOnceDmd $ contEvalContext k -- Not 100% sure that's correct, . Here's an example: - -- f (e x) and f :: <SCS(C1(L))> + -- f (e x) and f :: <SC(S,C(1,L))> -- then what is the evaluation context of 'e' when we simplify it? E.g., - -- simpl e (ApplyToVal x $ Stop "CS(C1(L))") - -- then it *should* be "C1(CS(C1(L))", so perhaps correct after all. + -- simpl e (ApplyToVal x $ Stop "C(S,C(1,L))") + -- then it *should* be "C(1,C(S,C(1,L))", so perhaps correct after all. -- But for now we just panic: ApplyToVal{} -> pprPanic "contEvalContext" (ppr k) StrictArg{sc_fun=fun_info} -> subDemandIfEvaluated (head (ai_dmds fun_info)) diff --git a/compiler/GHC/Core/Opt/WorkWrap.hs b/compiler/GHC/Core/Opt/WorkWrap.hs index 711ce6dbd8..d4fac1f869 100644 --- a/compiler/GHC/Core/Opt/WorkWrap.hs +++ b/compiler/GHC/Core/Opt/WorkWrap.hs @@ -925,15 +925,15 @@ attach OneShot annotations to the worker’s lambda binders. Example: -- Original function - f [Demand=<L,1*C1(U)>] :: (a,a) -> a + f [Demand=<L,1*C(1,U)>] :: (a,a) -> a f = \p -> ... -- Wrapper - f [Demand=<L,1*C1(U)>] :: a -> a -> a + f [Demand=<L,1*C(1,U)>] :: a -> a -> a f = \p -> case p of (a,b) -> $wf a b -- Worker - $wf [Demand=<L,1*C1(C1(U))>] :: Int -> Int + $wf [Demand=<L,1*C(1,C(1,U))>] :: Int -> Int $wf = \a b -> ... We need to check whether the original function is called once, with @@ -942,7 +942,7 @@ takes the arity of the original function (resp. the wrapper) and the demand on the original function. The demand on the worker is then calculated using mkWorkerDemand, and always of -the form [Demand=<L,1*(C1(...(C1(U))))>] +the form [Demand=<L,1*(C(1,...(C(1,U))))>] Note [Thunk splitting] ~~~~~~~~~~~~~~~~~~~~~~ |