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

Unboxed tuples #2879

Merged
merged 4 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion middle_end/flambda2/from_lambda/closure_conversion.ml
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ let close_c_call acc env ~loc ~let_bound_ids_with_kinds
K.With_subkind.(
kind
(from_lambda_values_and_unboxed_numbers_only
(Typeopt.layout_of_const_sort sort)))
(Typeopt.layout_of_base_sort sort)))
| Unboxed_float Pfloat64 -> K.naked_float
| Unboxed_float Pfloat32 -> K.naked_float32
| Unboxed_integer Pnativeint -> K.naked_nativeint
Expand Down
7 changes: 6 additions & 1 deletion ocaml/bytecomp/bytegen.ml
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ let comp_primitive stack_info p sz args =
| Pcompare_floats Pfloat32 -> Kccall("caml_float32_compare", 2)
| Pcompare_bints bi -> comp_bint_primitive bi "compare" args
| Pfield (n, _ptr, _sem) -> Kgetfield n
| Punboxed_product_field (n, _layouts) -> Kgetfield n
| Pfield_computed _sem -> Kgetvectitem
| Psetfield(n, _ptr, _init) -> Ksetfield n
| Psetfield_computed(_ptr, _init) -> Ksetvectitem
Expand Down Expand Up @@ -628,12 +629,12 @@ let comp_primitive stack_info p sz args =
| Pmakearray _ | Pduparray _
| Pfloatcomp (_, _) | Punboxed_float_comp (_, _)
| Pmakeblock _
| Pmake_unboxed_product _
| Pmakefloatblock _
| Pmakeufloatblock _
| Pmakemixedblock _
| Pprobe_is_enabled _
| Punbox_float _ | Pbox_float (_, _) | Punbox_int _ | Pbox_int _
| Pmake_unboxed_product _ | Punboxed_product_field _
->
fatal_error "Bytegen.comp_primitive"

Expand Down Expand Up @@ -920,6 +921,10 @@ let rec comp_expr stack_info env exp sz cont =
let cont = add_pseudo_event loc !compunit_name cont in
comp_args stack_info env args sz
(Kmakeblock(List.length args, tag) :: cont)
| Lprim(Pmake_unboxed_product _, args, loc) ->
let cont = add_pseudo_event loc !compunit_name cont in
comp_args stack_info env args sz
(Kmakeblock(List.length args, 0) :: cont)
| Lprim(Pfloatfield (n, _, _), args, loc) ->
let cont = add_pseudo_event loc !compunit_name cont in
comp_args stack_info env args sz (Kgetfloatfield n :: cont)
Expand Down
5 changes: 4 additions & 1 deletion ocaml/file_formats/cmt_format.ml
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,8 @@ let iter_on_occurrences
| Texp_extension_constructor (lid, path) ->
f ~namespace:Extension_constructor exp_env path lid
| Texp_constant _ | Texp_let _ | Texp_function _ | Texp_apply _
| Texp_match _ | Texp_try _ | Texp_tuple _ | Texp_variant _ | Texp_array _
| Texp_match _ | Texp_try _ | Texp_tuple _ | Texp_unboxed_tuple _
| Texp_variant _ | Texp_array _
| Texp_ifthenelse _ | Texp_sequence _ | Texp_while _ | Texp_for _
| Texp_send _
| Texp_letmodule _ | Texp_letexception _ | Texp_assert _ | Texp_lazy _
Expand All @@ -243,6 +244,7 @@ let iter_on_occurrences
(* Deprecated syntax to extend a polymorphic variant *)
f ~namespace:Type ctyp_env path lid
| Ttyp_var _ | Ttyp_arrow _ | Ttyp_tuple _ | Ttyp_object _
| Ttyp_unboxed_tuple _
| Ttyp_alias _ | Ttyp_variant _ | Ttyp_poly _
| Ttyp_call_pos -> ());
default_iterator.typ sub ct);
Expand All @@ -268,6 +270,7 @@ let iter_on_occurrences
add_label pat_env lid label_descr)
fields
| Tpat_any | Tpat_var _ | Tpat_alias _ | Tpat_constant _ | Tpat_tuple _
| Tpat_unboxed_tuple _
| Tpat_variant _ | Tpat_array _ | Tpat_lazy _ | Tpat_value _
| Tpat_exception _ | Tpat_or _ -> ());
List.iter (fun (pat_extra, _, _) ->
Expand Down
2 changes: 1 addition & 1 deletion ocaml/lambda/lambda.ml
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ type primitive =
| Pdls_get

and extern_repr =
| Same_as_ocaml_repr of Jkind.Sort.const
| Same_as_ocaml_repr of Jkind.Sort.base
| Unboxed_float of boxed_float
| Unboxed_vector of Primitive.boxed_vector
| Unboxed_integer of Primitive.boxed_integer
Expand Down
2 changes: 1 addition & 1 deletion ocaml/lambda/lambda.mli
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ type primitive =
(** This is the same as [Primitive.native_repr] but with [Repr_poly]
compiled away. *)
and extern_repr =
| Same_as_ocaml_repr of Jkind.Sort.const
| Same_as_ocaml_repr of Jkind.Sort.base
| Unboxed_float of boxed_float
| Unboxed_vector of Primitive.boxed_vector
| Unboxed_integer of Primitive.boxed_integer
Expand Down
90 changes: 63 additions & 27 deletions ocaml/lambda/matching.ml
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,18 @@ exception Error of Location.t * error
let dbg = false

let jkind_layout_default_to_value_and_check_not_void loc jkind =
let rec contains_void : Jkind.Layout.Const.t -> bool = function
| Any -> false
| Base Void -> true
| Base (Value | Float64 | Float32 | Word | Bits32 | Bits64) -> false
| Product [] ->
Misc.fatal_error "nil in jkind_layout_default_to_value_and_check_not_void"
| Product ts -> List.exists contains_void ts
ccasin marked this conversation as resolved.
Show resolved Hide resolved
in
let const = Jkind.default_to_value_and_get jkind in
let layout = Jkind.Const.get_layout const in
match layout with
| Sort Void -> raise (Error (loc, Void_layout))
| _ -> ()
if contains_void layout then
raise (Error (loc, Void_layout))
;;

(*
Expand Down Expand Up @@ -261,8 +268,8 @@ end = struct
| `Or _ as or_view -> stop orpat or_view
| other_view -> continue orpat other_view
)
| ( `Constant _ | `Tuple _ | `Construct _ | `Variant _ | `Array _
| `Lazy _ ) as view ->
| ( `Constant _ | `Tuple _ | `Unboxed_tuple _ | `Construct _ | `Variant _
| `Array _ | `Lazy _ ) as view ->
stop p view
in
aux cl
Expand Down Expand Up @@ -299,6 +306,9 @@ end = struct
| `Constant cst -> `Constant cst
| `Tuple ps ->
`Tuple (List.map (fun (label, p) -> label, alpha_pat env p) ps)
| `Unboxed_tuple ps ->
`Unboxed_tuple
(List.map (fun (label, p, sort) -> label, alpha_pat env p, sort) ps)
| `Construct (cstr, cst_descr, args) ->
`Construct (cstr, cst_descr, List.map (alpha_pat env) args)
| `Variant (cstr, argo, row_desc) ->
Expand Down Expand Up @@ -437,42 +447,27 @@ let matcher discr (p : Simple.pattern) rem =
match (discr.pat_desc, ph.pat_desc) with
| Any, _ -> rem
| ( ( Constant _ | Construct _ | Variant _ | Lazy | Array _ | Record _
| Tuple _ ),
| Tuple _ | Unboxed_tuple _ ),
Any ) ->
omegas @ rem
| Constant cst, Constant cst' -> yesif (const_compare cst cst' = 0)
| Constant _, (Construct _ | Variant _ | Lazy | Array _ | Record _ | Tuple _)
->
no ()
| Construct cstr, Construct cstr' ->
(* NB: may_equal_constr considers (potential) constructor rebinding;
Types.may_equal_constr does check that the arities are the same,
preserving row-size coherence. *)
yesif (Types.may_equal_constr cstr cstr')
| Construct _, (Constant _ | Variant _ | Lazy | Array _ | Record _ | Tuple _)
->
no ()
| Variant { tag; has_arg }, Variant { tag = tag'; has_arg = has_arg' } ->
yesif (tag = tag' && has_arg = has_arg')
| Variant _, (Constant _ | Construct _ | Lazy | Array _ | Record _ | Tuple _)
->
no ()
| Array (am1, _, n1), Array (am2, _, n2) -> yesif (am1 = am2 && n1 = n2)
| Array _, (Constant _ | Construct _ | Variant _ | Lazy | Record _ | Tuple _)
->
no ()
| Tuple n1, Tuple n2 -> yesif (n1 = n2)
| Tuple _, (Constant _ | Construct _ | Variant _ | Lazy | Array _ | Record _)
->
no ()
| Unboxed_tuple l1, Unboxed_tuple l2 ->
yesif (List.for_all2 (fun (lbl1, _) (lbl2, _) -> lbl1 = lbl2) l1 l2)
| Record l, Record l' ->
(* we already expanded the record fully *)
yesif (List.length l = List.length l')
| Record _, (Constant _ | Construct _ | Variant _ | Lazy | Array _ | Tuple _)
->
no ()
| Lazy, Lazy -> yes ()
| Lazy, (Constant _ | Construct _ | Variant _ | Array _ | Record _ | Tuple _)
| ( Constant _ | Construct _ | Variant _ | Lazy | Array _ | Record _ | Tuple _
| Unboxed_tuple _), _
->
no ()

Expand Down Expand Up @@ -1180,6 +1175,7 @@ let can_group discr pat =
Types.equal_tag discr_tag pat_cstr.cstr_tag
| Construct _, Construct _
| Tuple _, (Tuple _ | Any)
| Unboxed_tuple _, (Unboxed_tuple _ | Any)
| Record _, (Record _ | Any)
| Array _, Array _
| Variant _, Variant _
Expand All @@ -1193,7 +1189,8 @@ let can_group discr pat =
| Const_int32 _ | Const_int64 _ | Const_nativeint _
| Const_unboxed_int32 _ | Const_unboxed_int64 _
| Const_unboxed_nativeint _ )
| Construct _ | Tuple _ | Record _ | Array _ | Variant _ | Lazy ) ) ->
| Construct _ | Tuple _ | Unboxed_tuple _ | Record _ | Array _
| Variant _ | Lazy ) ) ->
false

let is_or p =
Expand Down Expand Up @@ -2098,6 +2095,13 @@ let get_pat_args_tuple arity p rem =
| { pat_desc = Tpat_tuple args } -> (List.map snd args) @ rem
| _ -> assert false

let get_pat_args_unboxed_tuple arity p rem =
match p with
| { pat_desc = Tpat_any } -> Patterns.omegas arity @ rem
| { pat_desc = Tpat_unboxed_tuple args } ->
(List.map (fun (_, p, _) -> p) args) @ rem
| _ -> assert false

let get_expr_args_tuple ~scopes head (arg, _mut, _sort, _layout) rem =
let loc = head_loc ~scopes head in
let arity = Patterns.Head.arity head in
Expand All @@ -2111,13 +2115,38 @@ let get_expr_args_tuple ~scopes head (arg, _mut, _sort, _layout) rem =
in
make_args 0

let get_expr_args_unboxed_tuple ~scopes shape head (arg, _mut, _sort, _layout)
rem =
let loc = head_loc ~scopes head in
let shape =
List.map (fun (_, sort) ->
sort,
(* CR layouts v7.1: consider whether more accurate [Lambda.layout]s here
would make a difference for later optimizations. *)
Typeopt.layout_of_sort (Scoped_location.to_location loc) sort
) shape
in
let layouts = List.map (fun (_, layout) -> layout) shape in
List.mapi (fun pos (sort, layout) ->
(Lprim (Punboxed_product_field (pos, layouts), [ arg ], loc), Alias,
sort, layout))
shape
@ rem

let divide_tuple ~scopes head ctx pm =
let arity = Patterns.Head.arity head in
divide_line (Context.specialize head)
(get_expr_args_tuple ~scopes)
(get_pat_args_tuple arity)
head ctx pm

let divide_unboxed_tuple ~scopes head shape ctx pm =
let arity = Patterns.Head.arity head in
divide_line (Context.specialize head)
(get_expr_args_unboxed_tuple ~scopes shape)
(get_pat_args_unboxed_tuple arity)
head ctx pm

(* Matching against a record pattern *)

let record_matching_line num_fields lbl_pat_list =
Expand Down Expand Up @@ -3582,6 +3611,10 @@ and do_compile_matching ~scopes value_kind repr partial ctx pmh =
compile_no_test ~scopes value_kind
(divide_tuple ~scopes ph)
Context.combine repr partial ctx pm
| Unboxed_tuple shape ->
compile_no_test ~scopes value_kind
(divide_unboxed_tuple ~scopes ph shape)
Context.combine repr partial ctx pm
| Record [] -> assert false
| Record (lbl :: _) ->
compile_no_test ~scopes value_kind
Expand Down Expand Up @@ -3663,6 +3696,7 @@ let is_lazy_pat p =
| Tpat_variant _
| Tpat_record _
| Tpat_tuple _
| Tpat_unboxed_tuple _
| Tpat_construct _
| Tpat_array _
| Tpat_or _
Expand All @@ -3683,6 +3717,7 @@ let is_record_with_mutable_field p =
| Tpat_variant _
| Tpat_lazy _
| Tpat_tuple _
| Tpat_unboxed_tuple _
| Tpat_construct _
| Tpat_array _
| Tpat_or _
Expand Down Expand Up @@ -4024,7 +4059,8 @@ let flatten_simple_pattern size (p : Simple.pattern) =
| `Record _
| `Lazy _
| `Construct _
| `Constant _ ->
| `Constant _
| `Unboxed_tuple _ ->
(* All calls to this function originate from [do_for_multiple_match],
where we know that the scrutinee is a tuple literal.

Expand Down
27 changes: 23 additions & 4 deletions ocaml/lambda/translcore.ml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type error =
| Unreachable_reached
| Bad_probe_layout of Ident.t
| Illegal_void_record_field
| Illegal_product_record_field of Jkind.Sort.Const.t
| Void_sort of type_expr

exception Error of Location.t * error
Expand All @@ -55,8 +56,9 @@ let layout_pat sort p = layout p.pat_env p.pat_loc sort p.pat_type

let check_record_field_sort loc sort =
match Jkind.Sort.default_to_value_and_get sort with
| Value | Float64 | Float32 | Bits32 | Bits64 | Word -> ()
| Void -> raise (Error (loc, Illegal_void_record_field))
| Base (Value | Float64 | Float32 | Bits32 | Bits64 | Word) -> ()
| Base Void -> raise (Error (loc, Illegal_void_record_field))
| Product _ as c -> raise (Error (loc, Illegal_product_record_field c))

(* Forward declaration -- to be filled in by Translmod.transl_module *)
let transl_module =
Expand Down Expand Up @@ -428,8 +430,9 @@ and transl_exp0 ~in_new_scope ~scopes sort e =
| ((_, arg_repr) :: prim_repr), ((_, Arg (x, _)) :: oargs) ->
let arg_exps, extra_args = cut_args prim_repr oargs in
let arg_sort =
Jkind.Sort.of_const
(Translprim.sort_of_native_repr arg_repr ~poly_sort:psort)
Jkind.Sort.of_base
(Translprim.sort_of_native_repr ~loc:x.exp_loc arg_repr
~poly_sort:psort)
in
(x, arg_sort) :: arg_exps, extra_args
| _, ((_, Omitted _) :: _) -> assert false
Expand Down Expand Up @@ -510,6 +513,12 @@ and transl_exp0 ~in_new_scope ~scopes sort e =
ll,
(of_location ~scopes e.exp_loc))
end
| Texp_unboxed_tuple el ->
let shape = List.map (fun (_, e, s) -> layout_exp s e) el in
let ll = List.map (fun (_, e, s) -> transl_exp ~scopes s e) el in
Lprim(Pmake_unboxed_product shape,
ll,
of_location ~scopes e.exp_loc)
| Texp_construct(_, cstr, args, alloc_mode) ->
let args_with_sorts =
List.mapi (fun i e ->
Expand Down Expand Up @@ -2094,6 +2103,11 @@ and transl_match ~scopes ~arg_sort ~return_sort e arg pat_expr_list partial =
let classic =
match arg, exn_cases with
| {exp_desc = Texp_tuple (argl, alloc_mode)}, [] ->
(* CR layouts v7.1: This case and the one below it give special treatment
to matching on literal tuples. This optimization is irrelevant for
unboxed tuples in native code, but not doing it for unboxed tuples in
bytecode means unboxed tuple are slightly worse than normal tuples
there. Consider adding it for unboxed tuples. *)
assert (static_handlers = []);
let mode = transl_alloc_mode alloc_mode in
let argl =
Expand Down Expand Up @@ -2256,6 +2270,11 @@ let report_error ppf = function
fprintf ppf
"Void sort detected where value was expected in a record field:@ Please \
report this error to the Jane Street compilers team."
| Illegal_product_record_field c ->
fprintf ppf
"Product sort %a detected in a record field:@ Please \
report this error to the Jane Street compilers team."
Jkind.Sort.Const.format c
| Void_sort ty ->
fprintf ppf
"Void detected in translation for type %a:@ Please report this error \
Expand Down
1 change: 1 addition & 0 deletions ocaml/lambda/translcore.mli
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ type error =
| Unreachable_reached
| Bad_probe_layout of Ident.t
| Illegal_void_record_field
| Illegal_product_record_field of Jkind.Sort.Const.t
| Void_sort of Types.type_expr

exception Error of Location.t * error
Expand Down
Loading
Loading