Rethinking dataToTag#
We currently use a primop dataToTag#
that requires some careful handling because it can only be applied to something that has already been evaluated. We (now) mark it can_fail
to prevent it from floating out, and then add a fix-up pass in CorePrep just in case things went wrong. Could we do something simpler? Suppose we had
-- The real primop, preferably not exported from *anywhere*, but at least documented as never to be used outside GHC.
secretDataToTag# :: a -> Int#
-- A wired-in safe version
dataToTag# :: a -> Int#
dataToTag# !a = secretDataToTag# a
{-# NOINLINE dataToTag# #-}
Then dataToTag#
could be inlined in CorePrep, just like runRW#
.
Questions
How would this interact with float out? It should be perfectly safe to float out when its argument is known to be forced, but it seems likely we'll run into let/app invariant failures.
What RULES do we (or should we) have for dataToTag#
? How will this change affect them? My vague recollection is that we don't have any, but it would be pretty nice to apply something equivalent to case-of-known-constructor. Whenever dataToTag#
is applied to a known constructor, we should be able to evaluate it. The earlier we do this the better it will inform simplification.
Trac metadata
Trac field | Value |
---|---|
Version | 8.1 |
Type | Task |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |