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 | ||
|  | 
 |