summaryrefslogtreecommitdiff
path: root/compiler/coreSyn/CoreUtils.lhs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/coreSyn/CoreUtils.lhs')
-rw-r--r--compiler/coreSyn/CoreUtils.lhs29
1 files changed, 18 insertions, 11 deletions
diff --git a/compiler/coreSyn/CoreUtils.lhs b/compiler/coreSyn/CoreUtils.lhs
index 3bf07febf3..baf7e4fa80 100644
--- a/compiler/coreSyn/CoreUtils.lhs
+++ b/compiler/coreSyn/CoreUtils.lhs
@@ -908,13 +908,22 @@ it's applied only to dictionaries.
-- Note [exprOkForSpeculation: case expressions] below
--
-- Precisely, it returns @True@ iff:
+-- a) The expression guarantees to terminate,
+-- b) soon,
+-- c) without causing a write side effect (e.g. writing a mutable variable)
+-- d) without throwing a Haskell exception
+-- e) without risking an unchecked runtime exception (array out of bounds,
+-- divide by zero)
--
--- * The expression guarantees to terminate,
--- * soon,
--- * without raising an exception,
--- * without causing a side effect (e.g. writing a mutable variable)
+-- For @exprOkForSideEffects@ the list is the same, but omitting (e).
+--
+-- Note that
+-- exprIsHNF implies exprOkForSpeculation
+-- exprOkForSpeculation implies exprOkForSideEffects
+--
+-- See Note [PrimOp can_fail and has_side_effects] in PrimOp
+-- and Note [Implementation: how can_fail/has_side_effects affect transformations]
--
--- Note that if @exprIsHNF e@, then @exprOkForSpecuation e@.
-- As an example of the considerations in this test, consider:
--
-- > let x = case y# +# 1# of { r# -> I# r# }
@@ -964,7 +973,7 @@ app_ok :: (PrimOp -> Bool) -> Id -> [Expr b] -> Bool
app_ok primop_ok fun args
= case idDetails fun of
DFunId _ new_type -> not new_type
- -- DFuns terminate, unless the dict is implemented
+ -- DFuns terminate, unless the dict is implemented
-- with a newtype in which case they may not
DataConWorkId {} -> True
@@ -983,14 +992,12 @@ app_ok primop_ok fun args
-> True
| otherwise
- -> primop_ok op -- A bit conservative: we don't really need
- && all (expr_ok primop_ok) args
-
- -- to care about lazy arguments, but this is easy
+ -> primop_ok op -- A bit conservative: we don't really need
+ && all (expr_ok primop_ok) args -- 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 &&
+ || (n_val_args == 0 &&
isEvaldUnfolding (idUnfolding fun)) -- Let-bound values
where
n_val_args = valArgCount args