Skip to content

Commit fb4a897

Browse files
authored
Extend Pblock value kind to handle variants (#703)
1 parent 4d2f22b commit fb4a897

25 files changed

+657
-215
lines changed

backend/cmmgen.ml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ let join_unboxed_number_kind ~strict k1 k2 =
339339

340340
let is_strict = function
341341
| Pfloatval | Pboxedintval _ -> false
342-
| Pintval | Pgenval | Pblock _ | Parrayval _ -> true
342+
| Pintval | Pgenval | Pvariant _ | Parrayval _ -> true
343343

344344
let rec is_unboxed_number_cmm = function
345345
| Cop(Calloc mode, [Cconst_natint (hdr, _); _], dbg)
@@ -386,10 +386,10 @@ let rec is_unboxed_number_cmm = function
386386
| Cassign _
387387
| Ctuple _
388388
| Cop _ -> No_unboxing
389-
| Cifthenelse (_, _, _, _, _, _, Vval (Pintval | Pblock _))
390-
| Cswitch (_, _, _, _, Vval (Pintval | Pblock _))
391-
| Ctrywith (_, _, _, _, _, Vval (Pintval | Pblock _))
392-
| Ccatch (_, _, _, Vval (Pintval | Pblock _)) ->
389+
| Cifthenelse (_, _, _, _, _, _, Vval (Pintval | Pvariant _))
390+
| Cswitch (_, _, _, _, Vval (Pintval | Pvariant _))
391+
| Ctrywith (_, _, _, _, _, Vval (Pintval | Pvariant _))
392+
| Ccatch (_, _, _, Vval (Pintval | Pvariant _)) ->
393393
No_unboxing
394394
| Cifthenelse (_, _, a, _, b, _, Vval kind) ->
395395
join_unboxed_number_kind ~strict:(is_strict kind)

middle_end/clambda_primitives.ml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,10 @@ and array_kind = Lambda.array_kind =
135135
and value_kind = Lambda.value_kind =
136136
(* CR mshinwell: Pfloatval should be renamed to Pboxedfloatval *)
137137
Pgenval | Pfloatval | Pboxedintval of boxed_integer | Pintval
138-
| Pblock of { tag : int; fields : value_kind list }
138+
| Pvariant of {
139+
consts : int list;
140+
non_consts : (int * value_kind list) list;
141+
}
139142
| Parrayval of array_kind
140143

141144
and block_shape = Lambda.block_shape

middle_end/clambda_primitives.mli

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,10 @@ and array_kind = Lambda.array_kind =
138138
and value_kind = Lambda.value_kind =
139139
(* CR mshinwell: Pfloatval should be renamed to Pboxedfloatval *)
140140
Pgenval | Pfloatval | Pboxedintval of boxed_integer | Pintval
141-
| Pblock of { tag : int; fields : value_kind list }
141+
| Pvariant of {
142+
consts : int list;
143+
non_consts : (int * value_kind list) list;
144+
}
142145
| Parrayval of array_kind
143146

144147
and block_shape = Lambda.block_shape

middle_end/flambda2/from_lambda/lambda_to_flambda_primitives.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ let convert_block_of_values_field (value_kind : L.value_kind) :
3030
| Pboxedintval Pint64 -> Boxed_int64
3131
| Pboxedintval Pnativeint -> Boxed_nativeint
3232
| Pintval -> Immediate
33-
| Pblock _ | Parrayval _ -> Any_value
33+
| Pvariant _ | Parrayval _ -> Any_value
3434

3535
let convert_integer_comparison_prim (comp : L.integer_comparison) :
3636
P.binary_primitive =

middle_end/flambda2/kinds/flambda_kind.ml

Lines changed: 79 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -276,9 +276,9 @@ module With_subkind = struct
276276
| Boxed_int64
277277
| Boxed_nativeint
278278
| Tagged_immediate
279-
| Block of
280-
{ tag : Tag.t;
281-
fields : t list
279+
| Variant of
280+
{ consts : Targetint_31_63.Set.t;
281+
non_consts : t list Tag.Scannable.Map.t
282282
}
283283
| Float_block of { num_fields : int }
284284
| Float_array
@@ -300,19 +300,34 @@ module With_subkind = struct
300300
| Value_array, Value_array
301301
| Generic_array, Generic_array ->
302302
true
303-
| ( Block { tag = t1; fields = fields1 },
304-
Block { tag = t2; fields = fields2 } ) ->
305-
Tag.equal t1 t2
306-
&& List.length fields1 = List.length fields2
307-
&& List.for_all2
308-
(fun d when_used_at -> compatible d ~when_used_at)
309-
fields1 fields2
303+
| ( Variant { consts = consts1; non_consts = non_consts1 },
304+
Variant { consts = consts2; non_consts = non_consts2 } ) ->
305+
if not (Targetint_31_63.Set.equal consts1 consts2)
306+
then false
307+
else
308+
let tags1 = Tag.Scannable.Map.keys non_consts1 in
309+
let tags2 = Tag.Scannable.Map.keys non_consts2 in
310+
if not (Tag.Scannable.Set.equal tags1 tags2)
311+
then false
312+
else
313+
let field_lists1 = Tag.Scannable.Map.data non_consts1 in
314+
let field_lists2 = Tag.Scannable.Map.data non_consts2 in
315+
assert (List.compare_lengths field_lists1 field_lists2 = 0);
316+
List.for_all2
317+
(fun fields1 fields2 ->
318+
if List.compare_lengths fields1 fields2 <> 0
319+
then false
320+
else
321+
List.for_all2
322+
(fun d when_used_at -> compatible d ~when_used_at)
323+
fields1 fields2)
324+
field_lists1 field_lists2
310325
| ( Float_block { num_fields = num_fields1 },
311326
Float_block { num_fields = num_fields2 } ) ->
312327
num_fields1 = num_fields2
313328
(* Subkinds of [Value] may always be used at [Value] (but not the
314329
converse): *)
315-
| ( ( Block _ | Float_block _ | Float_array | Immediate_array
330+
| ( ( Variant _ | Float_block _ | Float_array | Immediate_array
316331
| Value_array | Generic_array | Boxed_float | Boxed_int32
317332
| Boxed_int64 | Boxed_nativeint | Tagged_immediate ),
318333
Anything ) ->
@@ -324,7 +339,7 @@ module With_subkind = struct
324339
true
325340
(* All other combinations are incompatible: *)
326341
| ( ( Anything | Boxed_float | Boxed_int32 | Boxed_int64 | Boxed_nativeint
327-
| Tagged_immediate | Block _ | Float_block _ | Float_array
342+
| Tagged_immediate | Variant _ | Float_block _ | Float_array
328343
| Immediate_array | Value_array | Generic_array ),
329344
_ ) ->
330345
false
@@ -335,7 +350,7 @@ module With_subkind = struct
335350
let rec print ppf t =
336351
let colour = Flambda_colours.subkind () in
337352
match t with
338-
| Anything -> ()
353+
| Anything -> Format.fprintf ppf "*"
339354
| Tagged_immediate ->
340355
Format.fprintf ppf "@<0>%s=tagged_@<1>\u{2115}@<1>\u{1d55a}@<0>%s"
341356
colour
@@ -356,10 +371,15 @@ module With_subkind = struct
356371
Format.fprintf ppf "@<0>%s=boxed_@<1>\u{2115}@<1>\u{2115}@<0>%s"
357372
colour
358373
(Flambda_colours.normal ())
359-
| Block { tag; fields } ->
360-
Format.fprintf ppf "@<0>%s=Block{%a: %a}@<0>%s" colour Tag.print tag
361-
(Format.pp_print_list ~pp_sep:Format.pp_print_space print)
362-
fields
374+
| Variant { consts; non_consts } ->
375+
Format.fprintf ppf
376+
"@<0>%s=Variant((consts (%a))@ (non_consts (%a)))@<0>%s" colour
377+
Targetint_31_63.Set.print consts
378+
(Tag.Scannable.Map.print (fun ppf fields ->
379+
Format.fprintf ppf "[%a]"
380+
(Format.pp_print_list ~pp_sep:Format.pp_print_space print)
381+
fields))
382+
non_consts
363383
(Flambda_colours.normal ())
364384
| Float_block { num_fields } ->
365385
Format.fprintf ppf "@<0>%s=Float_block(%d)@<0>%s" colour num_fields
@@ -399,7 +419,7 @@ module With_subkind = struct
399419
match subkind with
400420
| Anything -> ()
401421
| Boxed_float | Boxed_int32 | Boxed_int64 | Boxed_nativeint
402-
| Tagged_immediate | Block _ | Float_block _ | Float_array
422+
| Tagged_immediate | Variant _ | Float_block _ | Float_array
403423
| Immediate_array | Value_array | Generic_array ->
404424
Misc.fatal_errorf "Subkind %a is not valid for kind %a" Subkind.print
405425
subkind print kind));
@@ -448,7 +468,14 @@ module With_subkind = struct
448468
"Block with fields of non-Value kind (use \
449469
[Flambda_kind.With_subkind.float_block] for float records)";
450470
let fields = List.map (fun t -> t.subkind) fields in
451-
create value (Block { tag; fields })
471+
match Tag.Scannable.of_tag tag with
472+
| Some tag ->
473+
create value
474+
(Variant
475+
{ consts = Targetint_31_63.Set.empty;
476+
non_consts = Tag.Scannable.Map.singleton tag fields
477+
})
478+
| None -> Misc.fatal_errorf "Tag %a is not scannable" Tag.print tag
452479

453480
let float_block ~num_fields = create value (Float_block { num_fields })
454481

@@ -468,12 +495,34 @@ module With_subkind = struct
468495
| Pboxedintval Pint64 -> boxed_int64
469496
| Pboxedintval Pnativeint -> boxed_nativeint
470497
| Pintval -> tagged_immediate
471-
| Pblock { tag; fields } ->
472-
(* If we have [Obj.double_array_tag] here, this is always an all-float
473-
block, not an array. *)
474-
if tag = Obj.double_array_tag
475-
then float_block ~num_fields:(List.length fields)
476-
else block (Tag.create_exn tag) (List.map from_lambda fields)
498+
| Pvariant { consts; non_consts } -> (
499+
match consts, non_consts with
500+
| [], [] -> Misc.fatal_error "[Pvariant] with no constructors at all"
501+
| [], [(tag, fields)] when tag = Obj.double_array_tag ->
502+
(* If we have [Obj.double_array_tag] here, this is always an all-float
503+
block, not an array. *)
504+
float_block ~num_fields:(List.length fields)
505+
| [], _ :: _ | _ :: _, [] | _ :: _, _ :: _ ->
506+
let consts =
507+
Targetint_31_63.Set.of_list
508+
(List.map
509+
(fun const ->
510+
Targetint_31_63.int (Targetint_31_63.Imm.of_int const))
511+
consts)
512+
in
513+
let non_consts =
514+
List.fold_left
515+
(fun non_consts (tag, fields) ->
516+
match Tag.Scannable.create tag with
517+
| Some tag ->
518+
Tag.Scannable.Map.add tag
519+
(List.map (fun vk -> subkind (from_lambda vk)) fields)
520+
non_consts
521+
| None ->
522+
Misc.fatal_errorf "Non-scannable tag %d in [Pvariant]" tag)
523+
Tag.Scannable.Map.empty non_consts
524+
in
525+
create value (Variant { consts; non_consts }))
477526
| Parrayval Pfloatarray -> float_array
478527
| Parrayval Pintarray -> immediate_array
479528
| Parrayval Paddrarray -> value_array
@@ -489,7 +538,7 @@ module With_subkind = struct
489538
Format.fprintf ppf "@[%a%a@]" print kind Subkind.print subkind
490539
| ( (Naked_number _ | Region | Rec_info),
491540
( Boxed_float | Boxed_int32 | Boxed_int64 | Boxed_nativeint
492-
| Tagged_immediate | Block _ | Float_block _ | Float_array
541+
| Tagged_immediate | Variant _ | Float_block _ | Float_array
493542
| Immediate_array | Value_array | Generic_array ) ) ->
494543
assert false
495544
(* see [create] *)
@@ -511,7 +560,9 @@ module With_subkind = struct
511560
match t.subkind with
512561
| Anything -> false
513562
| Boxed_float | Boxed_int32 | Boxed_int64 | Boxed_nativeint
514-
| Tagged_immediate | Block _ | Float_block _ | Float_array | Immediate_array
515-
| Value_array | Generic_array ->
563+
| Tagged_immediate | Variant _ | Float_block _ | Float_array
564+
| Immediate_array | Value_array | Generic_array ->
516565
true
566+
567+
let erase_subkind t = { t with subkind = Anything }
517568
end

middle_end/flambda2/kinds/flambda_kind.mli

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,9 @@ module With_subkind : sig
131131
| Boxed_int64
132132
| Boxed_nativeint
133133
| Tagged_immediate
134-
| Block of
135-
{ tag : Tag.t;
136-
fields : t list
134+
| Variant of
135+
{ consts : Targetint_31_63.Set.t;
136+
non_consts : t list Tag.Scannable.Map.t
137137
}
138138
| Float_block of { num_fields : int }
139139
| Float_array
@@ -198,5 +198,7 @@ module With_subkind : sig
198198

199199
val compatible : t -> when_used_at:t -> bool
200200

201+
val erase_subkind : t -> t
202+
201203
include Container_types.S with type t := t
202204
end

middle_end/flambda2/parser/print_fexpr.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ let kind_with_subkind ppf (k : kind_with_subkind) =
142142
| Value -> (
143143
match Flambda_kind.With_subkind.subkind k with
144144
| Anything -> str "val"
145-
| Block _ -> str "block" (* CR mshinwell: improve this *)
145+
| Variant _ -> str "variant" (* CR mshinwell: improve this *)
146146
| Float_block _ -> str "float_block"
147147
| Boxed_float -> str "float boxed"
148148
| Boxed_int32 -> str "int32 boxed"

middle_end/flambda2/types/grammar/more_type_creators.ml

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -315,16 +315,19 @@ let rec unknown_with_subkind (kind : Flambda_kind.With_subkind.t) =
315315
| Boxed_int64 -> any_boxed_int64
316316
| Boxed_nativeint -> any_boxed_nativeint
317317
| Tagged_immediate -> any_tagged_immediate
318-
| Block { tag; fields } ->
319-
assert (not (Tag.equal tag Tag.double_array_tag));
320-
immutable_block ~is_unique:false tag ~field_kind:Flambda_kind.value
321-
~fields:
322-
(List.map
323-
(fun subkind ->
324-
unknown_with_subkind
325-
(Flambda_kind.With_subkind.create Flambda_kind.value subkind))
326-
fields)
327-
Unknown
318+
| Variant { consts; non_consts } ->
319+
let const_ctors = these_naked_immediates consts in
320+
let non_const_ctors =
321+
Tag.Scannable.Map.map
322+
(fun fields ->
323+
List.map
324+
(fun subkind ->
325+
unknown_with_subkind
326+
(Flambda_kind.With_subkind.create Flambda_kind.value subkind))
327+
fields)
328+
non_consts
329+
in
330+
variant ~const_ctors ~non_const_ctors Unknown
328331
| Float_block { num_fields } ->
329332
immutable_block ~is_unique:false Tag.double_array_tag
330333
~field_kind:Flambda_kind.naked_float

middle_end/printclambda.ml

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,33 @@ let mutable_flag = function
2424
| Lambda.Mutable-> "[mut]"
2525
| Lambda.Immutable | Lambda.Immutable_unique -> ""
2626

27-
let value_kind =
27+
let rec value_kind0 ppf kind =
2828
let open Lambda in
29-
function
30-
| Pgenval -> ""
31-
| Pintval -> ":int"
32-
| Pfloatval -> ":float"
33-
| Parrayval Pgenarray -> ":genarray"
34-
| Parrayval Pintarray -> ":intarray"
35-
| Parrayval Pfloatarray -> ":floatarray"
36-
| Parrayval Paddrarray -> ":addrarray"
37-
| Pboxedintval Pnativeint -> ":nativeint"
38-
| Pboxedintval Pint32 -> ":int32"
39-
| Pboxedintval Pint64 -> ":int64"
40-
| Pblock { tag; fields } ->
41-
asprintf ":[%d: %a]" tag
42-
(Format.pp_print_list ~pp_sep:(fun ppf () -> fprintf ppf ",@ ")
43-
Printlambda.value_kind') fields
29+
match kind with
30+
| Pgenval -> Format.pp_print_string ppf ""
31+
| Pintval -> Format.pp_print_string ppf ":int"
32+
| Pfloatval -> Format.pp_print_string ppf ":float"
33+
| Parrayval Pgenarray -> Format.pp_print_string ppf ":genarray"
34+
| Parrayval Pintarray -> Format.pp_print_string ppf ":intarray"
35+
| Parrayval Pfloatarray -> Format.pp_print_string ppf ":floatarray"
36+
| Parrayval Paddrarray -> Format.pp_print_string ppf ":addrarray"
37+
| Pboxedintval Pnativeint -> Format.pp_print_string ppf ":nativeint"
38+
| Pboxedintval Pint32 -> Format.pp_print_string ppf ":int32"
39+
| Pboxedintval Pint64 -> Format.pp_print_string ppf ":int64"
40+
| Pvariant { consts; non_consts } ->
41+
Format.fprintf ppf "@[<hov 1>[(consts (%a))@ (non_consts (%a))]@]"
42+
(Format.pp_print_list ~pp_sep:Format.pp_print_space Format.pp_print_int)
43+
consts
44+
(Format.pp_print_list ~pp_sep:Format.pp_print_space
45+
(fun ppf (tag, fields) ->
46+
fprintf ppf "@[<hov 1>[%d:@ %a]@]" tag
47+
(Format.pp_print_list
48+
~pp_sep:(fun ppf () -> fprintf ppf ",@ ")
49+
value_kind0)
50+
fields))
51+
non_consts
52+
53+
let value_kind kind = Format.asprintf "%a" value_kind0 kind
4454

4555
let rec structured_constant ppf = function
4656
| Uconst_float x -> fprintf ppf "%F" x

ocaml/asmcomp/cmmgen.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,7 @@ and transl_catch env nfail ids body handler dbg =
711711
let strict =
712712
match kind with
713713
| Pfloatval | Pboxedintval _ -> false
714-
| Pintval | Pgenval | Pblock _ | Parrayval _ -> true
714+
| Pintval | Pgenval | Pvariant _ | Parrayval _ -> true
715715
in
716716
u := join_unboxed_number_kind ~strict !u
717717
(is_unboxed_number_cmm ~strict c)
@@ -1179,7 +1179,7 @@ and transl_let env str kind id exp transl_body =
11791179
we do it only if this indeed allows us to get rid of
11801180
some allocations in the bound expression. *)
11811181
is_unboxed_number_cmm ~strict:false cexp
1182-
| _, (Pgenval | Pblock _ | Parrayval _) ->
1182+
| _, (Pgenval | Pvariant _ | Parrayval _) ->
11831183
(* Here we don't know statically that the bound expression
11841184
evaluates to an unboxable number type. We need to be stricter
11851185
and ensure that all possible branches in the expression

0 commit comments

Comments
 (0)