Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Static allocation / simplification for unboxed product arrays #3363

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

mshinwell
Copy link
Collaborator

This allows arrays involving unboxed products to be statically allocated and in certain cases have their accesses simplified, just like for normal arrays. This doesn't currently add to the testsuite; we can do that once #3317 has been merged with the augmented tests. Previously for testing I used:

(* ... with the temporary used to communicate to the C runtime stub
   being constant, and statically allocated *)

let make_unboxed_tuple_vect_scannable () =
  make_unboxed_tuple_vect 42 #(1, 2.0, "3")

let make_unboxed_tuple_vect_ignorable () =
  make_unboxed_tuple_vect 42 #(#1.0, 2, #3L, true)

let _ = make_unboxed_tuple_vect_scannable ()
let _ = make_unboxed_tuple_vect_ignorable ()

(* ... with the temporary used to communicate to the C runtime stub
   being inconstant, and statically allocated *)

let[@inline] make_unboxed_tuple_vect_scannable_inconstant () =
  make_unboxed_tuple_vect 42 #(Sys.opaque_identity 1, 2.0, "3")

let[@inline] make_unboxed_tuple_vect_ignorable_inconstant () =
  make_unboxed_tuple_vect 42 #(#1.0, (Random.int [@inlined never]) 42, #3L, true)

let _ = make_unboxed_tuple_vect_scannable_inconstant ()
let _ = make_unboxed_tuple_vect_ignorable_inconstant ()

(* ... with the temporary used to communicate to the C runtime stub
   being dynamically allocated on the local stack. *)

let[@inline never] make_unboxed_tuple_vect_scannable_dynamic () =
  make_unboxed_tuple_vect 42 #(Sys.opaque_identity 1, 2.0, "3")

let[@inline never] make_unboxed_tuple_vect_ignorable_dynamic () =
  make_unboxed_tuple_vect 42 #(#1.0, (Random.int [@inlined never]) 42, #3L, true)

let _ = make_unboxed_tuple_vect_scannable_dynamic ()
let _ = make_unboxed_tuple_vect_ignorable_dynamic ()

@mshinwell mshinwell added flambda2 Prerequisite for, or part of, flambda2 unboxed types labels Dec 11, 2024
@mshinwell mshinwell requested review from TheNumbat and lthls December 12, 2024 13:51
| [element_kind] -> (
match K.With_subkind.kind element_kind with
| Value -> Proved false
| Naked_number Naked_float -> Proved true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks wrong. If you look at the comment in flambda_primitive.mli, on the Unboxed_product constructor of the Array_kind.t type, it says that arrays of unboxed products are never float arrays (in the sense of having Double_array_tag). So because here we can't distinguish between a legacy flat float array and an array of unboxed floats represented as unboxed products of size 1, we risk returning a wrong answer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, but the frontend will rule out unboxed products of size 1 (#3317 (comment))

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new code here should also be better.

let array_kind =
(* XXX mshinwell: should the array_load_kind be specialised too? *)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd guess no since unboxed load kinds are already known by the frontend?

else
let index = Targetint_31_63.to_int imm in
let num_elt_kinds = List.length elt_kinds in
let elt_kind = List.nth elt_kinds (index mod num_elt_kinds) in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CR: packing

let elt_kind = List.nth elt_kinds (index mod num_elt_kinds) in
if not (K.equal (K.With_subkind.kind elt_kind) result_kind)
then
(* CR mshinwell: I think this should try to reinterpret *)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, why?

@@ -959,36 +951,38 @@ let simplify_array_load (array_kind : P.Array_kind.t)
SPR.create named ~try_reify dacc
in
let[@inline] contents_unknown () =
return_given_type (T.unknown (P.result_kind' prim)) ~try_reify:false
return_given_type (T.unknown result_kind) ~try_reify:false
in
(* CR mshinwell/vlaviron: if immutable array accesses were consistently
setting [mutability] to [Immutable], we could restrict the following code
to immutable loads only and use [T.meet_is_immutable_array] instead. *)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not directly related, but we can do this now

middle_end/flambda2/terms/static_const.ml Outdated Show resolved Hide resolved
@@ -164,47 +171,47 @@ let [@ocamlformat "disable"] print ppf t =
Flambda_colours.static_part
Flambda_colours.pop
(Format.pp_print_list
~pp_sep:(fun ppf () -> Format.pp_print_string ppf "@; ")
~pp_sep:(fun ppf () -> Format.fprintf ppf "@; ")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No longer needs Format.

middle_end/flambda2/terms/static_const.ml Outdated Show resolved Hide resolved
naked_int64s
| Naked_number Naked_float -> naked_floats
| Naked_number Naked_vec128 -> naked_vec128_fields
(* The "fields" update kinds are used because we are writing into a 64-bit
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CR: packing

| [element_kind] -> (
match K.With_subkind.kind element_kind with
| Value -> Proved false
| Naked_number Naked_float -> Proved true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, but the frontend will rule out unboxed products of size 1 (#3317 (comment))

match
try_to_reify_fields env ~var_allowed alloc_mode
~field_types_and_expected_kinds
with
| Some fields -> Lift (Immutable_value_array { fields })
(* XXX mshinwell: We need to convince ourselves that there is no
problem with making different decisions based on immediacy
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this means static arrays of immediates will become non-scannable blocks? I can't think of any reason that'd be a problem, but may be worth considering stuff like this

@mshinwell mshinwell marked this pull request as draft December 20, 2024 19:31
@mshinwell
Copy link
Collaborator Author

Setting back to draft whilst work is in progress.

@mshinwell mshinwell force-pushed the flambda2-upa-static-alloc branch from 2f4cfcd to d8e9441 Compare December 20, 2024 19:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flambda2 Prerequisite for, or part of, flambda2 unboxed types
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants