(**************************************************************************) (* *) (* OCaml *) (* *) (* Pierre Chambart, OCamlPro *) (* Mark Shinwell and Leo White, Jane Street Europe *) (* *) (* Copyright 2013--2016 OCamlPro SAS *) (* Copyright 2014--2016 Jane Street Group LLC *) (* *) (* All rights reserved. This file is distributed under the terms of *) (* the GNU Lesser General Public License version 2.1, with the *) (* special exception on linking described in the file LICENSE. *) (* *) (**************************************************************************) [@@@ocaml.warning "+a-4-9-30-40-41-42-66"] open! Int_replace_polymorphic_compare let pass_name = "remove-free-vars-equal-to-args" let () = Pass_wrapper.register ~pass_name let rewrite_one_function_decl ~(function_decl : Flambda.function_declaration) ~back_free_vars ~specialised_args = let params_for_equal_free_vars = List.fold_left (fun subst param -> match Variable.Map.find param specialised_args with | exception Not_found -> (* param is not specialised *) subst | (spec_to : Flambda.specialised_to) -> let outside_var = spec_to.var in match Variable.Map.find outside_var back_free_vars with | exception Not_found -> (* No free variables equal to the param *) subst | set -> (* Replace the free variables equal to a parameter *) Variable.Set.fold (fun free_var subst -> Variable.Map.add free_var param subst) set subst) Variable.Map.empty (Parameter.List.vars function_decl.params) in if Variable.Map.is_empty params_for_equal_free_vars then function_decl else let body = Flambda_utils.toplevel_substitution params_for_equal_free_vars function_decl.body in Flambda.update_function_declaration function_decl ~params:function_decl.params ~body:body let rewrite_one_set_of_closures (set_of_closures : Flambda.set_of_closures) = let back_free_vars = Variable.Map.fold (fun var (outside_var : Flambda.specialised_to) map -> let set = match Variable.Map.find outside_var.var map with | exception Not_found -> Variable.Set.singleton var | set -> Variable.Set.add var set in Variable.Map.add outside_var.var set map) set_of_closures.free_vars Variable.Map.empty in let done_something = ref false in let funs = Variable.Map.map (fun function_decl -> let new_function_decl = rewrite_one_function_decl ~function_decl ~back_free_vars ~specialised_args:set_of_closures.specialised_args in if not (new_function_decl == function_decl) then begin done_something := true end; new_function_decl) set_of_closures.function_decls.funs in if not !done_something then None else let function_decls = Flambda.update_function_declarations set_of_closures.function_decls ~funs in let set_of_closures = Flambda.create_set_of_closures ~function_decls ~free_vars:set_of_closures.free_vars ~specialised_args:set_of_closures.specialised_args ~direct_call_surrogates:set_of_closures.direct_call_surrogates in Some set_of_closures let run ~ppf_dump set_of_closures = Pass_wrapper.with_dump ~ppf_dump ~pass_name ~input:set_of_closures ~print_input:Flambda.print_set_of_closures ~print_output:Flambda.print_set_of_closures ~f:(fun () -> rewrite_one_set_of_closures set_of_closures)