Skip to content

Commit bfcbbf8

Browse files
authored
flambda-backend: Extend Pblock value kind to handle variants (#703)
1 parent b2cab95 commit bfcbbf8

16 files changed

+519
-149
lines changed

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

lambda/lambda.ml

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,10 @@ and float_comparison =
220220

221221
and value_kind =
222222
Pgenval | Pfloatval | Pboxedintval of boxed_integer | Pintval
223-
| Pblock of { tag : int; fields : value_kind list }
223+
| Pvariant of {
224+
consts : int list;
225+
non_consts : (int * value_kind list) list;
226+
}
224227
| Parrayval of array_kind
225228

226229
and block_shape =
@@ -273,11 +276,20 @@ let rec equal_value_kind x y =
273276
| Pboxedintval bi1, Pboxedintval bi2 -> equal_boxed_integer bi1 bi2
274277
| Pintval, Pintval -> true
275278
| Parrayval elt_kind1, Parrayval elt_kind2 -> elt_kind1 = elt_kind2
276-
| Pblock { tag = tag1; fields = fields1 },
277-
Pblock { tag = tag2; fields = fields2 } ->
278-
tag1 = tag2 && List.length fields1 = List.length fields2 &&
279-
List.for_all2 equal_value_kind fields1 fields2
280-
| (Pgenval | Pfloatval | Pboxedintval _ | Pintval | Pblock _
279+
| Pvariant { consts = consts1; non_consts = non_consts1; },
280+
Pvariant { consts = consts2; non_consts = non_consts2; } ->
281+
let consts1 = List.sort Int.compare consts1 in
282+
let consts2 = List.sort Int.compare consts2 in
283+
let compare_by_tag (tag1, _) (tag2, _) = Int.compare tag1 tag2 in
284+
let non_consts1 = List.sort compare_by_tag non_consts1 in
285+
let non_consts2 = List.sort compare_by_tag non_consts2 in
286+
List.equal Int.equal consts1 consts2
287+
&& List.equal (fun (tag1, fields1) (tag2, fields2) ->
288+
Int.equal tag1 tag2
289+
&& List.length fields1 = List.length fields2
290+
&& List.for_all2 equal_value_kind fields1 fields2)
291+
non_consts1 non_consts2
292+
| (Pgenval | Pfloatval | Pboxedintval _ | Pintval | Pvariant _
281293
| Parrayval _), _ -> false
282294

283295

lambda/lambda.mli

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,13 @@ and array_kind =
193193

194194
and value_kind =
195195
Pgenval | Pfloatval | Pboxedintval of boxed_integer | Pintval
196-
| Pblock of { tag : int; fields : value_kind list }
196+
| Pvariant of {
197+
consts : int list;
198+
non_consts : (int * value_kind list) list;
199+
(** [non_consts] must be non-empty. For constant variants [Pintval]
200+
must be used. This causes a small loss of precision but it is not
201+
expected to be significant. *)
202+
}
197203
| Parrayval of array_kind
198204

199205
and block_shape =

lambda/printlambda.ml

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -63,27 +63,37 @@ let boxed_integer_name = function
6363
| Pint32 -> "int32"
6464
| Pint64 -> "int64"
6565

66+
let variant_kind print_contents ppf ~consts ~non_consts =
67+
fprintf ppf "@[<hov 1>[(consts (%a))@ (non_consts (%a))]@]"
68+
(Format.pp_print_list ~pp_sep:Format.pp_print_space Format.pp_print_int)
69+
consts
70+
(Format.pp_print_list ~pp_sep:Format.pp_print_space
71+
(fun ppf (tag, fields) ->
72+
fprintf ppf "@[<hov 1>[%d:@ %a]@]"
73+
tag
74+
(Format.pp_print_list ~pp_sep:(fun ppf () -> fprintf ppf ",@ ")
75+
print_contents)
76+
fields
77+
))
78+
non_consts
79+
6680
let rec value_kind ppf = function
6781
| Pgenval -> ()
6882
| Pintval -> fprintf ppf "[int]"
6983
| Pfloatval -> fprintf ppf "[float]"
7084
| Parrayval elt_kind -> fprintf ppf "[%sarray]" (array_kind elt_kind)
7185
| Pboxedintval bi -> fprintf ppf "[%s]" (boxed_integer_name bi)
72-
| Pblock { tag; fields } ->
73-
fprintf ppf "[%d: %a]" tag
74-
(Format.pp_print_list ~pp_sep:(fun ppf () -> fprintf ppf ",@ ")
75-
value_kind') fields
86+
| Pvariant { consts; non_consts; } ->
87+
variant_kind value_kind' ppf ~consts ~non_consts
7688

7789
and value_kind' ppf = function
7890
| Pgenval -> fprintf ppf "*"
7991
| Pintval -> fprintf ppf "[int]"
8092
| Pfloatval -> fprintf ppf "[float]"
8193
| Parrayval elt_kind -> fprintf ppf "[%sarray]" (array_kind elt_kind)
8294
| Pboxedintval bi -> fprintf ppf "[%s]" (boxed_integer_name bi)
83-
| Pblock { tag; fields } ->
84-
fprintf ppf "[%d: %a]" tag
85-
(Format.pp_print_list ~pp_sep:(fun ppf () -> fprintf ppf ",@ ")
86-
value_kind') fields
95+
| Pvariant { consts; non_consts; } ->
96+
variant_kind value_kind' ppf ~consts ~non_consts
8797

8898
let return_kind ppf (mode, kind) =
8999
let smode = alloc_mode mode in
@@ -95,21 +105,27 @@ let return_kind ppf (mode, kind) =
95105
| Parrayval elt_kind ->
96106
fprintf ppf ": %s%sarray@ " smode (array_kind elt_kind)
97107
| Pboxedintval bi -> fprintf ppf ": %s%s@ " smode (boxed_integer_name bi)
98-
| Pblock { tag; fields } ->
99-
fprintf ppf ": %s[%d: %a]@ " smode tag
100-
(Format.pp_print_list ~pp_sep:(fun ppf () -> fprintf ppf ",@ ")
101-
value_kind') fields
108+
| Pvariant { consts; non_consts; } ->
109+
variant_kind value_kind' ppf ~consts ~non_consts
102110

103111
let field_kind ppf = function
104112
| Pgenval -> pp_print_string ppf "*"
105113
| Pintval -> pp_print_string ppf "int"
106114
| Pfloatval -> pp_print_string ppf "float"
107115
| Parrayval elt_kind -> fprintf ppf "%s-array" (array_kind elt_kind)
108116
| Pboxedintval bi -> pp_print_string ppf (boxed_integer_name bi)
109-
| Pblock { tag; fields } ->
110-
fprintf ppf "[%d: %a]" tag
111-
(Format.pp_print_list ~pp_sep:(fun ppf () -> fprintf ppf ",@ ")
112-
value_kind') fields
117+
| Pvariant { consts; non_consts; } ->
118+
fprintf ppf "@[<hov 1>[(consts (%a))@ (non_consts (%a))]@]"
119+
(Format.pp_print_list ~pp_sep:Format.pp_print_space Format.pp_print_int)
120+
consts
121+
(Format.pp_print_list ~pp_sep:Format.pp_print_space
122+
(fun ppf (tag, fields) ->
123+
fprintf ppf "@[<hov 1>[%d:@ %a]@]"
124+
tag
125+
(Format.pp_print_list ~pp_sep:(fun ppf () -> fprintf ppf ",@ ")
126+
value_kind') fields
127+
))
128+
non_consts
113129

114130
let alloc_kind = function
115131
| Alloc_heap -> ""

lambda/printlambda.mli

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ val lambda: formatter -> lambda -> unit
2424
val program: formatter -> program -> unit
2525
val primitive: formatter -> primitive -> unit
2626
val name_of_primitive : primitive -> string
27+
val variant_kind : (formatter -> value_kind -> unit) ->
28+
formatter -> consts:int list -> non_consts:(int * value_kind list) list ->
29+
unit
2730
val value_kind : formatter -> value_kind -> unit
2831
val value_kind' : formatter -> value_kind -> unit
2932
val block_shape : formatter -> value_kind list option -> unit

middle_end/clambda_primitives.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ 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 { tag : int; fields : value_kind list }
139139
| Parrayval of array_kind
140140

141141
and block_shape = Lambda.block_shape

middle_end/clambda_primitives.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ 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 { tag : int; fields : value_kind list }
142142
| Parrayval of array_kind
143143

144144
and block_shape = Lambda.block_shape

middle_end/printclambda.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ let value_kind =
3737
| Pboxedintval Pnativeint -> ":nativeint"
3838
| Pboxedintval Pint32 -> ":int32"
3939
| Pboxedintval Pint64 -> ":int64"
40-
| Pblock { tag; fields } ->
40+
| Pvariant { tag; fields } ->
4141
asprintf ":[%d: %a]" tag
4242
(Format.pp_print_list ~pp_sep:(fun ppf () -> fprintf ppf ",@ ")
4343
Printlambda.value_kind') fields

testsuite/tests/basic-modules/anonymous.ocamlc.reference

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,25 @@
11
(setglobal Anonymous!
2-
(seq (ignore (let (x =[0: [int], [int]] [0: 13 37]) (makeblock 0 x)))
2+
(seq
3+
(ignore
4+
(let (x =[(consts ()) (non_consts ([0: [int], [int]]))] [0: 13 37])
5+
(makeblock 0 x)))
36
(let
47
(A =
58
(apply (field 0 (global CamlinternalMod!)) [0: "anonymous.ml" 25 6]
69
[0: [0]])
710
B =
811
(apply (field 0 (global CamlinternalMod!)) [0: "anonymous.ml" 35 6]
912
[0: [0]]))
10-
(seq (ignore (let (x =[0: [int], [int]] [0: 4 2]) (makeblock 0 x)))
13+
(seq
14+
(ignore
15+
(let (x =[(consts ()) (non_consts ([0: [int], [int]]))] [0: 4 2])
16+
(makeblock 0 x)))
1117
(apply (field 1 (global CamlinternalMod!)) [0: [0]] A
1218
(module-defn(A) Anonymous anonymous.ml(23):567-608 A))
1319
(apply (field 1 (global CamlinternalMod!)) [0: [0]] B
1420
(module-defn(B) Anonymous anonymous.ml(33):703-773
15-
(let (x =[0: *, *] [0: "foo" "bar"]) (makeblock 0))))
21+
(let (x =[(consts ()) (non_consts ([0: *, *]))] [0: "foo" "bar"])
22+
(makeblock 0))))
1623
(let (f = (function param : int 0) s = (makemutable 0 ""))
1724
(seq
1825
(ignore

testsuite/tests/basic-modules/anonymous.ocamlopt.flambda.reference

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
1-
(seq (ignore (let (x =[0: [int], [int]] [0: 13 37]) (makeblock 0 x)))
1+
(seq
2+
(ignore
3+
(let (x =[(consts ()) (non_consts ([0: [int], [int]]))] [0: 13 37])
4+
(makeblock 0 x)))
25
(let
36
(A =
47
(apply (field 0 (global CamlinternalMod!)) [0: "anonymous.ml" 25 6]
58
[0: [0]])
69
B =
710
(apply (field 0 (global CamlinternalMod!)) [0: "anonymous.ml" 35 6]
811
[0: [0]]))
9-
(seq (ignore (let (x =[0: [int], [int]] [0: 4 2]) (makeblock 0 x)))
12+
(seq
13+
(ignore
14+
(let (x =[(consts ()) (non_consts ([0: [int], [int]]))] [0: 4 2])
15+
(makeblock 0 x)))
1016
(apply (field 1 (global CamlinternalMod!)) [0: [0]] A
1117
(module-defn(A) Anonymous anonymous.ml(23):567-608 A))
1218
(apply (field 1 (global CamlinternalMod!)) [0: [0]] B
1319
(module-defn(B) Anonymous anonymous.ml(33):703-773
14-
(let (x =[0: *, *] [0: "foo" "bar"]) (makeblock 0))))
20+
(let (x =[(consts ()) (non_consts ([0: *, *]))] [0: "foo" "bar"])
21+
(makeblock 0))))
1522
(let (f = (function param : int 0) s = (makemutable 0 ""))
1623
(seq
1724
(ignore

testsuite/tests/basic-modules/anonymous.ocamlopt.reference

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
1-
(seq (ignore (let (x =[0: [int], [int]] [0: 13 37]) (makeblock 0 x)))
1+
(seq
2+
(ignore
3+
(let (x =[(consts ()) (non_consts ([0: [int], [int]]))] [0: 13 37])
4+
(makeblock 0 x)))
25
(let
36
(A =
47
(apply (field 0 (global CamlinternalMod!)) [0: "anonymous.ml" 25 6]
58
[0: [0]])
69
B =
710
(apply (field 0 (global CamlinternalMod!)) [0: "anonymous.ml" 35 6]
811
[0: [0]]))
9-
(seq (ignore (let (x =[0: [int], [int]] [0: 4 2]) (makeblock 0 x)))
12+
(seq
13+
(ignore
14+
(let (x =[(consts ()) (non_consts ([0: [int], [int]]))] [0: 4 2])
15+
(makeblock 0 x)))
1016
(apply (field 1 (global CamlinternalMod!)) [0: [0]] A A)
1117
(apply (field 1 (global CamlinternalMod!)) [0: [0]] B
12-
(let (x =[0: *, *] [0: "foo" "bar"]) (makeblock 0)))
18+
(let (x =[(consts ()) (non_consts ([0: *, *]))] [0: "foo" "bar"])
19+
(makeblock 0)))
1320
(setfield_ptr(root-init) 0 (global Anonymous!) A)
1421
(setfield_ptr(root-init) 1 (global Anonymous!) B)
1522
(let (f = (function param : int 0))

testsuite/tests/basic/patmatch_for_multiple.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ match (3, 2, 1) with
5555
*match*/283 =a (field 1 *match*/279))
5656
(exit 5 *match*/279)))))
5757
with (6) 0)
58-
with (5 x/274[0: [int], [int], [int]]) (seq (ignore x/274) 1)))
58+
with (5 x/274[(consts ()) (non_consts ([0: [int], [int], [int]]))])
59+
(seq (ignore x/274) 1)))
5960
- : bool = false
6061
|}];;

testsuite/tests/basic/patmatch_split_no_or.ml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ let last_is_anys = function
1616
[%%expect{|
1717
(let
1818
(last_is_anys/10 =
19-
(function param/12[0: [int], [int]] : int
19+
(function param/12[(consts ()) (non_consts ([0: [int], [int]]))] : int
2020
(catch
2121
(if (field 0 param/12) (if (field 1 param/12) (exit 1) 1)
2222
(if (field 1 param/12) (exit 1) 2))
@@ -33,7 +33,7 @@ let last_is_vars = function
3333
[%%expect{|
3434
(let
3535
(last_is_vars/17 =
36-
(function param/21[0: [int], [int]] : int
36+
(function param/21[(consts ()) (non_consts ([0: [int], [int]]))] : int
3737
(catch
3838
(if (field 0 param/21) (if (field 1 param/21) (exit 3) 1)
3939
(if (field 1 param/21) (exit 3) 2))
@@ -75,7 +75,8 @@ let f = function
7575
B/26 = (apply (field 0 (global Toploop!)) "B/26")
7676
A/25 = (apply (field 0 (global Toploop!)) "A/25")
7777
f/28 =
78-
(function param/30[0: *, [int], [int]] : int
78+
(function param/30[(consts ()) (non_consts ([0: *, [int], [int]]))]
79+
: int
7980
(let (*match*/31 =a (field 0 param/30))
8081
(catch
8182
(if (== *match*/31 A/25) (if (field 1 param/30) 1 (exit 8))

0 commit comments

Comments
 (0)