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