Skip to content

Commit

Permalink
added new lambda construct Lmutvar and Lmutĺet (#9954)
Browse files Browse the repository at this point in the history
Used in replacement of Variable attribute of Llet
  • Loading branch information
Keryan-dev committed Dec 17, 2020
1 parent 2b574d2 commit ebf2048
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 47 deletions.
6 changes: 4 additions & 2 deletions bytecomp/bytegen.ml
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,8 @@ module Storer =
let rec comp_expr env exp sz cont =
if sz > !max_stack_used then max_stack_used := sz;
match exp with
Lvar id ->
Lvar id
| Lmutvar id ->
begin try
let pos = Ident.find_same id env.ce_stack in
Kacc(sz - pos) :: cont
Expand Down Expand Up @@ -591,7 +592,8 @@ let rec comp_expr env exp sz cont =
Stack.push to_compile functions_to_compile;
comp_args env (List.map (fun n -> Lvar n) fv) sz
(Kclosure(lbl, List.length fv) :: cont)
| Llet(_str, _k, id, arg, body) ->
| Llet(_, _k, id, arg, body)
| Lmutlet(_k, id, arg, body) ->
comp_expr env arg sz
(Kpush :: comp_expr (add_var id (sz+1) env) body (sz+1)
(add_pop 1 cont))
Expand Down
33 changes: 28 additions & 5 deletions lambda/lambda.ml
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ type local_attribute =

type function_kind = Curried | Tupled

type let_kind = Strict | Alias | StrictOpt | Variable
type let_kind = Strict | Alias | StrictOpt

type meth_kind = Self | Public | Cached

Expand All @@ -284,10 +284,12 @@ type scoped_location = Debuginfo.Scoped_location.t

type lambda =
Lvar of Ident.t
| Lmutvar of Ident.t
| Lconst of structured_constant
| Lapply of lambda_apply
| Lfunction of lfunction
| Llet of let_kind * value_kind * Ident.t * lambda * lambda
| Lmutlet of value_kind * Ident.t * lambda * lambda
| Lletrec of (Ident.t * lambda) list * lambda
| Lprim of primitive * lambda list * scoped_location
| Lswitch of lambda * lambda_switch * scoped_location
Expand Down Expand Up @@ -382,7 +384,8 @@ let make_key e =
incr count ;
if !count > max_raw then raise Not_simple ; (* Too big ! *)
match e with
| Lvar id ->
| Lvar id
| Lmutvar id ->
begin
try Ident.find_same id env
with Not_found -> e
Expand All @@ -405,6 +408,10 @@ let make_key e =
let ex = tr_rec env ex in
let y = make_key x in
Llet (str,k,y,ex,tr_rec (Ident.add x (Lvar y) env) e)
| Lmutlet (k,x,ex,e) ->
let ex = tr_rec env ex in
let y = make_key x in
Lmutlet (k,y,ex,tr_rec (Ident.add x (Lmutvar y) env) e)
| Lprim (p,es,_) ->
Lprim (p,tr_recs env es, Loc_unknown)
| Lswitch (e,sw,loc) ->
Expand Down Expand Up @@ -479,12 +486,14 @@ let iter_opt f = function

let shallow_iter ~tail ~non_tail:f = function
Lvar _
| Lmutvar _
| Lconst _ -> ()
| Lapply{ap_func = fn; ap_args = args} ->
f fn; List.iter f args
| Lfunction{body} ->
f body
| Llet(_str, _k, _id, arg, body) ->
| Llet(_, _k, _id, arg, body)
| Lmutlet(_k, _id, arg, body) ->
f arg; tail body
| Lletrec(decl, body) ->
tail body;
Expand Down Expand Up @@ -533,14 +542,16 @@ let iter_head_constructor f l =
shallow_iter ~tail:f ~non_tail:f l

let rec free_variables = function
| Lvar id -> Ident.Set.singleton id
| Lvar id
| Lmutvar id -> Ident.Set.singleton id
| Lconst _ -> Ident.Set.empty
| Lapply{ap_func = fn; ap_args = args} ->
free_variables_list (free_variables fn) args
| Lfunction{body; params} ->
Ident.Set.diff (free_variables body)
(Ident.Set.of_list (List.map fst params))
| Llet(_str, _k, id, arg, body) ->
| Llet(_, _k, id, arg, body)
| Lmutlet(_k, id, arg, body) ->
Ident.Set.union
(free_variables arg)
(Ident.Set.remove id (free_variables body))
Expand Down Expand Up @@ -715,6 +726,12 @@ let subst update_env ?(freshen_bound_variables = false) s input_lam =
to [l]; it is a free variable of the input term. *)
begin try Ident.Map.find id s with Not_found -> lam end
end
| Lmutvar id as lam ->
begin match Ident.Map.find id l with
| id' -> Lmutvar id'
| exception Not_found ->
begin try Ident.Map.find id s with Not_found -> lam end
end
| Lconst _ as l -> l
| Lapply ap ->
Lapply{ap with ap_func = subst s l ap.ap_func;
Expand All @@ -725,6 +742,9 @@ let subst update_env ?(freshen_bound_variables = false) s input_lam =
| Llet(str, k, id, arg, body) ->
let id, l' = bind id l in
Llet(str, k, id, subst s l arg, subst s l' body)
| Lmutlet(k, id, arg, body) ->
let id, l' = bind id l in
Lmutlet(k, id, subst s l arg, subst s l' body)
| Lletrec(decl, body) ->
let decl, l' = bind_many decl l in
Lletrec(List.map (subst_decl s l') decl, subst s l' body)
Expand Down Expand Up @@ -818,6 +838,7 @@ let duplicate lam =

let shallow_map f = function
| Lvar _
| Lmutvar _
| Lconst _ as lam -> lam
| Lapply { ap_func; ap_args; ap_loc; ap_tailcall;
ap_inlined; ap_specialised } ->
Expand All @@ -833,6 +854,8 @@ let shallow_map f = function
Lfunction { kind; params; return; body = f body; attr; loc; }
| Llet (str, k, v, e1, e2) ->
Llet (str, k, v, f e1, f e2)
| Lmutlet (k, v, e1, e2) ->
Lmutlet (k, v, f e1, f e2)
| Lletrec (idel, e2) ->
Lletrec (List.map (fun (v, e) -> (v, f e)) idel, f e2)
| Lprim (p, el, loc) ->
Expand Down
5 changes: 3 additions & 2 deletions lambda/lambda.mli
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ type local_attribute =

type function_kind = Curried | Tupled

type let_kind = Strict | Alias | StrictOpt | Variable
type let_kind = Strict | Alias | StrictOpt
(* Meaning of kinds for let x = e in e':
Strict: e may have side-effects; always evaluate e first
(If e is a simple expression, e.g. a variable or constant,
Expand All @@ -243,7 +243,6 @@ type let_kind = Strict | Alias | StrictOpt | Variable
in e'
StrictOpt: e does not have side-effects, but depend on the store;
we can discard e if x does not appear in e'
Variable: the variable x is assigned later in e'
*)

type meth_kind = Self | Public | Cached
Expand All @@ -264,10 +263,12 @@ type scoped_location = Debuginfo.Scoped_location.t

type lambda =
Lvar of Ident.t
| Lmutvar of Ident.t
| Lconst of structured_constant
| Lapply of lambda_apply
| Lfunction of lfunction
| Llet of let_kind * value_kind * Ident.t * lambda * lambda
| Lmutlet of value_kind * Ident.t * lambda * lambda
| Lletrec of (Ident.t * lambda) list * lambda
| Lprim of primitive * lambda list * scoped_location
| Lswitch of lambda * lambda_switch * scoped_location
Expand Down
5 changes: 3 additions & 2 deletions lambda/matching.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3549,6 +3549,7 @@ let simple_for_let ~scopes loc param pat body =

let rec map_return f = function
| Llet (str, k, id, l1, l2) -> Llet (str, k, id, l1, map_return f l2)
| Lmutlet (k, id, l1, l2) -> Lmutlet (k, id, l1, map_return f l2)
| Lletrec (l1, l2) -> Lletrec (l1, map_return f l2)
| Lifthenelse (lcond, lthen, lelse) ->
Lifthenelse (lcond, map_return f lthen, map_return f lelse)
Expand Down Expand Up @@ -3576,8 +3577,8 @@ let rec map_return f = function
Option.map (map_return f) def,
loc )
| (Lstaticraise _ | Lprim (Praise _, _, _)) as l -> l
| ( Lvar _ | Lconst _ | Lapply _ | Lfunction _ | Lsend _ | Lprim _ | Lwhile _
| Lfor _ | Lassign _ | Lifused _ ) as l ->
| ( Lvar _ | Lmutvar _ | Lconst _ | Lapply _ | Lfunction _ | Lsend _ | Lprim _
| Lwhile _ | Lfor _ | Lassign _ | Lifused _ ) as l ->
f l

(* The 'opt' reference indicates if the optimization is worthy.
Expand Down
17 changes: 15 additions & 2 deletions lambda/printlambda.ml
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,8 @@ let apply_specialised_attribute ppf = function
let rec lam ppf = function
| Lvar id ->
Ident.print ppf id
| Lmutvar id ->
fprintf ppf "*%a" Ident.print id
| Lconst cst ->
struct_const ppf cst
| Lapply ap ->
Expand Down Expand Up @@ -523,8 +525,8 @@ let rec lam ppf = function
fprintf ppf "@[<2>(function%a@ %a%a%a)@]" pr_params params
function_attribute attr return_kind return lam body
| Llet(str, k, id, arg, body) ->
let kind = function
Alias -> "a" | Strict -> "" | StrictOpt -> "o" | Variable -> "v"
let kind = function
Alias -> "a" | Strict -> "" | StrictOpt -> "o"
in
let rec letbody = function
| Llet(str, k, id, arg, body) ->
Expand All @@ -536,6 +538,17 @@ let rec lam ppf = function
Ident.print id (kind str) value_kind k lam arg;
let expr = letbody body in
fprintf ppf ")@]@ %a)@]" lam expr
| Lmutlet(k, id, arg, body) ->
let rec letbody = function
| Lmutlet(k, id, arg, body) ->
fprintf ppf "@ @[<2>%a =%a@ %a@]"
Ident.print id value_kind k lam arg;
letbody body
| expr -> expr in
fprintf ppf "@[<2>(let[mut]@ @[<hv 1>(@[<2>%a =%a@ %a@]"
Ident.print id value_kind k lam arg;
let expr = letbody body in
fprintf ppf ")@]@ %a)@]" lam expr
| Lletrec(id_arg_list, body) ->
let bindings ppf id_arg_list =
let spc = ref false in
Expand Down
45 changes: 32 additions & 13 deletions lambda/simplif.ml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ open Debuginfo.Scoped_location
exception Real_reference

let rec eliminate_ref id = function
Lvar v as lam ->
Lvar v
| Lmutvar v as lam ->
if Ident.same v id then raise Real_reference else lam
| Lconst _ as lam -> lam
| Lapply ap ->
Expand All @@ -37,11 +38,13 @@ let rec eliminate_ref id = function
else lam
| Llet(str, kind, v, e1, e2) ->
Llet(str, kind, v, eliminate_ref id e1, eliminate_ref id e2)
| Lmutlet(kind, v, e1, e2) ->
Lmutlet(kind, v, eliminate_ref id e1, eliminate_ref id e2)
| Lletrec(idel, e2) ->
Lletrec(List.map (fun (v, e) -> (v, eliminate_ref id e)) idel,
eliminate_ref id e2)
| Lprim(Pfield 0, [Lvar v], _) when Ident.same v id ->
Lvar id
Lmutvar id
| Lprim(Psetfield(0, _, _), [Lvar v; e], _) when Ident.same v id ->
Lassign(id, eliminate_ref id e)
| Lprim(Poffsetref delta, [Lvar v], loc) when Ident.same v id ->
Expand Down Expand Up @@ -120,10 +123,11 @@ let simplify_exits lam =
in

let rec count = function
| (Lvar _| Lconst _) -> ()
| (Lvar _ | Lmutvar _ | Lconst _) -> ()
| Lapply ap -> count ap.ap_func; List.iter count ap.ap_args
| Lfunction {body} -> count body
| Llet(_str, _kind, _v, l1, l2) ->
| Llet(_, _kind, _v, l1, l2)
| Lmutlet(_kind, _v, l1, l2) ->
count l2; count l1
| Lletrec(bindings, body) ->
List.iter (fun (_v, l) -> count l) bindings;
Expand Down Expand Up @@ -203,13 +207,14 @@ let simplify_exits lam =
let subst = Hashtbl.create 17 in

let rec simplif = function
| (Lvar _|Lconst _) as l -> l
| (Lvar _ | Lmutvar _ | Lconst _) as l -> l
| Lapply ap ->
Lapply{ap with ap_func = simplif ap.ap_func;
ap_args = List.map simplif ap.ap_args}
| Lfunction{kind; params; return; body = l; attr; loc} ->
Lfunction{kind; params; return; body = simplif l; attr; loc}
| Llet(str, kind, v, l1, l2) -> Llet(str, kind, v, simplif l1, simplif l2)
| Lmutlet(kind, v, l1, l2) -> Lmutlet(kind, v, simplif l1, simplif l2)
| Lletrec(bindings, body) ->
Lletrec(List.map (fun (v, l) -> (v, simplif l)) bindings, simplif body)
| Lprim(p, ll, loc) -> begin
Expand Down Expand Up @@ -406,7 +411,8 @@ let simplify_lets lam =

let rec count bv = function
| Lconst _ -> ()
| Lvar v ->
| Lvar v
| Lmutvar v ->
use_var bv v 1
| Lapply{ap_func = ll; ap_args = args} ->
let no_opt () = count bv ll; List.iter (count bv) args in
Expand All @@ -427,9 +433,11 @@ let simplify_lets lam =
count (bind_var bv v) l2;
use_var bv w (count_var v)
| Llet(str, _kind, v, l1, l2) ->
count (bind_var bv v) l2;
count (bind_var bv v) l2;
(* If v is unused, l1 will be removed, so don't count its variables *)
if str = Strict || count_var v > 0 then count bv l1
| Lmutlet(_kind, v, _l1, l2) ->
count (bind_var bv v) l2
| Lletrec(bindings, body) ->
List.iter (fun (_v, l) -> count bv l) bindings;
count bv body
Expand Down Expand Up @@ -491,13 +499,21 @@ let simplify_lets lam =
(* This (small) optimisation is always legal, it may uncover some
tail call later on. *)

let mklet str kind v e1 e2 = match e2 with
| Lvar w when optimize && Ident.same v w -> e1
| _ -> Llet (str, kind,v,e1,e2) in
let mklet str kind v e1 e2 =
match e2 with
| Lvar w when optimize && Ident.same v w -> e1
| _ -> Llet (str, kind,v,e1,e2)
in

let mkmutlet kind v e1 e2 =
match e2 with
| Lmutvar w when optimize && Ident.same v w -> e1
| _ -> Lmutlet (kind,v,e1,e2)
in

let rec simplif = function
Lvar v as l ->
Lvar v
| Lmutvar v as l ->
begin try
Hashtbl.find subst v
with Not_found ->
Expand Down Expand Up @@ -545,7 +561,7 @@ let simplify_lets lam =
| Some [field_kind] -> field_kind
| Some _ -> assert false
in
mklet Variable kind v slinit (eliminate_ref v slbody)
mkmutlet kind v slinit (eliminate_ref v slbody)
with Real_reference ->
mklet Strict kind v (Lprim(prim, [slinit], loc)) slbody
end
Expand All @@ -561,6 +577,7 @@ let simplify_lets lam =
| _ -> mklet StrictOpt kind v (simplif l1) (simplif l2)
end
| Llet(str, kind, v, l1, l2) -> mklet str kind v (simplif l1) (simplif l2)
| Lmutlet(kind, v, l1, l2) -> mkmutlet kind v (simplif l1) (simplif l2)
| Lletrec(bindings, body) ->
Lletrec(List.map (fun (v, l) -> (v, simplif l)) bindings, simplif body)
| Lprim(p, ll, loc) -> Lprim(p, List.map simplif ll, loc)
Expand Down Expand Up @@ -606,6 +623,7 @@ let simplify_lets lam =
let rec emit_tail_infos is_tail lambda =
match lambda with
| Lvar _ -> ()
| Lmutvar _ -> ()
| Lconst _ -> ()
| Lapply ap ->
begin
Expand All @@ -629,7 +647,8 @@ let rec emit_tail_infos is_tail lambda =
list_emit_tail_infos false ap.ap_args
| Lfunction {body = lam} ->
emit_tail_infos true lam
| Llet (_str, _k, _, lam, body) ->
| Llet (_, _k, _, lam, body)
| Lmutlet (_k, _, lam, body) ->
emit_tail_infos false lam;
emit_tail_infos is_tail body
| Lletrec (bindings, body) ->
Expand Down
5 changes: 3 additions & 2 deletions lambda/translclass.ml
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,8 @@ let free_methods l =
| Lsend _ -> ()
| Lfunction{params} ->
List.iter (fun (param, _) -> fv := Ident.Set.remove param !fv) params
| Llet(_str, _k, id, _arg, _body) ->
| Llet(_, _k, id, _arg, _body)
| Lmutlet(_k, id, _arg, _body) ->
fv := Ident.Set.remove id !fv
| Lletrec(decl, _body) ->
List.iter (fun (id, _exp) -> fv := Ident.Set.remove id !fv) decl
Expand All @@ -674,7 +675,7 @@ let free_methods l =
| Lfor(v, _e1, _e2, _dir, _e3) ->
fv := Ident.Set.remove v !fv
| Lassign _
| Lvar _ | Lconst _ | Lapply _
| Lvar _ | Lmutvar _ | Lconst _ | Lapply _
| Lprim _ | Lswitch _ | Lstringswitch _ | Lstaticraise _
| Lifthenelse _ | Lsequence _ | Lwhile _
| Levent _ | Lifused _ -> ()
Expand Down

0 comments on commit ebf2048

Please sign in to comment.