mirror of
https://github.com/tildearrow/furnace.git
synced 2024-12-18 06:20:17 +00:00
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
|
||
|
|