summaryrefslogtreecommitdiff
path: root/compiler/prelude
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2018-10-12 16:04:57 +0100
committerSimon Peyton Jones <simonpj@microsoft.com>2018-10-12 16:05:17 +0100
commit05b2587b00d0a69ae98b2c4976b85cc3e33a7b49 (patch)
treecee6e542f847557d9e5789a65d736d3e58041e85 /compiler/prelude
parentce7a1c4ae4c93f2d0d3d7a0b573ddd876fc855c2 (diff)
downloadhaskell-05b2587b00d0a69ae98b2c4976b85cc3e33a7b49.tar.gz
Comments about dataToTag# only
Diffstat (limited to 'compiler/prelude')
-rw-r--r--compiler/prelude/PrelRules.hs4
-rw-r--r--compiler/prelude/primops.txt.pp74
2 files changed, 56 insertions, 22 deletions
diff --git a/compiler/prelude/PrelRules.hs b/compiler/prelude/PrelRules.hs
index 28c0628f16..3d419ba382 100644
--- a/compiler/prelude/PrelRules.hs
+++ b/compiler/prelude/PrelRules.hs
@@ -1020,7 +1020,7 @@ tagToEnumRule = do
------------------------------
dataToTagRule :: RuleM CoreExpr
--- Rules for dataToTag#
+-- See Note [dataToTag#] in primops.txt.pp
dataToTagRule = a `mplus` b
where
-- dataToTag (tagToEnum x) ==> x
@@ -2105,6 +2105,8 @@ Instead, we deal with turning one branch into DEFAULT in SimplUtils
Note [caseRules for dataToTag]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+See also Note [dataToTag#] in primpops.txt.pp
+
We want to transform
case dataToTag x of
DEFAULT -> e1
diff --git a/compiler/prelude/primops.txt.pp b/compiler/prelude/primops.txt.pp
index 303c902c83..8b327ddbc4 100644
--- a/compiler/prelude/primops.txt.pp
+++ b/compiler/prelude/primops.txt.pp
@@ -2992,27 +2992,59 @@ primop DataToTagOp "dataToTag#" GenPrimOp
primop TagToEnumOp "tagToEnum#" GenPrimOp
Int# -> a
--- Note [dataToTag#]
--- ~~~~~~~~~~~~~~~~~
--- dataToTag# evaluates its argument, so we don't want to float it out.
--- Consider:
---
--- \z. case x of y -> let v = dataToTag# y in ...
---
--- To improve floating, the FloatOut pass (deliberately) does a
--- binder-swap on the case, to give
---
--- \z. case x of y -> let v = dataToTag# x in ...
---
--- Now FloatOut might float that v-binding outside the \z
---
--- let v = dataToTag# x in \z. case x of y -> ...
---
--- But that is bad because that might mean x gets evaluated much too early!
---
--- Solution: make dataToTag# into a can_fail primop. That will stop it floating
--- (see Note [PrimOp can_fail and has_side_effects] in PrimOp). It's a bit of
--- a hack but never mind.
+{- Note [dataToTag#]
+~~~~~~~~~~~~~~~~~~~~
+The primop dataToTag# is unusual because it evaluates its argument.
+Only `SeqOp` shares that property. (Other primops do not do anything
+as fancy as argument evaluation.) The special handling for dataToTag#
+is:
+
+* CoreUtils.exprOkForSpeculation has a special case for DataToTagOp,
+ (actually in app_ok). Most primops with lifted arguments do not
+ evaluate those arguments, but DataToTagOp and SeqOp are two
+ exceptions. We say that they are /never/ ok-for-speculation,
+ regardless of the evaluated-ness of their argument.
+ See CoreUtils Note [PrimOps that evaluate their arguments]
+
+* There is a special case for DataToTagOp in StgCmmExpr.cgExpr,
+ that evaluates its argument and then extracts the tag from
+ the returned value.
+
+* An application like (dataToTag# (Just x)) is optimised by
+ dataToTagRule in PrelRules.
+
+* A case expression like
+ case (dataToTag# e) of <alts>
+ gets transformed t
+ case e of <transformed alts>
+ by PrelRules.caseRules; see Note [caseRules for dataToTag]
+
+See Trac #15696 for a long saga.
+
+Note [dataToTag# hack]
+~~~~~~~~~~~~~~~~~~~~~~
+(This a temporary hack: see Trac #15696 commment:60.)
+
+dataToTag# evaluates its argument, so we don't want to float it out.
+Consider:
+
+ \z. case x of y -> let v = dataToTag# y in ...
+
+To improve floating, the FloatOut pass (deliberately) does a
+binder-swap on the case, to give
+
+ \z. case x of y -> let v = dataToTag# x in ...
+
+Now FloatOut might float that v-binding outside the \z
+
+ let v = dataToTag# x in \z. case x of y -> ...
+
+But that is bad because that might mean x gets evaluated much too early!
+
+Solution: make dataToTag# into a can_fail primop. That will stop it floating
+(see Note [PrimOp can_fail and has_side_effects] in PrimOp). It's a bit of
+a hack but never mind.
+-}
------------------------------------------------------------------------
section "Bytecode operations"