@@ -147,39 +147,60 @@ and rewrite_body
147147 let s =
148148 Var.Set. fold (fun x m -> Var.Map. add x (Var. fork x) m) free_vars Var.Map. empty
149149 in
150- let program = Subst.Excluding_Binders. cont (Subst. from_map s) pc' program in
151- let f' = try Var.Map. find f s with Not_found -> Var. fork f in
152- let s = Var.Map. bindings (Var.Map. remove f s) in
153- let f'' = Var. fork f in
154- if debug ()
155- then
156- Format. eprintf
157- " LIFT %s (depth:%d free_vars:%d inner_depth:%d)@."
158- (Code.Var. to_string f'')
159- depth
160- (Var.Set. cardinal free_vars)
161- (compute_depth program pc');
162- let pc'' = program.free_pc in
163- let bl = { params = [] ; body = [ Let (f', cl) ]; branch = Return f' } in
164- let program =
165- { program with free_pc = pc'' + 1 ; blocks = Addr.Map. add pc'' bl program.blocks }
166- in
167- (* Add to returned list of lifter functions definitions *)
168- let functions = Let (f'', Closure (List. map s ~f: snd, (pc'', [] ))) :: functions in
169- let lifters = Var.Map. add f f' lifters in
170- rewrite_body
171- ~to_lift
172- ~inside_lifted
173- ~current_contiguous: []
174- ~st: (program, functions, lifters)
175- ~var_depth
176- ~acc_instr:
177- (* Replace closure with application of the lifter function *)
178- (Let (f, Apply { f = f''; args = List. map ~f: fst s; exact = true }) :: acc_instr)
179- ~depth
180- rem
150+ if not Var.Map. (is_empty (remove f s))
151+ then (
152+ let program = Subst.Excluding_Binders. cont (Subst. from_map s) pc' program in
153+ let f' = try Var.Map. find f s with Not_found -> Var. fork f in
154+ let f'' = Var. fork f in
155+ let s = Var.Map. bindings (Var.Map. remove f s) in
156+ if debug ()
157+ then
158+ Format. eprintf
159+ " LIFT %s (depth:%d free_vars:%d inner_depth:%d)@."
160+ (Code.Var. to_string f'')
161+ depth
162+ (Var.Set. cardinal free_vars)
163+ (compute_depth program pc');
164+ let pc'' = program.free_pc in
165+ let bl = { params = [] ; body = [ Let (f', cl) ]; branch = Return f' } in
166+ let program =
167+ { program with
168+ free_pc = pc'' + 1
169+ ; blocks = Addr.Map. add pc'' bl program.blocks
170+ }
171+ in
172+ (* Add to returned list of lifter functions definitions *)
173+ let functions = Let (f'', Closure (List. map s ~f: snd, (pc'', [] ))) :: functions in
174+ let lifters = Var.Map. add f f' lifters in
175+ rewrite_body
176+ ~to_lift
177+ ~inside_lifted
178+ ~current_contiguous: []
179+ ~st: (program, functions, lifters)
180+ ~var_depth
181+ ~acc_instr:
182+ (* Replace closure with application of the lifter function *)
183+ (Let (f, Apply { f = f''; args = List. map ~f: fst s; exact = true })
184+ :: acc_instr)
185+ ~depth
186+ rem)
187+ else
188+ (* The closure doesn't have free variables, and thus doesn't need a lifter
189+ function. Just make sure it's a top-level function. *)
190+ let functions = Let (f, cl) :: functions in
191+ rewrite_body
192+ ~to_lift
193+ ~inside_lifted
194+ ~var_depth
195+ ~current_contiguous: []
196+ ~st: (program, functions, lifters)
197+ ~acc_instr
198+ ~depth
199+ rem
181200 | Let (cname , Closure (params , (pc' , args ))) :: rem ->
182- (* More closure definitions follow: accumulate and lift later *)
201+ (* We do not lift an isolated closure: either more closure definitions follow, or
202+ the closure doesn't need to be lifted. In both cases, we accumulate it and will
203+ lift (or not) later. *)
183204 let st =
184205 rewrite_blocks
185206 ~to_lift
0 commit comments