summaryrefslogtreecommitdiff
path: root/compiler/stranal
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2015-06-24 23:43:41 +0100
committerSimon Peyton Jones <simonpj@microsoft.com>2015-06-26 08:33:06 +0100
commit9014a7ee6c1182df62dfd343e0a2269b0b4988d0 (patch)
tree6b3cf43a75c3b9cd14555e17588780b34be94126 /compiler/stranal
parentcc0dba1e4da6857a740b866d3f8a12d8549dc452 (diff)
downloadhaskell-9014a7ee6c1182df62dfd343e0a2269b0b4988d0.tar.gz
Fix addDataConStrictness
See Note [Add demands for strict constructors]. The new bit is the test for isAbsDmd in addDataConStrictness. There was a cryptic note that said that this function should add a seqDmd even for Absent arguments, but that is definitely a bad thing (as the Note now says), causing unused arguments to be passed to the worker. Easy fix!
Diffstat (limited to 'compiler/stranal')
-rw-r--r--compiler/stranal/DmdAnal.hs25
1 files changed, 14 insertions, 11 deletions
diff --git a/compiler/stranal/DmdAnal.hs b/compiler/stranal/DmdAnal.hs
index a345e45327..a0e5fef8d8 100644
--- a/compiler/stranal/DmdAnal.hs
+++ b/compiler/stranal/DmdAnal.hs
@@ -431,10 +431,7 @@ in this case.
In other words, for locally-bound lambdas we can infer
one-shotness.
--}
-
-{-
Note [Add demands for strict constructors]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider this program (due to Roman):
@@ -462,17 +459,23 @@ because X is strict, so its argument must be evaluated. And if we
because the seq is discarded (very early) since X is strict!
+We achieve the effect using addDataConStrictness. It is called at a
+case expression, such as the pattern match on (X a) in the example
+above. After computing how 'a' is used in the alternatives, we add an
+extra 'seqDmd' to it. The case alternative isn't itself strict in the
+sub-components, but simply evaluating the scrutinee to HNF does force
+those sub-components.
+
+If the argument is not used at all in the alternative (i.e. it is
+Absent), then *don't* add a 'seqDmd'. If we do, it makes it look used
+and hence it'll be passed to the worker when it doesn't need to be.
+Hence the isAbsDmd test in addDataConStrictness.
+
There is the usual danger of reboxing, which as usual we ignore. But
if X is monomorphic, and has an UNPACK pragma, then this optimisation
is even more important. We don't want the wrapper to rebox an unboxed
argument, and pass an Int to $wfoo!
-We add these extra strict demands to the demand on the *scrutinee* of
-the case expression; hence the use of addDataConStrictness when
-forming scrut_dmd. The case alternatives aren't strict in their
-sub-components, but simply evaluating the scrutinee to HNF does force
-those sub-components.
-
************************************************************************
* *
@@ -1101,9 +1104,9 @@ addDataConStrictness con ds
zipWith add ds strs
where
strs = dataConRepStrictness con
- add dmd str | isMarkedStrict str = dmd `bothDmd` seqDmd
+ add dmd str | isMarkedStrict str
+ , not (isAbsDmd dmd) = dmd `bothDmd` seqDmd
| otherwise = dmd
- -- Yes, even if 'dmd' is Absent!
findBndrsDmds :: AnalEnv -> DmdType -> [Var] -> (DmdType, [Demand])
-- Return the demands on the Ids in the [Var]