Unarise: When converting unboxed sums to tuples use a more compact representation.
Summary
Currently a unboxed sum of (# Float# | Double# #) will be represented as (# Tag, Float#, Double# #) after unarise.
This was done as a stop-gap measure to fix #22208 (closed). #22208 (comment 454455) and the following comments describe why it's not trivial to simply use one double register to represent both fields.
The key issue is that if we have:
foo :: (# Float# | Double# #) -> FD
foo x = case x of
(# x1 | #) -> F x1
(# | x2 #) -> D x2
If we convert this to a single field for both float and double then we get:
M.foo :: (# GHC.Prim.Float# | GHC.Prim.Double# #) -> M.FD
[GblId, Arity=1, Unf=OtherCon []] =
{} \r [sum_tag sum_field]
case sum_tag of tag_gsc {
__DEFAULT -> M.F [sum_field];
2# -> M.D [sum_field];
};
Which in stg's current type system - weak as it is - is still ill-typed as sum_field
is used both as float and double rep.
Ideally we would generate something like:
M.foo :: (# GHC.Prim.Float# | GHC.Prim.Double# #) -> M.FD
[GblId, Arity=1, Unf=OtherCon []] =
{} \r [sum_tag sum_field]
case sum_tag of tag_gsc {
__DEFAULT -> case aKindOfTypedUnsafeCoerce# sum_field of sumfield1 { _DEFAULT -> M.F [sum_field] ; };
2# -> M.D [sum_field];
};
Where aKindOfTypedUnsafeCoerce#
is a no-op on systems where floats/doubles are stored in the same register.
Environment
- GHC version used:
Optional:
- Operating System:
- System Architecture: