@@ -371,28 +371,31 @@ let rec small_function ~context info args =
371371 && body_size ~context info < = 15
372372 && closure_count ~context info = 0
373373 && (not (List. is_empty args))
374- &&
374+ && not (Var.Map. is_empty (relevant_arguments ~context info args))
375+
376+ and relevant_arguments ~context info args =
375377 let relevant_params = interesting_parameters ~context info in
376- try
377- List. iter2 args info.params ~f: (fun arg param ->
378+ List. fold_left2
379+ args
380+ info.params
381+ ~f: (fun m arg param ->
382+ if
383+ Var.Map. mem arg context.env
384+ && List. exists ~f: (fun (p , _ ) -> Var. equal p param) relevant_params
385+ then
386+ let info' = Var.Map. find arg context.env in
387+ let _, arity = List. find ~f: (fun (p , _ ) -> Var. equal p param) relevant_params in
378388 if
379- Var.Map. mem arg context.env
380- && List. exists ~f: (fun (p , _ ) -> Var. equal p param) relevant_params
381- then
382- let info' = Var.Map. find arg context.env in
383- let _, arity = List. find ~f: (fun (p , _ ) -> Var. equal p param) relevant_params in
384- if
385- List. compare_length_with info'.params ~len: arity = 0
386- && should_inline
387- ~context:
388- { context with
389- in_loop = context.in_loop || contains_loop ~context info
390- }
391- info'
392- []
393- then raise Exit );
394- false
395- with Exit -> true
389+ List. compare_length_with info'.params ~len: arity = 0
390+ && should_inline
391+ ~context:
392+ { context with in_loop = context.in_loop || contains_loop ~context info }
393+ info'
394+ []
395+ then Var.Map. add param arg m
396+ else m
397+ else m)
398+ ~init: Var.Map. empty
396399
397400and should_inline ~context info args =
398401 (* Typically, in JavaScript implementations, a closure contains a
@@ -521,7 +524,7 @@ let rewrite_closure blocks cont_pc clos_pc =
521524 blocks
522525 blocks
523526
524- let inline_function p rem branch x params cont args =
527+ let rewrite_inlined_function p rem branch x params cont args =
525528 let blocks, cont_pc, free_pc =
526529 match rem, branch with
527530 | [] , Return y when Var. equal x y ->
@@ -546,27 +549,69 @@ let inline_function p rem branch x params cont args =
546549 in
547550 [] , (Branch (fresh_addr, args), { p with blocks; free_pc })
548551
552+ let rec inline_recursively ~context ~info p params (pc , _ ) args =
553+ let relevant_args = relevant_arguments ~context info args in
554+ if Var.Map. is_empty relevant_args
555+ then p
556+ else
557+ let subst =
558+ List. fold_left2
559+ params
560+ info.params
561+ ~f: (fun m param param' ->
562+ if Var.Map. mem param' relevant_args
563+ then Var.Map. add param (Var.Map. find param' relevant_args) m
564+ else m)
565+ ~init: Var.Map. empty
566+ in
567+ Code. traverse
568+ { fold = Code. fold_children }
569+ (fun pc p ->
570+ let block = Addr.Map. find pc p.blocks in
571+ let body, (branch, p) =
572+ List. fold_right
573+ ~f: (fun i (rem , state ) ->
574+ match i with
575+ | Let (x , Apply { f; args; _ } ) when Var.Map. mem f subst ->
576+ let f = Var.Map. find f subst in
577+ inline_function ~context i x f args rem state
578+ | _ -> i :: rem, state)
579+ ~init: ([] , (block.branch, p))
580+ block.body
581+ in
582+ { p with blocks = Addr.Map. add pc { block with body; branch } p.blocks })
583+ pc
584+ p.blocks
585+ p
586+
587+ and inline_function ~context i x f args rem state =
588+ let info = Var.Map. find f context.env in
589+ let { params; cont; _ } = info in
590+ trace_inlining ~context info x args;
591+ if should_inline ~context info args
592+ then (
593+ let branch, p = state in
594+ incr context.inline_count;
595+ if closure_count ~context info > 0 then context.has_closures := true ;
596+ context.live_vars.(Var. idx f) < - context.live_vars.(Var. idx f) - 1 ;
597+ let p, params, cont =
598+ if context.live_vars.(Var. idx f) > 0
599+ then
600+ let p, _, params, cont = Duplicate. closure p ~f ~params ~cont in
601+ p, params, cont
602+ else p, params, cont
603+ in
604+ let p = inline_recursively ~context ~info p params cont args in
605+ rewrite_inlined_function p rem branch x params cont args)
606+ else i :: rem, state
607+
549608let inline_in_block ~context pc block p =
550609 let body, (branch, p) =
551610 List. fold_right
552611 ~f: (fun i (rem , state ) ->
553612 match i with
554613 | Let (x , Apply { f; args; exact = true ; _ } ) when Var.Map. mem f context.env ->
555- let info = Var.Map. find f context.env in
556- let { params; cont; _ } = info in
557- trace_inlining ~context info x args;
558- if should_inline ~context info args
559- then (
560- let branch, p = state in
561- incr context.inline_count;
562- if closure_count ~context info > 0 then context.has_closures := true ;
563- context.live_vars.(Var. idx f) < - context.live_vars.(Var. idx f) - 1 ;
564- if context.live_vars.(Var. idx f) > 0
565- then
566- let p, _, params, cont = Duplicate. closure p ~f ~params ~cont in
567- inline_function p rem branch x params cont args
568- else inline_function p rem branch x params cont args)
569- else i :: rem, state
614+ inline_function ~context i x f args rem state
570615 | _ -> i :: rem, state)
571616 ~init: ([] , (block.branch, p))
572617 block.body
0 commit comments