summaryrefslogtreecommitdiff
path: root/compiler/simplCore
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2013-01-04 10:18:49 +0000
committerSimon Peyton Jones <simonpj@microsoft.com>2013-01-04 10:18:58 +0000
commit28d9a03253e8fd613667526a170b684f2017d299 (patch)
tree2b260d6234fd572d2de8bdeb36640bd5a4861a86 /compiler/simplCore
parent1687a666052ba19249186d0c4bb8e2dc3d7847f2 (diff)
downloadhaskell-28d9a03253e8fd613667526a170b684f2017d299.tar.gz
Make CaseElim a bit less aggressive
See Note [Case elimination: lifted case]: We used to do case elimination if (c) the scrutinee is a variable and 'x' is used strictly But that changes case x of { _ -> error "bad" } --> error "bad" which is very puzzling if 'x' is later bound to (error "good"). Where the order of evaluation is specified (via seq or case) we should respect it. c.f. Note [Empty case alternatives] in CoreSyn, which is how I came across this.
Diffstat (limited to 'compiler/simplCore')
-rw-r--r--compiler/simplCore/Simplify.lhs36
1 files changed, 21 insertions, 15 deletions
diff --git a/compiler/simplCore/Simplify.lhs b/compiler/simplCore/Simplify.lhs
index 8f663127d5..246c5b3ec3 100644
--- a/compiler/simplCore/Simplify.lhs
+++ b/compiler/simplCore/Simplify.lhs
@@ -26,7 +26,7 @@ import FamInstEnv ( topNormaliseType )
import DataCon ( DataCon, dataConWorkId, dataConRepStrictness, isMarkedStrict )
import CoreMonad ( Tick(..), SimplifierMode(..) )
import CoreSyn
-import Demand ( isStrictDmd, StrictSig(..), dmdTypeDepth )
+import Demand ( StrictSig(..), dmdTypeDepth )
import PprCore ( pprParendExpr, pprCoreExpr )
import CoreUnfold
import CoreUtils
@@ -1666,11 +1666,9 @@ check that
(a) 'e' is already evaluated (it may so if e is a variable)
Specifically we check (exprIsHNF e)
or
- (b) the scrutinee is a variable and 'x' is used strictly
-or
- (c) 'x' is not used at all and e is ok-for-speculation
+ (b) 'x' is not used at all and e is ok-for-speculation
-For the (c), consider
+For the (b), consider
case (case a ># b of { True -> (p,q); False -> (q,p) }) of
r -> blah
The scrutinee is ok-for-speculation (it looks inside cases), but we do
@@ -1679,6 +1677,24 @@ not want to transform to
in blah
because that builds an unnecessary thunk.
+We used also to do case elimination if
+ (c) the scrutinee is a variable and 'x' is used strictly
+But that changes
+ case x of { _ -> error "bad" }
+ --> error "bad"
+which is very puzzling if 'x' is later bound to (error "good").
+Where the order of evaluation is specified (via seq or case)
+we should respect it. See also
+Note [Empty case alternatives] in CoreSyn.
+
+ For reference, the old code was an extra disjunct in elim_lifted
+ || (strict_case_bndr && scrut_is_var scrut)
+ strict_case_bndr = isStrictDmd (idDemandInfo case_bndr)
+ scrut_is_var (Cast s _) = scrut_is_var s
+ scrut_is_var (Var _) = True
+ scrut_is_var _ = False
+
+
Note [Case elimination: unlifted case]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider
@@ -1791,7 +1807,6 @@ rebuildCase env scrut case_bndr [(_, bndrs, rhs)] cont
then elim_unlifted -- Satisfy the let-binding invariant
else elim_lifted
= do { -- pprTrace "case elim" (vcat [ppr case_bndr, ppr (exprIsHNF scrut),
- -- ppr strict_case_bndr, ppr (scrut_is_var scrut),
-- ppr ok_for_spec,
-- ppr scrut]) $
tick (CaseElim case_bndr)
@@ -1801,10 +1816,6 @@ rebuildCase env scrut case_bndr [(_, bndrs, rhs)] cont
where
elim_lifted -- See Note [Case elimination: lifted case]
= exprIsHNF scrut
- || (strict_case_bndr && scrut_is_var scrut)
- -- The case binder is going to be evaluated later,
- -- and the scrutinee is a simple variable
-
|| (is_plain_seq && ok_for_spec)
-- Note: not the same as exprIsHNF
@@ -1819,11 +1830,6 @@ rebuildCase env scrut case_bndr [(_, bndrs, rhs)] cont
ok_for_spec = exprOkForSpeculation scrut
is_plain_seq = isDeadBinder case_bndr -- Evaluation *only* for effect
- strict_case_bndr = isStrictDmd (idDemandInfo case_bndr)
-
- scrut_is_var (Cast s _) = scrut_is_var s
- scrut_is_var (Var _) = True
- scrut_is_var _ = False
--------------------------------------------------