Small refactorings: Loop_control

Summary:
- docstrings
- mli
- split `get_control_maps`: `get_loop_head_to_source_nodes` is used both by Cost and Hoisting. If using both analyzers, it is called twice whereas it could be shared (which is done later in the stack of diffs).

Reviewed By: ezgicicek

Differential Revision: D14258372

fbshipit-source-id: 29addddb7
master
Mehdi Bouaziz 6 years ago committed by Facebook Github Bot
parent 21c9227529
commit 48298f9bcc

@ -751,7 +751,10 @@ let checker {Callbacks.tenv; proc_desc; integer_type_widths; summary} : Summary.
(* computes reaching defs: node -> (var -> node set) *) (* computes reaching defs: node -> (var -> node set) *)
let reaching_defs_invariant_map = ReachingDefs.compute_invariant_map proc_desc tenv in let reaching_defs_invariant_map = ReachingDefs.compute_invariant_map proc_desc tenv in
(* collect all prune nodes that occur in loop guards, needed for ControlDepAnalyzer *) (* collect all prune nodes that occur in loop guards, needed for ControlDepAnalyzer *)
let control_maps, loop_head_to_loop_nodes = Loop_control.get_control_maps node_cfg in let control_maps, loop_head_to_loop_nodes =
let loop_head_to_source_nodes_map = Loop_control.get_loop_head_to_source_nodes node_cfg in
Loop_control.get_control_maps loop_head_to_source_nodes_map
in
(* computes the control dependencies: node -> var set *) (* computes the control dependencies: node -> var set *)
let control_dep_invariant_map = Control.compute_invariant_map proc_desc tenv control_maps in let control_dep_invariant_map = Control.compute_invariant_map proc_desc tenv control_maps in
(* compute loop invariant map for control var analysis *) (* compute loop invariant map for control var analysis *)

@ -72,9 +72,11 @@ let get_exit_nodes_in_loop loop_nodes =
Control.GuardNodes.diff succs_of_loop_nodes loop_nodes |> Control.GuardNodes.elements Control.GuardNodes.diff succs_of_loop_nodes loop_nodes |> Control.GuardNodes.elements
(* Starting from the start_nodes, find all the nodes upwards until the (**
target is reached, i.e picking up predecessors which have not been Starting from the start_nodes, find all the nodes upwards until the
already added to the found_nodes *) target is reached, i.e picking up predecessors which have not been
already added to the found_nodes
*)
let get_all_nodes_upwards_until target start_nodes = let get_all_nodes_upwards_until target start_nodes =
let rec aux found_nodes = function let rec aux found_nodes = function
| [] -> | [] ->
@ -92,9 +94,11 @@ let is_prune node =
match Procdesc.Node.get_kind node with Procdesc.Node.Prune_node _ -> true | _ -> false match Procdesc.Node.get_kind node with Procdesc.Node.Prune_node _ -> true | _ -> false
(* Remove pairs of prune nodes that are for the same condition, (**
i.e. sibling of the same parent. This is necessary to prevent Remove pairs of prune nodes that are for the same condition,
picking unnecessary control variables in do-while like loops *) i.e. sibling of the same parent. This is necessary to prevent
picking unnecessary control variables in do-while like loops
*)
let remove_prune_node_pairs exit_nodes guard_nodes = let remove_prune_node_pairs exit_nodes guard_nodes =
let exit_nodes = Control.GuardNodes.of_list exit_nodes in let exit_nodes = Control.GuardNodes.of_list exit_nodes in
let except_exit_nodes = Control.GuardNodes.diff guard_nodes exit_nodes in let except_exit_nodes = Control.GuardNodes.diff guard_nodes exit_nodes in
@ -108,6 +112,10 @@ let remove_prune_node_pairs exit_nodes guard_nodes =
|> Control.GuardNodes.union exit_nodes |> Control.GuardNodes.union exit_nodes
(**
Since there could be multiple back-edges per loop, collect all source nodes per loop head.
loop_head (target of back-edges) --> source nodes
*)
let get_loop_head_to_source_nodes cfg = let get_loop_head_to_source_nodes cfg =
get_back_edges cfg get_back_edges cfg
|> List.fold ~init:Procdesc.NodeMap.empty ~f:(fun loop_head_to_source_list {source; target} -> |> List.fold ~init:Procdesc.NodeMap.empty ~f:(fun loop_head_to_source_list {source; target} ->
@ -116,16 +124,14 @@ let get_loop_head_to_source_nodes cfg =
loop_head_to_source_list ) loop_head_to_source_list )
(* Get a pair of maps (exit_map, loop_head_to_guard_map) where (**
exit_map : exit_node -> loop_head set (i.e. target of the back edges) Get a pair of maps (exit_map, loop_head_to_guard_map) where
loop_head_to_guard_map : loop_head -> guard_nodes and exit_map : exit_node -> loop_head set (i.e. target of the back edges)
guard_nodes contains the nodes that may affect the looping behavior, i.e. loop_head_to_guard_map : loop_head -> guard_nodes and
occur in the guard of the loop conditional. *) guard_nodes contains the nodes that may affect the looping behavior, i.e.
let get_control_maps cfg = occur in the guard of the loop conditional.
(* Since there could be multiple back-edges per loop, collect all *)
source nodes per loop head *) let get_control_maps loop_head_to_source_nodes_map =
(* loop_head (target of back-edges) --> source nodes *)
let loop_head_to_source_nodes_map = get_loop_head_to_source_nodes cfg in
Procdesc.NodeMap.fold Procdesc.NodeMap.fold
(fun loop_head source_list (fun loop_head source_list
(Control.({exit_map; loop_head_to_guard_nodes}), loop_head_to_loop_nodes) -> (Control.({exit_map; loop_head_to_guard_nodes}), loop_head_to_loop_nodes) ->
@ -174,7 +180,7 @@ let get_control_maps cfg =
( {exit_map= exit_map'; loop_head_to_guard_nodes= loop_head_to_guard_nodes'} ( {exit_map= exit_map'; loop_head_to_guard_nodes= loop_head_to_guard_nodes'}
, loop_head_to_loop_nodes' ) ) , loop_head_to_loop_nodes' ) )
loop_head_to_source_nodes_map loop_head_to_source_nodes_map
( (let open Control in ( Control.
{ exit_map= Control.ExitNodeToLoopHeads.empty { exit_map= Control.ExitNodeToLoopHeads.empty
; loop_head_to_guard_nodes= Control.LoopHeadToGuardNodes.empty }) ; loop_head_to_guard_nodes= Control.LoopHeadToGuardNodes.empty }
, LoopInvariant.LoopHeadToLoopNodes.empty ) , LoopInvariant.LoopHeadToLoopNodes.empty )

@ -0,0 +1,32 @@
(*
* Copyright (c) 2019-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
val get_all_nodes_upwards_until : Procdesc.Node.t -> Procdesc.Node.t list -> Control.GuardNodes.t
(**
Starting from the start_nodes, find all the nodes upwards until the
target is reached, i.e picking up predecessors which have not been
already added to the found_nodes
*)
val get_loop_head_to_source_nodes : Procdesc.t -> Procdesc.Node.t list Procdesc.NodeMap.t
(**
Since there could be multiple back-edges per loop, collect all source nodes per loop head.
loop_head (target of back-edges) --> source nodes
*)
val get_control_maps :
Procdesc.Node.t list Procdesc.NodeMap.t
-> Control.loop_control_maps * Control.GuardNodes.t Procdesc.NodeMap.t
(**
Get a pair of maps (exit_map, loop_head_to_guard_map) where
exit_map : exit_node -> loop_head set (i.e. target of the back edges)
loop_head_to_guard_map : loop_head -> guard_nodes and
guard_nodes contains the nodes that may affect the looping behavior, i.e.
occur in the guard of the loop conditional.
*)
Loading…
Cancel
Save