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