diff --git a/src/causality.ml b/src/causality.ml index a94519cc4c9189e19b73f6f2a613caba34488fe2..a579e096c3973b389bd223d8078c6093925deb1d 100644 --- a/src/causality.ml +++ b/src/causality.ml @@ -48,7 +48,8 @@ exception Error of error to break cycle, then start afresh - insert g' into g - return g *) (* Tests whether [v] is a root of graph [g], i.e. a source *) -let is_graph_root v g = IdentDepGraph.in_degree g v = 0 +let is_graph_root v g = + IdentDepGraph.in_degree g v = 0 (* Computes the set of graph roots, i.e. the sources of acyclic graph [g] *) let graph_roots g = diff --git a/src/checks/liveness.ml b/src/checks/liveness.ml index 03a91558e00851001febae31afd4b2349a454e0d..99ea71ae18638a9aa75f9684ad17263755225486 100644 --- a/src/checks/liveness.ml +++ b/src/checks/liveness.ml @@ -183,7 +183,7 @@ let pp_context fmt ctx = quasi-reusable variables - [reusable] is the set of dead/reusable dependencies of [var] in graph [g] - [policy] is the reuse map (which domain is [evaluated]) *) -let compute_dependencies heads ctx = +let update_dependencies heads ctx = (*Log.report ~level:6 (fun fmt -> Format.fprintf fmt "compute_reusable_dependencies %a %a %a@." Disjunction.pp_ciset locals Printers.pp_var_name var pp_context ctx);*) @@ -201,32 +201,47 @@ let compute_dependencies heads ctx = [v] is not an aliasable input of the equation defining [var] - [v] is not one of the current heads (which contain [var]) - [v] is not currently in use *) let eligible node ctx heads var v = + let is_another_head head v = + head.var_id = v.var_id || try Hashtbl.find ctx.policy head.var_id = v with Not_found -> false + in Hashtbl.find ctx.policy v.var_id == v && Typing.eq_ground (Types.unclock_type var.var_type) (Types.unclock_type v.var_type) && (not (is_aliasable_input node var.var_id v)) - && (not (List.exists (fun h -> h.var_id = v.var_id) heads)) + && List.for_all (fun h -> not (is_another_head h v)) heads && (*let repr_v = Hashtbl.find ctx.policy v.var_id*) not (Disjunction.CISet.exists (fun p -> IdentDepGraph.mem_edge ctx.dep_graph p.var_id v.var_id) ctx.evaluated) -let compute_reuse node ctx heads var = +let compute_reuse node inputs ctx heads var = + (*Format.eprintf "compute_reuse %s@ %a@." var.var_id pp_context ctx;*) let disjoint = Hashtbl.find ctx.disjoint var.var_id in let locally_reusable v = + let v_id = + if Disjunction.CISet.mem v inputs + then ExprDep.mk_read_var v.var_id + else v.var_id in IdentDepGraph.fold_pred (fun p r -> r && Disjunction.CISet.exists (fun d -> p = d.var_id) disjoint) ctx.dep_graph - v.var_id + v_id true in let eligibles = - if ISet.mem var.var_id (ExprDep.node_memory_variables node) then + if ISet.mem var.var_id (ExprDep.node_memory_variables node) + then Disjunction.CISet.empty - else Disjunction.CISet.filter (eligible node ctx heads var) ctx.evaluated + else + if ISet.mem var.var_id (ExprDep.node_output_variables node) + then + Disjunction.CISet.filter (fun v -> (not (Disjunction.CISet.mem v inputs)) + && eligible node ctx heads var v) ctx.evaluated + else + Disjunction.CISet.filter (eligible node ctx heads var) ctx.evaluated in let quasi_dead, live = Disjunction.CISet.partition locally_reusable eligibles @@ -234,7 +249,7 @@ let compute_reuse node ctx heads var = let disjoint_live = Disjunction.CISet.inter disjoint live in let dead = Disjunction.CISet.filter - (fun v -> is_graph_root v.var_id ctx.dep_graph) + (fun v -> is_graph_root (if Disjunction.CISet.mem v inputs then ExprDep.mk_read_var v.var_id else v.var_id) ctx.dep_graph) quasi_dead in Log.report ~level:7 (fun fmt -> @@ -273,14 +288,27 @@ let remove_call_return_dependency g = IdentDepGraph.(iter_succ (remove_edge g v) g v)) g +let add_input_dependency inputs g = + Disjunction.CISet.iter (fun v -> IdentDepGraph.add_vertex g ExprDep.(mk_read_var v.var_id)) inputs + let compute_reuse_policy node schedule disjoint g = + let inputs = + List.fold_left + (fun inputs v -> Disjunction.CISet.add v inputs) + Disjunction.CISet.empty + (if node.node_iscontract then node.node_inputs @ node.node_outputs + else node.node_inputs) in + (*let inputs = Disjunction.CISet.empty in*) + let policy = Hashtbl.create 23 in + Disjunction.CISet.iter (fun v -> Hashtbl.add policy v.var_id v) inputs; remove_call_return_dependency g; + add_input_dependency inputs g; let ctx = { - evaluated = Disjunction.CISet.empty; + evaluated = inputs; dep_graph = g; disjoint; - policy = Hashtbl.create 23; + policy = policy; } in List.iter @@ -308,18 +336,14 @@ let compute_reuse_policy node schedule disjoint g = Printers.pp_node_eq (get_node_eq head.var_id node))) heads)); - compute_dependencies heads ctx; + update_dependencies heads ctx; Log.report ~level:6 (fun fmt -> Format.fprintf fmt "@[<v>@[<v 2>new context:@,%a@]@,COMPUTE_REUSE@,@]" pp_context ctx); - List.iter - (fun head -> - compute_dependencies [ head ] ctx; - compute_reuse node ctx heads head) - heads; + List.iter (fun head -> update_dependencies [head] ctx; compute_reuse node inputs ctx heads head) heads; (*compute_evaluated heads ctx;*) Log.report ~level:6 (fun fmt -> Format.( diff --git a/src/optimize_machine.ml b/src/optimize_machine.ml index cb8833d20b0917989dc02a8683af1a382c2ba46d..766352c1257b15434e40658362cff80b24d4554f 100644 --- a/src/optimize_machine.ml +++ b/src/optimize_machine.ml @@ -1044,9 +1044,12 @@ let step_replace_var m reuse step = List.fold_left (fun res l -> let l' = fvar l in - if List.exists (fun o -> o.var_id = l'.var_id) step.step_outputs then + if List.exists (fun o -> o.var_id = l'.var_id) step.step_outputs + || List.exists (fun i -> i.var_id = l'.var_id) step.step_inputs + then res - else Utils.add_cons l' res) + else + Utils.add_cons l' res) [] step.step_locals in