ocaml-flambda / flambda-backend

The Flambda backend project for OCaml
93 stars 67 forks source link

Improved reinterpret casts for integers and floats #2686

Closed mshinwell closed 10 hours ago

mshinwell commented 3 weeks ago

This first replaces the existing Flambda 2 Reinterpret_int64_as_float primitive, which is a no-op modulo a move between register classes, with a more flexible reinterpret operation parameterized as follows:

  type t =
    | Tagged_int63_as_unboxed_int64
    | Unboxed_int64_as_tagged_int63
    | Unboxed_int64_as_unboxed_float64
    | Unboxed_float64_as_unboxed_int64

These are only supported for 64-bit targets. The semantics are as follows:

The simplification rules have been enhanced to cope with the above, allowing compile-time evaluation when arguments are known.

We also allow Flambda 2 to intercept calls to caml_int64_bits_of_float_unboxed (e.g. from Int64.bits_of_float) in the same way as the existing code for caml_int64_float_of_bits_unboxed, except that both of these now use the new primitive.

The two primitives involving tagged immediates can be bound as follows:

external i63_to_i64 : int -> int64# = "%reinterpret_tagged_int63_as_unboxed_int64"
external i64_to_i63 : int64# -> int = "%reinterpret_unboxed_int64_as_tagged_int63"
mshinwell commented 5 days ago

I've added a test case, which showed up a bug on negative inputs to the i64 -> i63 conversion! @TheNumbat please approve + merge (assuming CI has passed)