%************************************************************************
%* *
-\subsubsection[PrimOp-ool]{Which PrimOps are out-of-line}
+ Which PrimOps are out-of-line
%* *
%************************************************************************
\end{code}
-primOpOkForSpeculation
-~~~~~~~~~~~~~~~~~~~~~~
+%************************************************************************
+%* *
+ Failure and side effects
+%* *
+%************************************************************************
+
+Note [PrimOp can_fail and has_side_effects]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * A primop that is neither can_fail nor has_side_effects can be
+ executed speculatively, any number of times
+
+ * A primop that is marked can_fail cannot be executed speculatively,
+ (becuase the might provoke the failure), but it can be repeated.
+ Why would you want to do that? Perhaps it might enable some
+ eta-expansion, if you can prove that the lambda is definitely
+ applied at least once. I guess we don't currently do that.
+
+ * A primop that is marked has_side_effects can be neither speculated
+ nor repeated; it must be executed exactly the right number of
+ times.
+
+So has_side_effects implies can_fail. We don't currently exploit
+the case of primops that can_fail but do not have_side_effects.
+
+Note [primOpOkForSpeculation]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sometimes we may choose to execute a PrimOp even though it isn't
certain that its result will be required; ie execute them
``speculatively''. The same thing as ``cheap eagerness.'' Usually
this is OK, because PrimOps are usually cheap, but it isn't OK for
-(a)~expensive PrimOps and (b)~PrimOps which can fail.
-
-PrimOps that have side effects also should not be executed speculatively.
+ * PrimOps that are expensive
+ * PrimOps which can fail
+ * PrimOps that have side effects
Ok-for-speculation also means that it's ok *not* to execute the
primop. For example
See also @primOpIsCheap@ (below).
+Note [primOpHasSideEffects]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Some primops have side-effects and so, for example, must not be
+duplicated.
+
+This predicate means a little more than just "modifies the state of
+the world". What it really means is "it cosumes the state on its
+input". To see what this means, consider
+
+ let
+ t = case readMutVar# v s0 of (# s1, x #) -> (S# s1, x)
+ y = case t of (s,x) -> x
+ in
+ ... y ... y ...
+
+Now, this is part of an ST or IO thread, so we are guaranteed by
+construction that the program uses the state in a single-threaded way.
+Whenever the state resulting from the readMutVar# is demanded, the
+readMutVar# will be performed, and it will be ordered correctly with
+respect to other operations in the monad.
+
+But there's another way this could go wrong: GHC can inline t into y,
+and inline y. Then although the original readMutVar# will still be
+correctly ordered with respect to the other operations, there will be
+one or more extra readMutVar#s performed later, possibly out-of-order.
+This really happened; see #3207.
+
+The property we need to capture about readMutVar# is that it consumes
+the State# value on its input. We must retain the linearity of the
+State#.
+
+Our fix for this is to declare any primop that must be used linearly
+as having side-effects. When primOpHasSideEffects is True,
+primOpOkForSpeculation will be False, and hence primOpIsCheap will
+also be False, and applications of the primop will never be
+duplicated.
\begin{code}
+primOpHasSideEffects :: PrimOp -> Bool
+#include "primop-has-side-effects.hs-incl"
+
+primOpCanFail :: PrimOp -> Bool
+#include "primop-can-fail.hs-incl"
+
primOpOkForSpeculation :: PrimOp -> Bool
- -- See comments with CoreUtils.exprOkForSpeculation
+ -- See Note [primOpOkForSpeculation]
+ -- See comments with CoreUtils.exprOkForSpeculation
primOpOkForSpeculation op
= not (primOpHasSideEffects op || primOpOutOfLine op || primOpCanFail op)
\end{code}
-- even if primOpIsCheap sometimes says 'True'.
\end{code}
+
+%************************************************************************
+%* *
+ PrimOp code size
+%* *
+%************************************************************************
+
primOpCodeSize
~~~~~~~~~~~~~~
Gives an indication of the code size of a primop, for the purposes of
primOpCodeSizeForeignCall = 4
\end{code}
-\begin{code}
-primOpCanFail :: PrimOp -> Bool
-#include "primop-can-fail.hs-incl"
-\end{code}
-
-And some primops have side-effects and so, for example, must not be
-duplicated.
-
-This predicate means a little more than just "modifies the state of
-the world". What it really means is "it cosumes the state on its
-input". To see what this means, consider
-
- let
- t = case readMutVar# v s0 of (# s1, x #) -> (S# s1, x)
- y = case t of (s,x) -> x
- in
- ... y ... y ...
-
-Now, this is part of an ST or IO thread, so we are guaranteed by
-construction that the program uses the state in a single-threaded way.
-Whenever the state resulting from the readMutVar# is demanded, the
-readMutVar# will be performed, and it will be ordered correctly with
-respect to other operations in the monad.
-
-But there's another way this could go wrong: GHC can inline t into y,
-and inline y. Then although the original readMutVar# will still be
-correctly ordered with respect to the other operations, there will be
-one or more extra readMutVar#s performed later, possibly out-of-order.
-This really happened; see #3207.
-The property we need to capture about readMutVar# is that it consumes
-the State# value on its input. We must retain the linearity of the
-State#.
-
-Our fix for this is to declare any primop that must be used linearly
-as having side-effects. When primOpHasSideEffects is True,
-primOpOkForSpeculation will be False, and hence primOpIsCheap will
-also be False, and applications of the primop will never be
-duplicated.
-
-\begin{code}
-primOpHasSideEffects :: PrimOp -> Bool
-#include "primop-has-side-effects.hs-incl"
-\end{code}
+%************************************************************************
+%* *
+ PrimOp types
+%* *
+%************************************************************************
\begin{code}
primOpType :: PrimOp -> Type -- you may want to use primOpSig instead