Skip to content

Commit

Permalink
Reinstate %makearray_dynamic (#3460)
Browse files Browse the repository at this point in the history
  • Loading branch information
mshinwell authored Jan 10, 2025
1 parent e1e4fb8 commit c7f573f
Show file tree
Hide file tree
Showing 50 changed files with 12,571 additions and 227 deletions.
60 changes: 57 additions & 3 deletions bytecomp/bytegen.ml
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,10 @@ let comp_primitive stack_info p sz args =
"Preinterpret_unboxed_int64_as_tagged_int63 can only be used on 64-bit \
targets";
Kccall("caml_reinterpret_unboxed_int64_as_tagged_int63", 1)
| Pmakearray_dynamic(kind, locality) ->
| Pmakearray_dynamic(kind, locality, With_initializer) ->
if List.compare_length_with args 2 <> 0 then
fatal_error "Bytegen.comp_primitive: Pmakearray_dynamic takes two \
arguments for [With_initializer]";
(* CR layouts v4.0: This is "wrong" for unboxed types. It should construct
blocks that can't be marshalled. We've decided to ignore that problem in
the short term, as it's unlikely to cause issues - see the internal arrays
Expand All @@ -701,15 +704,18 @@ let comp_primitive stack_info p sz args =
| Alloc_heap -> Kccall("caml_make_vect", 2)
| Alloc_local -> Kccall("caml_make_local_vect", 2)
end
| Parrayblit(kind) ->
begin match kind with
| Parrayblit { src_mutability = _; dst_array_set_kind } ->
begin match dst_array_set_kind with
| Punboxedvectorarray_set _ ->
fatal_error "SIMD is not supported in bytecode mode."
| Pgenarray_set _ | Pintarray_set | Paddrarray_set _
| Punboxedintarray_set _ | Pfloatarray_set | Punboxedfloatarray_set _
| Pgcscannableproductarray_set _ | Pgcignorableproductarray_set _ -> ()
end;
Kccall("caml_array_blit", 5)
| Pmakearray_dynamic(_, _, Uninitialized) ->
Misc.fatal_error "Pmakearray_dynamic Uninitialized should have been \
translated to Pmakearray_dynamic Initialized earlier on"
(* The cases below are handled in [comp_expr] before the [comp_primitive] call
(in the order in which they appear below),
so they should never be reached in this function. *)
Expand Down Expand Up @@ -1011,6 +1017,54 @@ and comp_expr stack_info env exp sz cont =
(Kreperformterm(sz + nargs) :: discard_dead_code cont)
else
fatal_error "Reperform used in non-tail position"
| Lprim (Pmakearray_dynamic (kind, locality, Uninitialized), [len], loc) ->
(* Use a dummy initializer to implement the "uninitialized" primitive *)
let init =
match kind with
| Pgenarray | Paddrarray | Pintarray | Pfloatarray
| Pgcscannableproductarray _ ->
Misc.fatal_errorf "Array kind %s should have been ruled out by \
the frontend for %%makearray_dynamic_uninit"
(Printlambda.array_kind kind)
| Punboxedfloatarray Unboxed_float32 ->
Lconst (Const_base (Const_float32 "0.0"))
| Punboxedfloatarray Unboxed_float64 ->
Lconst (Const_base (Const_float "0.0"))
| Punboxedintarray Unboxed_int32 ->
Lconst (Const_base (Const_int32 0l))
| Punboxedintarray Unboxed_int64 ->
Lconst (Const_base (Const_int64 0L))
| Punboxedintarray Unboxed_nativeint ->
Lconst (Const_base (Const_nativeint 0n))
| Punboxedvectorarray _ ->
fatal_error "SIMD is not supported in bytecode mode."
| Pgcignorableproductarray ignorables ->
let rec convert_ignorable
(ign : Lambda.ignorable_product_element_kind) =
match ign with
| Pint_ignorable -> Lconst (Const_base (Const_int 0))
| Punboxedfloat_ignorable Unboxed_float32 ->
Lconst (Const_base (Const_float32 "0.0"))
| Punboxedfloat_ignorable Unboxed_float64 ->
Lconst (Const_base (Const_float "0.0"))
| Punboxedint_ignorable Unboxed_int32 ->
Lconst (Const_base (Const_int32 0l))
| Punboxedint_ignorable Unboxed_int64 ->
Lconst (Const_base (Const_int64 0L))
| Punboxedint_ignorable Unboxed_nativeint ->
Lconst (Const_base (Const_nativeint 0n))
| Pproduct_ignorable ignorables ->
let fields = List.map convert_ignorable ignorables in
Lprim (Pmakeblock (0, Immutable, None, alloc_heap), fields,
loc)
in
convert_ignorable (Pproduct_ignorable ignorables)
in
comp_expr stack_info env
(Lprim (Pmakearray_dynamic (kind, locality, With_initializer),
[len; init], loc)) sz cont
| Lprim (Pmakearray_dynamic (_, _, Uninitialized), _, _loc) ->
Misc.fatal_error "Pmakearray_dynamic takes one arg when [Uninitialized]"
| Lprim (Pduparray (kind, mutability),
[Lprim (Pmakearray (kind',_,m),args,_)], loc) ->
assert (kind = kind');
Expand Down
71 changes: 68 additions & 3 deletions lambda/lambda.ml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ type field_read_semantics =
| Reads_agree
| Reads_vary

type has_initializer =
| With_initializer
| Uninitialized

include (struct

type locality_mode =
Expand Down Expand Up @@ -189,9 +193,12 @@ type primitive =
| Pbyteslength | Pbytesrefu | Pbytessetu | Pbytesrefs | Pbytessets
(* Array operations *)
| Pmakearray of array_kind * mutable_flag * locality_mode
| Pmakearray_dynamic of array_kind * locality_mode
| Pmakearray_dynamic of array_kind * locality_mode * has_initializer
| Pduparray of array_kind * mutable_flag
| Parrayblit of array_set_kind (* Kind of the dest array. *)
| Parrayblit of {
src_mutability : mutable_flag;
dst_array_set_kind : array_set_kind;
}
| Parraylength of array_kind
| Parrayrefu of array_ref_kind * array_index_kind * mutable_flag
| Parraysetu of array_set_kind * array_index_kind
Expand Down Expand Up @@ -944,6 +951,10 @@ let lfunction ~kind ~params ~return ~body ~attr ~loc ~mode ~ret_mode ~region =

let lambda_unit = Lconst const_unit

let of_bool = function
| true -> Lconst (const_int 1)
| false -> Lconst (const_int 0)

(* CR vlaviron: review the following cases *)
let non_null_value raw_kind =
Pvalue { raw_kind; nullable = Non_nullable }
Expand Down Expand Up @@ -1819,7 +1830,7 @@ let primitive_may_allocate : primitive -> locality_mode option = function
| Pstringlength | Pstringrefu | Pstringrefs
| Pbyteslength | Pbytesrefu | Pbytessetu | Pbytesrefs | Pbytessets -> None
| Pmakearray (_, _, m) -> Some m
| Pmakearray_dynamic (_, m) -> Some m
| Pmakearray_dynamic (_, m, _) -> Some m
| Pduparray _ -> Some alloc_heap
| Parraylength _ -> None
| Parrayblit _
Expand Down Expand Up @@ -2388,6 +2399,21 @@ let array_set_kind mode = function
| Pgcscannableproductarray kinds -> Pgcscannableproductarray_set (mode, kinds)
| Pgcignorableproductarray kinds -> Pgcignorableproductarray_set kinds

let array_ref_kind_of_array_set_kind (kind : array_set_kind) mode
: array_ref_kind =
match kind with
| Pintarray_set -> Pintarray_ref
| Punboxedfloatarray_set uf -> Punboxedfloatarray_ref uf
| Punboxedintarray_set ui -> Punboxedintarray_ref ui
| Punboxedvectorarray_set uv -> Punboxedvectorarray_ref uv
| Pgcscannableproductarray_set (_, scannables) ->
Pgcscannableproductarray_ref scannables
| Pgcignorableproductarray_set ignorables ->
Pgcignorableproductarray_ref ignorables
| Pgenarray_set _ -> Pgenarray_ref mode
| Paddrarray_set _ -> Paddrarray_ref
| Pfloatarray_set -> Pfloatarray_ref mode

let may_allocate_in_region lam =
(* loop_region raises, if the lambda might allocate in parent region *)
let rec loop_region lam =
Expand Down Expand Up @@ -2479,3 +2505,42 @@ let rec try_to_find_location lam =

let try_to_find_debuginfo lam =
Debuginfo.from_location (try_to_find_location lam)

let rec count_initializers_scannable
(scannable : scannable_product_element_kind) =
match scannable with
| Pint_scannable | Paddr_scannable -> 1
| Pproduct_scannable scannables ->
List.fold_left
(fun acc scannable -> acc + count_initializers_scannable scannable)
0 scannables

let rec count_initializers_ignorable
(ignorable : ignorable_product_element_kind) =
match ignorable with
| Pint_ignorable | Punboxedfloat_ignorable _ | Punboxedint_ignorable _ -> 1
| Pproduct_ignorable ignorables ->
List.fold_left
(fun acc ignorable -> acc + count_initializers_ignorable ignorable)
0 ignorables

let count_initializers_array_kind (lambda_array_kind : array_kind) =
match lambda_array_kind with
| Pgenarray | Paddrarray | Pintarray | Pfloatarray | Punboxedfloatarray _
| Punboxedintarray _ | Punboxedvectorarray _ -> 1
| Pgcscannableproductarray scannables ->
List.fold_left
(fun acc scannable -> acc + count_initializers_scannable scannable)
0 scannables
| Pgcignorableproductarray ignorables ->
List.fold_left
(fun acc ignorable -> acc + count_initializers_ignorable ignorable)
0 ignorables

let rec ignorable_product_element_kind_involves_int
(kind : ignorable_product_element_kind) =
match kind with
| Pint_ignorable -> true
| Punboxedfloat_ignorable _ | Punboxedint_ignorable _ -> false
| Pproduct_ignorable kinds ->
List.exists ignorable_product_element_kind_involves_int kinds
27 changes: 24 additions & 3 deletions lambda/lambda.mli
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ type field_read_semantics =
| Reads_agree
| Reads_vary

type has_initializer =
| With_initializer
| Uninitialized

(* Tail calls can close their enclosing region early *)
type region_close =
| Rc_normal (* do not close region, may TCO if in tail position *)
Expand Down Expand Up @@ -178,15 +182,21 @@ type primitive =
| Pbyteslength | Pbytesrefu | Pbytessetu | Pbytesrefs | Pbytessets
(* Array operations *)
| Pmakearray of array_kind * mutable_flag * locality_mode
| Pmakearray_dynamic of array_kind * locality_mode
| Pmakearray_dynamic of array_kind * locality_mode * has_initializer
(** For [Pmakearray_dynamic], if the array kind specifies an unboxed
product, the float array optimization will never apply. *)
| Pduparray of array_kind * mutable_flag
(** For [Pduparray], the argument must be an immutable array.
The arguments of [Pduparray] give the kind and mutability of the
array being *produced* by the duplication. *)
| Parrayblit of array_set_kind
| Parrayblit of {
src_mutability : mutable_flag;
dst_array_set_kind : array_set_kind;
}
(** For [Parrayblit], we record the [array_set_kind] of the destination
array. We check that the source array has the same shape, but do not
need to know anything about its locality. *)
need to know anything about its locality. We do however request the
mutability of the source array. *)
| Parraylength of array_kind
| Parrayrefu of array_ref_kind * array_index_kind * mutable_flag
| Parraysetu of array_set_kind * array_index_kind
Expand Down Expand Up @@ -914,6 +924,8 @@ val const_unit: structured_constant
val const_int : int -> structured_constant
val lambda_unit: lambda

val of_bool : bool -> lambda

val layout_unit : layout
val layout_int : layout
val layout_array : array_kind -> layout
Expand Down Expand Up @@ -1158,6 +1170,11 @@ val array_ref_kind : locality_mode -> array_kind -> array_ref_kind
(** The mode will be discarded if unnecessary for the given [array_kind] *)
val array_set_kind : modify_mode -> array_kind -> array_set_kind

(** Any mode information in the given [array_set_kind] is ignored. Any mode
in the return value always comes from the [locality_mode] parameter. *)
val array_ref_kind_of_array_set_kind
: array_set_kind -> locality_mode -> array_ref_kind

(* Returns true if the given lambda can allocate on the local stack *)
val may_allocate_in_region : lambda -> bool

Expand All @@ -1173,3 +1190,7 @@ val try_to_find_location : lambda -> scoped_location
val try_to_find_debuginfo : lambda -> Debuginfo.t

val primitive_can_raise : primitive -> bool

val count_initializers_array_kind : array_kind -> int
val ignorable_product_element_kind_involves_int :
ignorable_product_element_kind -> bool
12 changes: 9 additions & 3 deletions lambda/printlambda.ml
Original file line number Diff line number Diff line change
Expand Up @@ -668,14 +668,20 @@ let primitive ppf = function
| Pmakearray (k, Immutable_unique, mode) ->
fprintf ppf "make%sarray_unique[%s]" (locality_mode_if_local mode)
(array_kind k)
| Pmakearray_dynamic (k, mode) ->
fprintf ppf "make%sarray_any[%s]" (locality_mode_if_local mode)
| Pmakearray_dynamic (k, mode, has_init) ->
fprintf ppf "make%sarray_any[%s]%s" (locality_mode_if_local mode)
(array_kind k)
(match has_init with
| With_initializer -> ""
| Uninitialized -> "[uninit]")
| Pduparray (k, Mutable) -> fprintf ppf "duparray[%s]" (array_kind k)
| Pduparray (k, Immutable) -> fprintf ppf "duparray_imm[%s]" (array_kind k)
| Pduparray (k, Immutable_unique) ->
fprintf ppf "duparray_unique[%s]" (array_kind k)
| Parrayblit sk -> fprintf ppf "arrayblit[%a]" array_set_kind sk
| Parrayblit { src_mutability; dst_array_set_kind } ->
fprintf ppf "arrayblit[%s -> %a]"
(array_mut src_mutability)
array_set_kind dst_array_set_kind
| Parrayrefu (rk, idx, mut) -> fprintf ppf "%s.unsafe_get[%a indexed by %a]"
(array_mut mut)
array_ref_kind rk
Expand Down
1 change: 1 addition & 0 deletions lambda/printlambda.mli
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ val print_bigarray :
val zero_alloc_attribute : formatter -> zero_alloc_attribute -> unit
val locality_mode : formatter -> locality_mode -> unit
val array_kind : array_kind -> string
val array_set_kind : formatter -> array_set_kind -> unit

val tag_and_constructor_shape :
(formatter -> value_kind -> unit) ->
Expand Down
Loading

0 comments on commit c7f573f

Please sign in to comment.