110 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			OCaml
		
	
	
	
	
	
			
		
		
	
	
			110 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			OCaml
		
	
	
	
	
	
(*
 | 
						|
 * Copyright (c) 1997-1999 Massachusetts Institute of Technology
 | 
						|
 * Copyright (c) 2003, 2007-14 Matteo Frigo
 | 
						|
 * Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology
 | 
						|
 *
 | 
						|
 * This program is free software; you can redistribute it and/or modify
 | 
						|
 * it under the terms of the GNU General Public License as published by
 | 
						|
 * the Free Software Foundation; either version 2 of the License, or
 | 
						|
 * (at your option) any later version.
 | 
						|
 *
 | 
						|
 * This program is distributed in the hope that it will be useful,
 | 
						|
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
 * GNU General Public License for more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU General Public License
 | 
						|
 * along with this program; if not, write to the Free Software
 | 
						|
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 | 
						|
 *
 | 
						|
 *)
 | 
						|
 | 
						|
open Util
 | 
						|
 | 
						|
(* Here, we have functions to transform a sequence of assignments
 | 
						|
   (variable = expression) into a DAG (a directed, acyclic graph).
 | 
						|
   The nodes of the DAG are the assignments, and the edges indicate
 | 
						|
   dependencies.  (The DAG is analyzed in the scheduler to find an
 | 
						|
   efficient ordering of the assignments.)
 | 
						|
 | 
						|
   This file also contains utilities to manipulate the DAG in various
 | 
						|
   ways. *)
 | 
						|
 | 
						|
(********************************************
 | 
						|
 *  Dag structure
 | 
						|
 ********************************************)
 | 
						|
type color = RED | BLUE | BLACK | YELLOW
 | 
						|
 | 
						|
type dagnode = 
 | 
						|
    { assigned: Variable.variable;
 | 
						|
      mutable expression: Expr.expr;
 | 
						|
      input_variables: Variable.variable list;
 | 
						|
      mutable successors: dagnode list;
 | 
						|
      mutable predecessors: dagnode list;
 | 
						|
      mutable label: int;
 | 
						|
      mutable color: color}
 | 
						|
 | 
						|
type dag = Dag of (dagnode list)
 | 
						|
 | 
						|
(* true if node uses v *)
 | 
						|
let node_uses v node = 
 | 
						|
  List.exists (Variable.same v) node.input_variables
 | 
						|
 | 
						|
(* true if assignment of v clobbers any input of node *)
 | 
						|
let node_clobbers node v = 
 | 
						|
  List.exists (Variable.same_location v) node.input_variables
 | 
						|
 | 
						|
(* true if nodeb depends on nodea *)
 | 
						|
let depends_on nodea nodeb =
 | 
						|
  node_uses nodea.assigned nodeb ||
 | 
						|
  node_clobbers nodea nodeb.assigned
 | 
						|
 | 
						|
(* transform an assignment list into a dag *)
 | 
						|
let makedag alist =
 | 
						|
  let dag = List.map
 | 
						|
      (fun assignment ->
 | 
						|
	let (v, x) = assignment in
 | 
						|
	{ assigned = v;
 | 
						|
	  expression = x;
 | 
						|
	  input_variables = Expr.find_vars x;
 | 
						|
	  successors = [];
 | 
						|
	  predecessors = [];
 | 
						|
	  label = 0;
 | 
						|
	  color = BLACK })
 | 
						|
      alist
 | 
						|
  in begin
 | 
						|
    for_list dag (fun i ->
 | 
						|
	for_list dag (fun j ->
 | 
						|
	  if depends_on i j then begin
 | 
						|
	    i.successors <- j :: i.successors;
 | 
						|
	    j.predecessors <- i :: j.predecessors;
 | 
						|
	  end));
 | 
						|
    Dag dag;
 | 
						|
  end
 | 
						|
 | 
						|
let map f (Dag dag) = Dag (List.map f dag)
 | 
						|
let for_all (Dag dag) f = 
 | 
						|
  (* type system loophole *)
 | 
						|
  let make_unit _ = () in
 | 
						|
  make_unit (List.map f dag)
 | 
						|
let to_list (Dag dag) = dag
 | 
						|
 | 
						|
let find_node f (Dag dag) = Util.find_elem f dag
 | 
						|
 | 
						|
(* breadth-first search *)
 | 
						|
let rec bfs (Dag dag) node init_label =
 | 
						|
  let _ =  node.label <- init_label in
 | 
						|
  let rec loop = function
 | 
						|
      [] -> ()
 | 
						|
    | node :: rest ->
 | 
						|
	let neighbors = node.predecessors @ node.successors in
 | 
						|
	let m = min_list (List.map (fun node -> node.label) neighbors) in
 | 
						|
	if (node.label > m + 1) then begin
 | 
						|
	  node.label <- m + 1;
 | 
						|
	  loop (rest @ neighbors);
 | 
						|
	end else
 | 
						|
	  loop rest
 | 
						|
  in let neighbors = node.predecessors @ node.successors in
 | 
						|
  loop neighbors
 | 
						|
 |