Skip to content

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:
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information