summaryrefslogtreecommitdiff
path: root/compiler/coreSyn
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2011-11-11 19:47:15 +0000
committerSimon Peyton Jones <simonpj@microsoft.com>2011-11-11 19:47:15 +0000
commit06229a8a3d27320d51a80f5add2b307ba0eca597 (patch)
tree4f66f5a3662aa6714f0db78b0002143d41416882 /compiler/coreSyn
parentc09cbb3360cc78fc2a0e6fab61ab36a7592a77e2 (diff)
downloadhaskell-06229a8a3d27320d51a80f5add2b307ba0eca597.tar.gz
Make exprOkForSpeculation more modular (and self-consistent)
Diffstat (limited to 'compiler/coreSyn')
-rw-r--r--compiler/coreSyn/CoreUtils.lhs84
1 files changed, 44 insertions, 40 deletions
diff --git a/compiler/coreSyn/CoreUtils.lhs b/compiler/coreSyn/CoreUtils.lhs
index c4b3019485..c25b5d6618 100644
--- a/compiler/coreSyn/CoreUtils.lhs
+++ b/compiler/coreSyn/CoreUtils.lhs
@@ -715,6 +715,7 @@ it's applied only to dictionaries.
%************************************************************************
\begin{code}
+-----------------------------
-- | 'exprOkForSpeculation' returns True of an expression that is:
--
-- * Safe to evaluate even if normal order eval might not
@@ -755,12 +756,8 @@ exprOkForSpeculation :: Expr b -> Bool
exprOkForSpeculation (Lit _) = True
exprOkForSpeculation (Type _) = True
exprOkForSpeculation (Coercion _) = True
-
-exprOkForSpeculation (Var v)
- = isUnLiftedType (idType v) -- c.f. the Var case of exprIsHNF
- || isDataConWorkId v -- Nullary constructors
- || idArity v > 0 -- Functions
- || isEvaldUnfolding (idUnfolding v) -- Let-bound values
+exprOkForSpeculation (Var v) = appOkForSpeculation v []
+exprOkForSpeculation (Cast e _) = exprOkForSpeculation e
-- Tick annotations that *tick* cannot be speculated, because these
-- are meant to identify whether or not (and how often) the particular
@@ -769,8 +766,6 @@ exprOkForSpeculation (Tick tickish e)
| tickishCounts tickish = False
| otherwise = exprOkForSpeculation e
-exprOkForSpeculation (Cast e _) = exprOkForSpeculation e
-
exprOkForSpeculation (Case e _ _ alts)
= exprOkForSpeculation e -- Note [exprOkForSpeculation: case expressions]
&& all (\(_,_,rhs) -> exprOkForSpeculation rhs) alts
@@ -778,37 +773,46 @@ exprOkForSpeculation (Case e _ _ alts)
exprOkForSpeculation other_expr
= case collectArgs other_expr of
- (Var f, args) -> spec_ok (idDetails f) args
+ (Var f, args) -> appOkForSpeculation f args
_ -> False
- where
- spec_ok (DataConWorkId _) _
- = True -- The strictness of the constructor has already
+-----------------------------
+appOkForSpeculation :: Id -> [Expr b] -> Bool
+appOkForSpeculation fun args
+ = case idDetails fun of
+ DFunId new_type -> not new_type
+ -- DFuns terminate, unless the dict is implemented
+ -- with a newtype in which case they may not
+
+ DataConWorkId {} -> True
+ -- The strictness of the constructor has already
-- been expressed by its "wrapper", so we don't need
-- to take the arguments into account
- spec_ok (PrimOpId op) args
- | isDivOp op, -- Special case for dividing operations that fail
- [arg1, Lit lit] <- args -- only if the divisor is zero
- = not (isZeroLit lit) && exprOkForSpeculation arg1
- -- Often there is a literal divisor, and this
- -- can get rid of a thunk in an inner looop
-
- | DataToTagOp <- op -- See Note [dataToTag speculation]
- = True
-
- | otherwise
- = primOpOkForSpeculation op &&
- all exprOkForSpeculation args
- -- A bit conservative: we don't really need
- -- to care about lazy arguments, but this is easy
-
- spec_ok (DFunId new_type) _ = not new_type
- -- DFuns terminate, unless the dict is implemented with a newtype
- -- in which case they may not
-
- spec_ok _ _ = False
-
+ PrimOpId op
+ | isDivOp op -- Special case for dividing operations that fail
+ , [arg1, Lit lit] <- args -- only if the divisor is zero
+ -> not (isZeroLit lit) && exprOkForSpeculation arg1
+ -- Often there is a literal divisor, and this
+ -- can get rid of a thunk in an inner looop
+
+ | DataToTagOp <- op -- See Note [dataToTag speculation]
+ -> True
+
+ | otherwise
+ -> primOpOkForSpeculation op &&
+ all exprOkForSpeculation args
+ -- A bit conservative: we don't really need
+ -- to care about lazy arguments, but this is easy
+
+ _other -> isUnLiftedType (idType fun) -- c.f. the Var case of exprIsHNF
+ || idArity fun > n_val_args -- Partial apps
+ || (n_val_args ==0 &&
+ isEvaldUnfolding (idUnfolding fun)) -- Let-bound values
+ where
+ n_val_args = valArgCount args
+
+-----------------------------
altsAreExhaustive :: [Alt b] -> Bool
-- True <=> the case alterantives are definiely exhaustive
-- False <=> they may or may not be
@@ -977,19 +981,19 @@ exprIsHNFlike is_con is_con_unf = is_hnf_like
-- we could get an infinite loop
is_hnf_like (Lit _) = True
- is_hnf_like (Type _) = True -- Types are honorary Values;
+ is_hnf_like (Type _) = True -- Types are honorary Values;
-- we don't mind copying them
is_hnf_like (Coercion _) = True -- Same for coercions
is_hnf_like (Lam b e) = isRuntimeVar b || is_hnf_like e
is_hnf_like (Tick tickish e) = not (tickishCounts tickish)
&& is_hnf_like e
-- See Note [exprIsHNF Tick]
- is_hnf_like (Cast e _) = is_hnf_like e
- is_hnf_like (App e (Type _)) = is_hnf_like e
+ is_hnf_like (Cast e _) = is_hnf_like e
+ is_hnf_like (App e (Type _)) = is_hnf_like e
is_hnf_like (App e (Coercion _)) = is_hnf_like e
- is_hnf_like (App e a) = app_is_value e [a]
- is_hnf_like (Let _ e) = is_hnf_like e -- Lazy let(rec)s don't affect us
- is_hnf_like _ = False
+ is_hnf_like (App e a) = app_is_value e [a]
+ is_hnf_like (Let _ e) = is_hnf_like e -- Lazy let(rec)s don't affect us
+ is_hnf_like _ = False
-- There is at least one value argument
app_is_value :: CoreExpr -> [CoreArg] -> Bool