summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoachim Breitner <mail@joachim-breitner.de>2015-11-06 14:04:08 +0100
committerJoachim Breitner <mail@joachim-breitner.de>2015-11-06 15:31:55 +0100
commita58eeb7febd67c93dab82de7049ef1dcdecd34e9 (patch)
treebf4a585b5b603436ec16ed242ecb20b13ef9d561
parent10647d4e2e8e3b5eb5486bd6aafbe17cda139577 (diff)
downloadhaskell-a58eeb7febd67c93dab82de7049ef1dcdecd34e9.tar.gz
Call Arity: In "e x", the result of "x" is not shared
in contrast to "e (f x)", where CorePrep will turn it into "let y = f x in e x". So in let f = ... in e (f x) we know that f is called at most once, but in let f = ... in e f we do not know that. Previously Call Arity would assume that in "e x", "x" is evaluated at most once. This rarely would make a difference (the argument "x" is analized with an incoming arity of 0, so no eta-expansion would be done anyways), but of course this should still be fixed. This fixes #11064. Note the corresponding code dmdTransformThunkDmd in DmdAnal.
-rw-r--r--compiler/simplCore/CallArity.hs20
1 files changed, 15 insertions, 5 deletions
diff --git a/compiler/simplCore/CallArity.hs b/compiler/simplCore/CallArity.hs
index c2a5ad0cae..bd997c3676 100644
--- a/compiler/simplCore/CallArity.hs
+++ b/compiler/simplCore/CallArity.hs
@@ -15,7 +15,7 @@ import BasicTypes
import CoreSyn
import Id
import CoreArity ( typeArity )
-import CoreUtils ( exprIsHNF )
+import CoreUtils ( exprIsHNF, exprIsTrivial )
--import Outputable
import UnVarGraph
import Demand
@@ -149,10 +149,15 @@ The interesting cases of the analysis:
* Case alternatives alt₁,alt₂,...:
Only one can be execuded, so
Return (alt₁ ∪ alt₂ ∪...)
- * App e₁ e₂ (and analogously Case scrut alts):
- We get the results from both sides. Additionally, anything called by e₁ can
- possibly be called with anything from e₂.
+ * App e₁ e₂ (and analogously Case scrut alts), with non-trivial e₂:
+ We get the results from both sides, with the argument evaluted at most once.
+ Additionally, anything called by e₁ can possibly be called with anything
+ from e₂.
Return: C(e₁) ∪ C(e₂) ∪ (fv e₁) × (fv e₂)
+ * App e₁ x:
+ As this is already in A-normal form, CorePrep will not separately lambda
+ bind (and hence share) x. So we conservatively assume multiple calls to x here
+ Return: C(e₁) ∪ (fv e₁) × {x} ∪ {(x,x)}
* Let v = rhs in body:
In addition to the results from the subexpressions, add all co-calls from
everything that the body calls together with v to everthing that is called
@@ -472,7 +477,12 @@ callArityAnal arity int (App e1 e2)
where
(ae1, e1') = callArityAnal (arity + 1) int e1
(ae2, e2') = callArityAnal 0 int e2
- final_ae = ae1 `both` ae2
+ -- If the argument is trivial (e.g. a variable), then it will _not_ be
+ -- let-bound in the Core to STG transformation (CorePrep actually),
+ -- so no sharing will happen here, and we have to assume many calls.
+ ae2' | exprIsTrivial e2 = calledMultipleTimes ae2
+ | otherwise = ae2
+ final_ae = ae1 `both` ae2'
-- Case expression.
callArityAnal arity int (Case scrut bndr ty alts)