summaryrefslogtreecommitdiff
path: root/compiler/coreSyn/CoreUtils.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/coreSyn/CoreUtils.hs')
-rw-r--r--compiler/coreSyn/CoreUtils.hs24
1 files changed, 23 insertions, 1 deletions
diff --git a/compiler/coreSyn/CoreUtils.hs b/compiler/coreSyn/CoreUtils.hs
index 4db9d8fc29..5608afc334 100644
--- a/compiler/coreSyn/CoreUtils.hs
+++ b/compiler/coreSyn/CoreUtils.hs
@@ -1449,8 +1449,11 @@ app_ok primop_ok fun args
-- Often there is a literal divisor, and this
-- can get rid of a thunk in an inner loop
+ | SeqOp <- op -- See Note [seq# and expr_ok]
+ -> all (expr_ok primop_ok) args
+
| otherwise
- -> primop_ok op -- Check the primop itself
+ -> primop_ok op -- Check the primop itself
&& and (zipWith arg_ok arg_tys args) -- Check the arguments
_other -> isUnliftedType (idType fun) -- c.f. the Var case of exprIsHNF
@@ -1607,6 +1610,25 @@ See also Note [dataToTag#] in primops.txt.pp.
Bottom line:
* in exprOkForSpeculation we simply ignore all lifted arguments.
+ * except see Note [seq# and expr_ok] for an exception
+
+
+Note [seq# and expr_ok]
+~~~~~~~~~~~~~~~~~~~~~~~
+Recall that
+ seq# :: forall a s . a -> State# s -> (# State# s, a #)
+must always evaluate its first argument. So it's really a
+counter-example to Note [Primops with lifted arguments]. In
+the case of seq# we must check the argument to seq#. Remember
+item (d) of the specification of exprOkForSpeculation:
+
+ -- Precisely, it returns @True@ iff:
+ -- a) The expression guarantees to terminate,
+ ...
+ -- d) without throwing a Haskell exception
+
+The lack of this special case caused Trac #5129 to go bad again.
+See comment:24 and following
************************************************************************