Skip to content

Commit 9d3c1c1

Browse files
authored
Ltail for lambda and use in dissect_letrec (#1313)
1 parent 97dc31d commit 9d3c1c1

File tree

9 files changed

+97
-71
lines changed

9 files changed

+97
-71
lines changed

middle_end/closure/closure.ml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -987,6 +987,10 @@ let close_approx_var { fenv; cenv } id =
987987
let close_var env id =
988988
let (ulam, _app) = close_approx_var env id in ulam
989989

990+
let compute_expr_layout kinds lambda =
991+
let find_kind id = Ident.Map.find_opt id kinds in
992+
compute_expr_layout find_kind lambda
993+
990994
let rec close ({ backend; fenv; cenv ; mutable_vars; kinds; catch_env } as env) lam =
991995
let module B = (val backend : Backend_intf.S) in
992996
match lam with
@@ -1142,7 +1146,7 @@ let rec close ({ backend; fenv; cenv ; mutable_vars; kinds; catch_env } as env)
11421146
_approx_res)), uargs)
11431147
when nargs > List.length params_layout ->
11441148
let nparams = List.length params_layout in
1145-
let args_kinds = List.map (Lambda.compute_expr_layout kinds) args in
1149+
let args_kinds = List.map (compute_expr_layout kinds) args in
11461150
let args = List.map (fun arg -> V.create_local "arg", arg) uargs in
11471151
(* CR mshinwell: Edit when Lapply has kinds *)
11481152
let kinds =
@@ -1189,14 +1193,14 @@ let rec close ({ backend; fenv; cenv ; mutable_vars; kinds; catch_env } as env)
11891193
warning_if_forced_inlined ~loc ~attribute "Unknown function";
11901194
fail_if_probe ~probe "Unknown function";
11911195
(Ugeneric_apply(ufunct, uargs,
1192-
List.map (Lambda.compute_expr_layout kinds) args,
1196+
List.map (compute_expr_layout kinds) args,
11931197
ap_result_layout, (pos, mode), dbg), Value_unknown)
11941198
end
11951199
| Lsend(kind, met, obj, args, pos, mode, loc, result_layout) ->
11961200
let (umet, _) = close env met in
11971201
let (uobj, _) = close env obj in
11981202
let dbg = Debuginfo.from_location loc in
1199-
let args_layout = List.map (Lambda.compute_expr_layout kinds) args in
1203+
let args_layout = List.map (compute_expr_layout kinds) args in
12001204
(Usend(kind, umet, uobj, close_list env args, args_layout, result_layout, (pos,mode), dbg),
12011205
Value_unknown)
12021206
| Llet(str, kind, id, lam, body) ->

middle_end/flambda2/from_lambda/dissect_letrec.ml

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ let rec prepare_letrec (recursive_set : Ident.Set.t)
542542
Printlambda.lambda lam
543543
[@@ocaml.warning "-fragile-match"]
544544

545-
let dissect_letrec ~bindings ~body =
545+
let dissect_letrec ~bindings ~body ~free_vars_kind =
546546
let letbound = Ident.Set.of_list (List.map fst bindings) in
547547
let letrec =
548548
List.fold_right
@@ -575,19 +575,7 @@ let dissect_letrec ~bindings ~body =
575575
id, Lprim (Pccall desc, [size], Loc_unknown))
576576
letrec.blocks
577577
in
578-
let real_body = body in
579-
let bound_ids_freshening =
580-
List.map (fun (bound_id, _) -> bound_id, Ident.rename bound_id) bindings
581-
|> Ident.Map.of_list
582-
in
583-
let cont = next_raise_count () in
584-
let body =
585-
if not letrec.needs_region
586-
then body
587-
else
588-
let args = List.map (fun (bound_id, _) -> Lvar bound_id) bindings in
589-
Lstaticraise (cont, args)
590-
in
578+
let body = if not letrec.needs_region then body else Lexclave body in
591579
let effects_then_body = lsequence (letrec.effects, body) in
592580
let functions =
593581
match letrec.functions with
@@ -618,29 +606,32 @@ let dissect_letrec ~bindings ~body =
618606
with_preallocations letrec.consts
619607
in
620608
let substituted = Lambda.rename letrec.substitution with_constants in
621-
let body_layout = Lambda.layout_top in
622-
if not letrec.needs_region
623-
then substituted
624-
else
625-
Lstaticcatch
626-
( Lregion (Lambda.rename bound_ids_freshening substituted, body_layout),
627-
( cont,
628-
List.map
629-
(fun (bound_id, _) -> bound_id, Lambda.layout_letrec)
630-
bindings ),
631-
real_body,
632-
body_layout )
609+
if letrec.needs_region
610+
then
611+
let body_layout =
612+
let bindings =
613+
Ident.Map.map (fun _ -> Lambda.layout_letrec)
614+
@@ Ident.Map.of_list bindings
615+
in
616+
let free_vars_kind id : Lambda.layout option =
617+
try Some (Ident.Map.find id bindings)
618+
with Not_found -> free_vars_kind id
619+
in
620+
Lambda.compute_expr_layout free_vars_kind body
621+
in
622+
Lregion (substituted, body_layout)
623+
else substituted
633624

634625
type dissected =
635626
| Dissected of Lambda.lambda
636627
| Unchanged
637628

638-
let dissect_letrec ~bindings ~body =
629+
let dissect_letrec ~bindings ~body ~free_vars_kind =
639630
let is_a_function = function _, Lfunction _ -> true | _, _ -> false in
640631
if List.for_all is_a_function bindings
641632
then Unchanged
642633
else
643-
try Dissected (dissect_letrec ~bindings ~body)
634+
try Dissected (dissect_letrec ~bindings ~body ~free_vars_kind)
644635
with Bug ->
645636
Misc.fatal_errorf "let-rec@.%a@." Printlambda.lambda
646637
(Lletrec (bindings, body))

middle_end/flambda2/from_lambda/dissect_letrec.mli

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,7 @@ type dissected =
2424
(** [dissect_letrec] assumes that bindings have not been dissected yet. In
2525
particular, that no arguments of function call are recursive. *)
2626
val dissect_letrec :
27-
bindings:(Ident.t * Lambda.lambda) list -> body:Lambda.lambda -> dissected
27+
bindings:(Ident.t * Lambda.lambda) list ->
28+
body:Lambda.lambda ->
29+
free_vars_kind:(Ident.t -> Lambda.layout option) ->
30+
dissected

middle_end/flambda2/from_lambda/lambda_to_flambda.ml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1242,7 +1242,13 @@ let rec cps acc env ccenv (lam : L.lambda) (k : cps_continuation)
12421242
* in
12431243
* cps_non_tail_simple acc env ccenv defining_expr k k_exn *)
12441244
| Lletrec (bindings, body) -> (
1245-
match Dissect_letrec.dissect_letrec ~bindings ~body with
1245+
let free_vars_kind id =
1246+
let _, kind_with_subkind = CCenv.find_var ccenv id in
1247+
Some
1248+
(Flambda_kind.to_lambda
1249+
(Flambda_kind.With_subkind.kind kind_with_subkind))
1250+
in
1251+
match Dissect_letrec.dissect_letrec ~bindings ~body ~free_vars_kind with
12461252
| Unchanged ->
12471253
let function_declarations = cps_function_bindings env bindings in
12481254
let body acc ccenv = cps acc env ccenv body k k_exn in

middle_end/flambda2/kinds/flambda_kind.ml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,19 @@ let region = Region
5757

5858
let rec_info = Rec_info
5959

60+
let to_lambda (t : t) : Lambda.layout =
61+
match t with
62+
| Value -> Pvalue Pgenval
63+
| Naked_number Naked_immediate ->
64+
Misc.fatal_error "Can't convert kind [Naked_immediate] to lambda layout"
65+
| Naked_number Naked_float -> Punboxed_float
66+
| Naked_number Naked_int32 -> Punboxed_int Pint32
67+
| Naked_number Naked_int64 -> Punboxed_int Pint64
68+
| Naked_number Naked_nativeint -> Punboxed_int Pnativeint
69+
| Region -> Misc.fatal_error "Can't convert kind [Region] to lambda layout"
70+
| Rec_info ->
71+
Misc.fatal_error "Can't convert kind [Rec_info] to lambda layout"
72+
6073
include Container_types.Make (struct
6174
type nonrec t = t
6275

middle_end/flambda2/kinds/flambda_kind.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ val is_value : t -> bool
6464

6565
val is_naked_float : t -> bool
6666

67+
val to_lambda : t -> Lambda.layout
68+
6769
include Container_types.S with type t := t
6870

6971
module Standard_int : sig

ocaml/lambda/lambda.ml

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1491,37 +1491,40 @@ let primitive_result_layout (p : primitive) =
14911491
layout_any_value
14921492
| (Parray_to_iarray | Parray_of_iarray) -> layout_any_value
14931493

1494-
let rec compute_expr_layout kinds lam =
1495-
match lam with
1496-
| Lvar id | Lmutvar id ->
1497-
begin
1498-
try Ident.Map.find id kinds
1499-
with Not_found ->
1500-
Misc.fatal_errorf "Unbound layout for variable %a" Ident.print id
1501-
end
1502-
| Lconst cst -> structured_constant_layout cst
1503-
| Lfunction _ -> layout_function
1504-
| Lapply { ap_result_layout; _ } -> ap_result_layout
1505-
| Lsend (_, _, _, _, _, _, _, layout) -> layout
1506-
| Llet(_, kind, id, _, body) | Lmutlet(kind, id, _, body) ->
1507-
compute_expr_layout (Ident.Map.add id kind kinds) body
1508-
| Lletrec(defs, body) ->
1509-
let kinds =
1510-
List.fold_left (fun kinds (id, _) -> Ident.Map.add id layout_letrec kinds)
1511-
kinds defs
1512-
in
1513-
compute_expr_layout kinds body
1514-
| Lprim(p, _, _) ->
1515-
primitive_result_layout p
1516-
| Lswitch(_, _, _, kind) | Lstringswitch(_, _, _, _, kind)
1517-
| Lstaticcatch(_, _, _, kind) | Ltrywith(_, _, _, kind)
1518-
| Lifthenelse(_, _, _, kind) | Lregion (_, kind) ->
1519-
kind
1520-
| Lstaticraise (_, _) ->
1521-
layout_bottom
1522-
| Lsequence(_, body) | Levent(body, _) -> compute_expr_layout kinds body
1523-
| Lwhile _ | Lfor _ | Lassign _ -> layout_unit
1524-
| Lifused _ ->
1525-
assert false
1526-
| Lexclave e -> compute_expr_layout kinds e
1527-
1494+
let compute_expr_layout free_vars_kind lam =
1495+
let rec compute_expr_layout kinds = function
1496+
| Lvar id | Lmutvar id -> begin
1497+
try Ident.Map.find id kinds
1498+
with Not_found ->
1499+
match free_vars_kind id with
1500+
| Some kind -> kind
1501+
| None ->
1502+
Misc.fatal_errorf "Unbound layout for variable %a" Ident.print id
1503+
end
1504+
| Lconst cst -> structured_constant_layout cst
1505+
| Lfunction _ -> layout_function
1506+
| Lapply { ap_result_layout; _ } -> ap_result_layout
1507+
| Lsend (_, _, _, _, _, _, _, layout) -> layout
1508+
| Llet(_, kind, id, _, body) | Lmutlet(kind, id, _, body) ->
1509+
compute_expr_layout (Ident.Map.add id kind kinds) body
1510+
| Lletrec(defs, body) ->
1511+
let kinds =
1512+
List.fold_left (fun kinds (id, _) -> Ident.Map.add id layout_letrec kinds)
1513+
kinds defs
1514+
in
1515+
compute_expr_layout kinds body
1516+
| Lprim(p, _, _) ->
1517+
primitive_result_layout p
1518+
| Lswitch(_, _, _, kind) | Lstringswitch(_, _, _, _, kind)
1519+
| Lstaticcatch(_, _, _, kind) | Ltrywith(_, _, _, kind)
1520+
| Lifthenelse(_, _, _, kind) | Lregion (_, kind) ->
1521+
kind
1522+
| Lstaticraise (_, _) ->
1523+
layout_bottom
1524+
| Lsequence(_, body) | Levent(body, _) -> compute_expr_layout kinds body
1525+
| Lwhile _ | Lfor _ | Lassign _ -> layout_unit
1526+
| Lifused _ ->
1527+
assert false
1528+
| Lexclave e -> compute_expr_layout kinds e
1529+
in
1530+
compute_expr_layout Ident.Map.empty lam

ocaml/lambda/lambda.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -669,4 +669,4 @@ val structured_constant_layout : structured_constant -> layout
669669

670670
val primitive_result_layout : primitive -> layout
671671

672-
val compute_expr_layout : layout Ident.Map.t -> lambda -> layout
672+
val compute_expr_layout : (Ident.t -> layout option) -> lambda -> layout

ocaml/middle_end/closure/closure.ml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -987,6 +987,10 @@ let close_approx_var { fenv; cenv } id =
987987
let close_var env id =
988988
let (ulam, _app) = close_approx_var env id in ulam
989989

990+
let compute_expr_layout kinds lambda =
991+
let find_kind id = Ident.Map.find_opt id kinds in
992+
compute_expr_layout find_kind lambda
993+
990994
let rec close ({ backend; fenv; cenv ; mutable_vars; kinds; catch_env } as env) lam =
991995
let module B = (val backend : Backend_intf.S) in
992996
match lam with
@@ -1147,7 +1151,7 @@ let rec close ({ backend; fenv; cenv ; mutable_vars; kinds; catch_env } as env)
11471151
_approx_res)), uargs)
11481152
when nargs > List.length params_layout ->
11491153
let nparams = List.length params_layout in
1150-
let args_kinds = List.map (Lambda.compute_expr_layout kinds) args in
1154+
let args_kinds = List.map (compute_expr_layout kinds) args in
11511155
let args = List.map (fun arg -> V.create_local "arg", arg) uargs in
11521156
(* CR mshinwell: Edit when Lapply has kinds *)
11531157
let kinds =
@@ -1194,14 +1198,14 @@ let rec close ({ backend; fenv; cenv ; mutable_vars; kinds; catch_env } as env)
11941198
warning_if_forced_inlined ~loc ~attribute "Unknown function";
11951199
fail_if_probe ~probe "Unknown function";
11961200
(Ugeneric_apply(ufunct, uargs,
1197-
List.map (Lambda.compute_expr_layout kinds) args,
1201+
List.map (compute_expr_layout kinds) args,
11981202
ap_result_layout, (pos, mode), dbg), Value_unknown)
11991203
end
12001204
| Lsend(kind, met, obj, args, pos, mode, loc, result_layout) ->
12011205
let (umet, _) = close env met in
12021206
let (uobj, _) = close env obj in
12031207
let dbg = Debuginfo.from_location loc in
1204-
let args_layout = List.map (Lambda.compute_expr_layout kinds) args in
1208+
let args_layout = List.map (compute_expr_layout kinds) args in
12051209
(Usend(kind, umet, uobj, close_list env args, args_layout, result_layout, (pos,mode), dbg),
12061210
Value_unknown)
12071211
| Llet(str, kind, id, lam, body) ->

0 commit comments

Comments
 (0)