1 (* Copyright (C
) 1999-2006 Henry Cejtin
, Matthew Fluet
, Suresh
2 * Jagannathan
, and Stephen Weeks
.
4 * MLton is released under a BSD
-style license
.
5 * See the file MLton
-LICENSE for details
.
8 structure DirectedSubGraph
: DIRECTED_SUB_GRAPH
=
13 datatype node
= Node
of {successors
: edge list ref
,
14 plist
: PropertyList
.t
}
15 and edge
= Edge
of {from
: node
,
17 plist
: PropertyList
.t
}
18 and graph
= T
of {nodes
: node list ref
,
25 datatype graph
= datatype Types
.graph
26 type node
= Types
.node
27 datatype t
= datatype Types
.edge
29 fun layout _
= Layout
.str
"edge"
32 fun make
sel (Edge r
) = sel r
35 val plist
= make #plist
38 val from
= fn (T
{nodeP
, edgeP
, ...}, e
) =>
39 (Assert
.assert("DirectedSubGraph.Edge.from", fn () => edgeP e
)
40 ; Assert
.assert("DirectedSubGraph.Edge.from", fn () => nodeP (from e
))
42 val to
= fn (T
{nodeP
, edgeP
, ...}, e
) =>
43 (Assert
.assert("DirectedSubGraph.Edge.to", fn () => edgeP e
)
44 ; Assert
.assert("DirectedSubGraph.Edge.to", fn () => nodeP (to e
))
47 fun new (T
{nodeP
, edgeP
, ...}, {from
, to
}) =
48 (Assert
.assert("DirectedSubGraph.Edge.new", fn () => nodeP from
)
49 ; Assert
.assert("DirectedSubGraph.Edge.new", fn () => nodeP to
)
52 plist
= PropertyList
.new ()})
54 fun equals (e
, e
') = PropertyList
.equals (plist e
, plist e
')
59 datatype graph
= datatype Types
.graph
60 type edge
= Types
.edge
61 datatype t
= datatype Types
.node
63 fun layout _
= Layout
.str
"node"
66 fun make
sel (Node r
) = sel r
68 val plist
= make #plist
69 val successors
' = make #successors
70 val successors
= ! o successors
'
72 val foreachSuccessor
= fn (T
{nodeP
, edgeP
, ...}, n
, f
) =>
73 (Assert
.assert("DirectedSubGraph.Node.foreachSuccessor", fn () => nodeP n
)
74 ; List.foreach(successors n
, fn e
=> if edgeP e
then f e
else ()))
75 val forallSuccessors
= fn (T
{nodeP
, edgeP
, ...}, n
, f
) =>
76 (Assert
.assert("DirectedSubGraph.Node.forallSuccessors", fn () => nodeP n
)
77 ; List.forall(successors n
, fn e
=> if edgeP e
then f e
else true))
78 val existsSuccessor
= fn (T
{nodeP
, edgeP
, ...}, n
, f
) =>
79 (Assert
.assert("DirectedSubGraph.Node.existsSuccessor", fn () => nodeP n
)
80 ; List.exists(successors n
, fn e
=> if edgeP e
then f e
else false))
81 val successors
= fn (T
{nodeP
, edgeP
, ...}, n
) =>
82 (Assert
.assert("DirectedSubGraph.Node.successors", fn () => nodeP n
)
83 ; List.keepAll(successors n
, fn e
=> edgeP e
))
86 fun new g
= Node
{successors
= ref
[],
87 plist
= PropertyList
.new ()}
89 fun equals (n
, n
') = PropertyList
.equals (plist n
, plist n
')
91 fun hasEdge (g
as T
{nodeP
, edgeP
, ...}, {from
, to
}) =
92 if nodeP from
andalso nodeP to
93 then existsSuccessor (g
, from
, fn e
=>
94 equals (to
, Edge
.to (g
, e
)))
97 (* fun removeSuccessor (Node
{successors
, ...}, n
) =
98 * successors
:= List.removeFirst (!successors
, fn Edge
.Edge
{to
, ...} =>
105 type t
= {startNode
: Node
.t
-> unit
,
106 finishNode
: Node
.t
-> unit
,
107 handleTreeEdge
: Edge
.t
-> unit
,
108 handleNonTreeEdge
: Edge
.t
-> unit
,
109 startTree
: Node
.t
-> unit
,
110 finishTree
: Node
.t
-> unit
,
111 finishDfs
: unit
-> unit
}
115 fun finishNode f
= {finishNode
= f
,
117 handleTreeEdge
= ignore
,
118 handleNonTreeEdge
= ignore
,
123 fun startNode f
= {finishNode
= ignore
,
125 handleTreeEdge
= ignore
,
126 handleNonTreeEdge
= ignore
,
131 fun seq f g a
= (f a
; g a
)
133 fun combine ({startNode
, finishNode
,
134 handleTreeEdge
, handleNonTreeEdge
,
135 startTree
, finishTree
, finishDfs
}: t
,
136 {startNode
= sn
, finishNode
= fin
,
137 handleTreeEdge
= ht
, handleNonTreeEdge
= hn
,
138 startTree
= st
, finishTree
= ft
, finishDfs
= fd
}: t
): t
=
139 {startNode
= seq startNode sn
,
140 finishNode
= seq finishNode fin
,
141 handleTreeEdge
= seq handleTreeEdge ht
,
142 handleNonTreeEdge
= seq handleNonTreeEdge hn
,
143 startTree
= seq startTree st
,
144 finishTree
= seq finishTree ft
,
145 finishDfs
= seq finishDfs fd
}
148 (*---------------------------------------------------*)
150 (*---------------------------------------------------*)
152 datatype t
= datatype Types
.graph
154 (*--------------------------------------------------------*)
156 (*--------------------------------------------------------*)
159 fun foreachNode (g
, f
) = List.foreach (nodes g
, f
)
162 fun foreachNode (g
as T
{nodes
, nodeP
, ...}, f
)
163 = List.foreach (!nodes
, fn n
=> if nodeP n
then f n
else ())
166 fun foreachEdge (g
, f
) =
167 foreachNode (g
, fn n
=> List.foreach (Node
.successors (g
, n
), fn e
=> f (n
, e
)))
170 fun foreachEdge (g
, f
) =
171 foreachNode (g
, fn n
=> Node
.foreachSuccessor (g
, n
, fn e
=> f (n
, e
)))
173 (*--------------------------------------------------------*)
175 (*--------------------------------------------------------*)
177 fun subGraph (g
as T
{nodes
, nodeP
, edgeP
, ...},
178 {nodeP
= nodeP
', edgeP
= edgeP
'}) =
180 val nodeP
= fn n
=> if nodeP n
then nodeP
' n
else false
181 val edgeP
= fn e
=> if edgeP e
then edgeP
' e
else false
184 ("DirectedSubGraph.subGraph", fn () =>
185 List.forall(!nodes
, fn n
=>
187 then Node
.forallSuccessors(g
, n
, fn e
=>
188 nodeP (Edge
.to (g
, e
)))
191 T
{nodes
= nodes
, nodeP
= nodeP
, edgeP
= edgeP
}
194 fun supGraph (g
as T
{nodes
, ...}) =
195 T
{nodes
= nodes
, nodeP
= fn _
=> true, edgeP
= fn _
=> true}
197 fun nodes (T
{nodes
, nodeP
, ...}) = List.keepAll(!nodes
, nodeP
)
199 fun new () = T
{nodes
= ref
[], nodeP
= fn _
=> true, edgeP
= fn _
=> true}
201 fun newNode (g
as T
{nodes
, ...}) =
202 let val n
= Node
.new g
203 in List.push (nodes
, n
)
207 fun addEdge (g
as T
{nodeP
, ...}, e
as {from
, to
}) =
208 let val _
= Assert
.assert("DirectedSubGraph.addEdge", fn () => nodeP from
andalso nodeP to
)
209 val e
= Edge
.new (g
, e
)
211 List.push (Node
.successors
' from
, e
)
215 (*fun removeEdge (_
, {from
, to
}) = Node
.removeSuccessor (from
, to
) *)
217 fun layoutDot (g
, {edgeOptions
: Edge
.t
-> Dot
.EdgeOption
.t list
,
218 nodeOptions
: Node
.t
-> Dot
.NodeOption
.t list
,
222 val c
= Counter
.new
0
223 val {get
= nodeId
, destroy
, ...} =
227 (fn _
=> concat
["n", Int.toString (Counter
.next c
)]))
231 fn n
=> {name
= nodeId n
,
232 options
= nodeOptions n
,
233 successors
= List.revMap
234 (Node
.successors (g
, n
), fn e
=>
235 {name
= nodeId (Edge
.to (g
, e
)),
236 options
= edgeOptions e
})})
238 Dot
.layout
{nodes
= nodes
,
246 (*--------------------------------------------------------*)
247 (* Depth
-First Search
*)
248 (*--------------------------------------------------------*)
250 fun dfsNodes (g
as T
{nodeP
, ...}, ns
,
251 {startNode
, finishNode
,
252 handleTreeEdge
, handleNonTreeEdge
,
253 startTree
, finishTree
, finishDfs
}) =
255 val {get
= hasBeenVisited
, set
= setVisited
, destroy
, ...} =
256 Property
.destGetSet (Node
.plist
, Property
.initConst
false)
258 (Assert
.assert("DirectedSubGraph.dfsNodes", fn () => nodeP n
)
260 ; setVisited (n
, true)
261 ; Node
.foreachSuccessor (g
, n
, fn e
=>
262 let val n
' = Edge
.to (g
, e
)
263 in if hasBeenVisited n
'
264 then handleNonTreeEdge e
265 else (visit n
'; handleTreeEdge e
)
268 in List.foreach (ns
, fn n
=>
269 (Assert
.assert("DirectedSubGraph.dfsNodes", fn () => nodeP n
)
270 ; if hasBeenVisited n
272 else (startTree n
; visit n
; finishTree n
)))
277 fun dfs (g
, p
) = dfsNodes (g
, nodes g
, p
)
279 fun display
{graph
, layoutNode
, display
} =
283 display
let open Layout
284 in seq
[layoutNode n
,
286 list (List.revMap (Node
.successors (graph
, n
),
287 fn e
=> layoutNode (Edge
.to (graph
, e
))))]
290 fun foreachDescendent (g
, n
, f
) =
291 dfsNodes (g
, [n
], DfsParam
.finishNode f
)
293 (* fun removeBackEdges g
=
295 * val discoverTime
= Counter
.new
0
296 * val {get
, destroy
, ...} =
298 * (Node
.plist
, Property
.initFun (fn _
=> {time
= Counter
.next discoverTime
,
299 * alive
= ref
true}))
300 * val ignore
= DfsParam
.ignore
302 * (g
, {startNode
= fn n
=> (get n
; ()),
303 * finishNode
= fn n
=> #
alive (get n
) := false,
304 * handleNonTreeEdge
=
305 * fn e
as Edge
.Edge
{from
, to
, ...} =>
306 * let val {alive
, time
} = get to
307 * in if !alive
andalso time
< #
time (get from
)
308 * then removeEdge (g
, e
)
311 * handleTreeEdge
= ignore
,
312 * startTree
= ignore
,
313 * finishTree
= ignore
,
314 * finishDfs
= ignore
})
318 (*--------------------------------------------------------*)
320 (*--------------------------------------------------------*)
322 fun discoverFinishTimes g
=
323 let val time
: int ref
= ref
0
324 val {get
= discover
, set
= setDiscover
, destroy
= destroyDiscover
, ...} =
325 Property
.destGetSetOnce (Node
.plist
,
326 Property
.initRaise ("discover", Node
.layout
))
327 val {get
= finish
, set
= setFinish
, destroy
= destroyFinish
, ...} =
328 Property
.destGetSetOnce (Node
.plist
,
329 Property
.initRaise ("finish", Node
.layout
))
330 in {destroy
= fn () => (destroyDiscover (); destroyFinish ()),
333 param
= {startNode
= fn n
=> (Int.inc time
; setDiscover (n
, !time
)),
334 finishNode
= fn n
=> (Int.inc time
; setFinish (n
, !time
)),
335 handleTreeEdge
= DfsParam
.ignore
,
336 handleNonTreeEdge
= DfsParam
.ignore
,
337 startTree
= DfsParam
.ignore
,
338 finishTree
= DfsParam
.ignore
,
339 finishDfs
= DfsParam
.ignore
}}
342 (*--------------------------------------------------------*)
344 (*--------------------------------------------------------*)
346 fun maxNumEdges n
= n
* (n
- 1)
348 fun random
{numNodes
,numEdges
} =
349 let val max
= maxNumEdges numNodes
350 in if numNodes
< 0 orelse numEdges
< 0 orelse numEdges
> max
351 then Error
.error
"random"
352 else let val g
= new ()
353 val needed
= ref numEdges
354 val remaining
= ref max
355 fun maybeAddEdge (n
,n
') =
356 (if Int.random (1, !remaining
) <= !needed
357 then (addEdge (g
, Node
.fromInt n
, Node
.fromInt n
')
360 ; IntRef
.dec remaining
)
362 val maxNode
= numNodes
- 1
364 Int.foreach (0, maxNode
, fn n
' =>
365 if n
= n
' then () else maybeAddEdge (n
,n
'))
367 Int.foreach (n
+ 1, maxNode
, fn n
' => maybeAddEdge (n
,n
'))
368 val addEdges
= if isDirected
then directed
370 in Int.foreach (minNode
, maxNode
, addEdges
)
375 (*--------------------------------------------------------*)
377 (*--------------------------------------------------------*)
380 let val {get
= isActive
, set
= setActive
} =
381 nodeInfo (g
, fn _
=> false)
382 val cycle
= ref
false
383 in (cycle
, {startNode
= fn n
=> setActive (n
, true),
384 finishNode
= fn n
=> setActive (n
, false),
386 fn (n
, e
) => let val n
' = Edge
.otherNode (e
,n
)
387 in if isActive n
' then cycle
:= true
390 handleTreeEdge
= DfsParam
.ignore
,
391 startTree
= DfsParam
.ignore
,
392 finishTree
= DfsParam
.ignore
,
393 finishDfs
= DfsParam
.ignore
})
396 fun isCyclic g
= let val (cycle
, p
) = cycleParam g
397 in dfs (g
, p
); !cycle
401 (*--------------------------------------------------------*)
402 (* Topological Sort
*)
403 (*--------------------------------------------------------*)
405 exception TopologicalSort
409 val {get
= amVisiting
, set
= setVisiting
, destroy
, ...} =
410 Property
.destGetSet (Node
.plist
,
411 Property
.initRaise ("visiting", Node
.layout
))
413 in (ns
, {startNode
= fn n
=> amVisiting n
:= true,
414 finishNode
= fn n
=> (amVisiting n
:= false; List.push (ns
,n
)),
415 handleNonTreeEdge
= fn e
=> if !(amVisiting(Edge
.to (g
, e
)))
416 then raise TopologicalSort
418 startTree
= DfsParam
.ignore
, finishTree
= DfsParam
.ignore
,
419 handleTreeEdge
= DfsParam
.ignore
,
420 finishDfs
= destroy
})
423 fun topologicalSort g
= let val (ns
, p
) = topSortParam g
427 (*--------------------------------------------------------*)
429 (*--------------------------------------------------------*)
431 fun transposeParam g
=
433 fun handleEdge (n
, e
) = let val n
' = Edge
.otherNode (e
,n
)
434 in addEdge (gt
,n
',n
); ()
436 in (gt
, {handleTreeEdge
= handleEdge
,
437 handleNonTreeEdge
= handleEdge
,
438 finishDfs
= DfsParam
.ignore
,
439 startNode
= DfsParam
.ignore
, finishNode
= DfsParam
.ignore
,
440 startTree
= DfsParam
.ignore
, finishTree
= DfsParam
.ignore
})
443 fun transpose g
= let val (gt
, p
) = transposeParam g
447 (*--------------------------------------------------------*)
448 (* Strongly Connected Components
*)
449 (*--------------------------------------------------------*)
451 (* from Cormen
, Leiserson
, and Rivest
23.5 *)
455 val (gt
, p
) = transposeParam g
457 val p
' = P
.finishNode (fn n
=> List.push (ns
,n
))
458 val components
= ref
[]
459 val component
= ref
[]
460 fun startNode n
= List.push (component
,n
)
461 fun startTree _
= component
:= []
462 fun finishTree _
= List.push (components
, !component
)
463 val pt
= {startNode
= startNode
,
464 startTree
= startTree
,
465 finishTree
= finishTree
,
466 finishNode
= DfsParam
.ignore
,
467 finishDfs
= DfsParam
.ignore
,
468 handleTreeEdge
= DfsParam
.ignore
,
469 handleNonTreeEdge
= DfsParam
.ignore
}
470 in dfs (g
, P
.combine (p
, p
'))
471 ; dfsNodes (gt
, !ns
, pt
)
476 (* from Aho
, Hopcroft
, Ullman section
5.5 *)
478 fun stronglyConnectedComponents g
=
480 val {get
= discover
: Node
.t
-> int, set
= setDiscover
,
481 destroy
= destroyDiscover
, ...} =
482 Property
.destGetSetOnce (Node
.plist
,
483 Property
.initRaise ("discover", Node
.layout
))
484 val {get
= low
: Node
.t
-> int ref
, destroy
= destroyLow
, ...} =
485 Property
.destGet (Node
.plist
, Property
.initFun (fn _
=> ref ~
1))
486 val {get
= isOnStack
: Node
.t
-> bool, set
= setOnStack
,
487 destroy
= destroyStack
, ...} =
488 Property
.destGetSet (Node
.plist
,
489 Property
.initRaise ("isOnStack", Node
.layout
))
491 val components
= ref
[]
493 fun pop () = let val n
= List.pop stack
494 in setOnStack (n
, false); n
496 fun popTo n
= let fun popTo () = let val n
' = pop ()
497 in if Node
.equals (n
,n
') then [n
]
498 else n
' :: (popTo ())
502 fun startNode n
= (Int.inc time
503 ; setDiscover (n
, !time
)
505 ; setOnStack (n
, true)
506 ; List.push (stack
, n
))
507 fun finishNode n
= if discover n
= ! (low n
)
508 then List.push (components
, popTo n
)
511 let val from
= Edge
.from (g
, e
)
512 val to
= Edge
.to (g
, e
)
519 val handleTreeEdge
= updateLow
520 fun handleNonTreeEdge e
=
521 if isOnStack (Edge
.to (g
, e
))
524 val p
= {startNode
= startNode
, finishNode
= finishNode
,
525 handleTreeEdge
= handleTreeEdge
,
526 handleNonTreeEdge
= handleNonTreeEdge
,
527 startTree
= DfsParam
.ignore
, finishTree
= DfsParam
.ignore
,
528 finishDfs
= DfsParam
.ignore
}
536 (*--------------------------------------------------------*)
538 (*--------------------------------------------------------*)
540 (* This is an implementation
of the Lengauer
/Tarjan dominator algorithm
, as
541 * described on p
. 185-191 of Muchnick
's
"Advanced Compiler Design and
546 type t
= {ancestor
: Node
.t ref
,
547 bucket
: Node
.t list ref
,
549 dfn
: int ref
, (* depth first number
*)
553 preds
: Node
.t list ref
,
554 sdno
: int ref
, (* semidominator dfn
*)
558 fun validDominators (graph
,
560 idom
: Node
.t
-> Node
.t
}): bool =
561 (* Check for each edge v
--> w that idom w dominates v
.
562 * FIXME
: It should first check that idom describes a tree rooted at root
.
567 fun dominates (a
: Node
.t
, b
: Node
.t
): bool =
571 orelse (not (Node
.equals (b
, root
))
572 andalso loop (idom b
))
576 foreachEdge (graph
, fn (_
, Edge
.Edge
{from
, to
, ...}) =>
577 if dominates (idom to
, from
)
583 fun dominators (graph
, {root
}) =
586 fun newNode (n
: Node
.t
): NodeInfo
.t
=
597 val {get
= nodeInfo
: Node
.t
-> NodeInfo
.t
, ...} =
598 Property
.get (Node
.plist
, Property
.initFun newNode
)
600 fun 'a
make (sel
: NodeInfo
.t
-> 'a ref
) =
601 (sel
o nodeInfo
, ! o sel
o nodeInfo
)
603 val (ancestor
', ancestor
) = make #ancestor
604 val (bucket
', bucket
) = make #bucket
605 val (child
', child
) = make #child
606 val (dfn
', dfn
) = make #dfn
607 val (idom
', idom
) = make #idom
608 val (label
', label
) = make #label
609 val (parent
', parent
) = make #parent
610 val (preds
', preds
) = make #preds
611 val (sdno
', sdno
) = make #sdno
612 val (size
', size
) = make #size
614 val _
= size
' n0
:= 0
615 (* nodes is an array
of nodes indexed by dfs number
. *)
616 val numNodes
= List.length (nodes graph
)
617 val nodes
= Array
.new (numNodes
, n0
)
618 fun ndfs i
= Array
.sub (nodes
, i
)
619 val dfnCounter
= ref
0
620 fun dfs (v
: Node
.t
): unit
=
623 val _
= Int.inc dfnCounter
626 val _
= Array
.update (nodes
, i
, v
)
628 Node
.foreachSuccessor
631 val w
= Edge
.to (graph
, e
)
632 val _
= List.push (preds
' w
, v
)
642 if !dfnCounter
= numNodes
644 else Error
.bug
"DirectedSubGraph.dominators: graph is not connected"
645 (* compress ancestor path to node v to the node whose label has the
646 * maximal (minimal?
) semidominator number
.
648 fun compress (v
: Node
.t
): unit
=
649 if Node
.equals (n0
, ancestor (ancestor v
))
652 val _
= compress (ancestor v
)
654 if sdno (label (ancestor v
)) < sdno (label v
)
655 then label
' v
:= label (ancestor v
)
657 val _
= ancestor
' v
:= ancestor (ancestor v
)
660 fun eval (v
: Node
.t
): Node
.t
=
661 (* Determine the ancestor
of v whose semidominator has the minimal
662 * depth
-first number
.
664 if Node
.equals (ancestor v
, n0
)
669 if sdno (label (ancestor v
)) >= sdno (label v
)
671 else label (ancestor v
)
673 fun link (v
: Node
.t
, w
: Node
.t
): unit
=
676 if sdno (label w
) < sdno (label (child s
))
678 if size s
+ size (child (child s
)) >= 2 * size (child s
)
679 then (ancestor
' (child s
) := s
680 ; child
' s
:= child (child s
)
682 else (size
' (child s
) := size s
683 ; ancestor
' s
:= child s
687 val _
= label
' s
:= label w
688 val _
= size
' v
:= size v
+ size w
690 if size v
< 2 * size w
694 val _
= child
' v
:= s
699 if Node
.equals (s
, n0
)
701 else (ancestor
' s
:= v
708 (1, numNodes
, fn i
=>
710 (* Compute initial values for semidominators
and store nodes
with
711 * the same semidominator
in the same bucket
.
714 val min
= List.fold (preds w
, sdno w
, fn (n
, min
) =>
715 Int.min (min
, sdno (eval n
)))
716 val _
= sdno
' w
:= min
717 val _
= List.push (bucket
' (ndfs min
), w
)
718 val _
= link (parent w
, w
)
719 (* Compute immediate dominators for nodes
in the bucket
of w
's
724 (bucket (parent w
), fn v
=>
728 idom
' v
:= (if sdno u
< sdno v
732 val _
= bucket
' (parent w
) := []
735 (* Adjust immediate dominators
of nodes whose current version
of the
736 * immediate dominator differs from the node
with the depth
-first number
737 * of the node
's semidominator
.
741 (1, numNodes
, fn i
=>
745 if Node
.equals (idom w
, ndfs (sdno w
))
747 else idom
' w
:= idom (idom w
)
749 val _
= idom
' root
:= root
750 val _
= Assert
.assert ("DirectedSubGraph.dominators", fn () =>
751 validDominators (graph
, {root
= root
,
756 fun dominatorTree (graph
, {root
: Node
.t
, nodeValue
: Node
.t
-> 'a
}): 'a Tree
.t
=
758 val {idom
} = dominators (graph
, {root
= root
})
759 val {get
= nodeInfo
, ...} =
760 Property
.get (Node
.plist
,
761 Property
.initFun (fn n
=> {children
= ref
[],
762 value
= nodeValue n
}))
766 if Node
.equals (n
, root
)
768 else List.push (#
children (nodeInfo (idom n
)), n
))
769 fun treeAt (n
: Node
.t
): 'a Tree
.t
=
771 val {children
, value
} = nodeInfo n
773 Tree
.T (value
, Vector.fromListMap (!children
, treeAt
))
779 (*--------------------------------------------------------*)
781 (*--------------------------------------------------------*)
783 (* This is an implementation
of the G
. Ramalingam loop forest construction
,
784 * as described
in "On Loops, Dominators, and Dominance Frontiers"
785 * (originally
in PLDI00
; revised technical report at
786 * http
://www
.research
.ibm
.com
/people
/r
/rama
/Papers
/ibmtr21513
.revised
.ps
).
789 structure GraphNodeInfo
=
791 type t
= {forestNode
: Node
.t
}
794 structure ForestNodeInfo
=
796 type t
= {parent
: Node
.t option
,
797 loopNodes
: Node
.t list
}
800 structure SubGraphNodeInfo
=
802 type t
= {childSubGraphNode
: Node
.t option ref
,
806 (* loopForest
: {headers
: (* graph
*) Node
.t list
-> (* graph
*) Node
.t list
,
808 * root
: (* graph
*) Node
.t
}
810 * graphToForest
: (* graph
*) Node
.t
-> (* forest
*) Node
.t
,
811 * loopNodes
: (* forest
*) Node
.t
-> (* graph
*) Node
.t list
,
812 * parent
: (* forest
*) Node
.t
-> (* forest
*) Node
.t option
}
814 * Inputs
: graph
-- a rooted control flow graph
815 * root
-- the root
of graph
816 * headers
-- a function mapping strongly connected components
of graph
817 * to a set
of header nodes
818 * Outputs
: forest
-- the loop nesting forest
819 * "Consider any loop L. Let G_L denote the subgraph induced by
820 * the vertices in L, but without the loopback edges of L.
821 * The 'children' of L in the 'forest' representation are
822 * the strongly connected components of G_L. The non-trivial
823 * strongly connected components of G_L denote inner loops
824 * (which become internal nodes in the 'forest' representation),
825 * while the trivial strongly connected components of G_L
826 * denote vertices belonging to L but not to any inner loop of L,
827 * and these become 'leaves' of the 'forest'."
828 * graphToForest
-- maps a node
in graph to it
's corresponding leaf
in forest
829 * headers
-- a function mapping strongly connected components
of graph
830 * to a set
of header nodes
; compose
with loopNodes to get
831 * the loop headers
of an internal node
in the forest
832 * isHeader
-- predicate indicating that the node is the header for some loop
833 * loopNodes
-- maps an internal node
in the forest to a set
of nodes
834 * in graph that compose a loop
835 * parent
-- maps a node
in forest to it
's parent
in forest
839 fun loopForest
{headers
, graph
, root
}
841 val addEdge
= ignore
o addEdge
843 val {get
= graphNodeInfo
: Node
.t
-> GraphNodeInfo
.t
,
844 set
= setGraphNodeInfo
, ...}
845 = Property
.getSetOnce
846 (Node
.plist
, Property
.initRaise ("graphNodeInfo", Node
.layout
))
847 val forestNode
= #forestNode
o graphNodeInfo
849 val {get
= forestNodeInfo
: Node
.t
-> ForestNodeInfo
.t
,
850 set
= setForestNodeInfo
, ...}
851 = Property
.getSetOnce
852 (Node
.plist
, Property
.initRaise ("forestNodeInfo", Node
.layout
))
853 val parent
= #parent
o forestNodeInfo
854 val loopNodes
= #loopNodes
o forestNodeInfo
857 val {get
= nodeNesting
: Node
.t
-> int list ref
,
858 destroy
= destNodeNesting
, ...}
860 (Node
.plist
, Property
.initFun (fn _
=> ref
[]))
861 val {get
= edgeNesting
: Edge
.t
-> int list ref
,
862 destroy
= destEdgeNesting
, ...}
864 (Edge
.plist
, Property
.initFun (fn _
=> ref
[]))
866 val {get
= getIsHeader
: Node
.t
-> bool ref
, ...}
868 (Node
.plist
, Property
.initFun (fn _
=> ref
false))
875 fun nodeP n
= fn node
=> case !(nodeNesting node
)
878 fun edgeP n
= fn edge
=> case !(edgeNesting edge
)
883 fun inducedGraph
{graph
, scc
}
886 val headers
= headers scc
887 val _
= List.foreach(headers
, fn header
=> getIsHeader header
:= true)
891 fn n
=> (List.push(nodeNesting n
, depth
) ;
892 Node
.foreachSuccessor
896 val to
= Edge
.to (graph
, e
)
898 if List.contains(scc
, to
, Node
.equals
)
900 not (List.contains(headers
, to
, Node
.equals
))
901 then List.push(edgeNesting e
, depth
)
904 subGraph (supGraph graph
, {nodeP
= nodeP depth
, edgeP
= edgeP depth
})
907 fun nest
{graph
, parent
}
909 (stronglyConnectedComponents graph
,
914 val _
= setForestNodeInfo(n
', {loopNodes
= scc
,
917 val _
= Int.inc depth
918 val graph
' = inducedGraph
{graph
= graph
,
920 val _
= nest
{graph
= graph
',
924 fn n
=> (Node
.foreachSuccessor
926 fn e
=> ignore(List.pop(edgeNesting e
)));
927 ignore(List.pop(nodeNesting n
))))
928 val _
= Int.dec depth
936 setForestNodeInfo (n
', {loopNodes
= [n
],
938 setGraphNodeInfo (n
, {forestNode
= n
'})
943 | SOME parent
=> addEdge (F
, {from
= parent
, to
= n
'}) ;
945 of [n
] => if Node
.hasEdge (graph
, {from
= n
, to
= n
})
955 fn n
=> (List.push(nodeNesting n
, depth
) ;
956 Node
.foreachSuccessor
957 (graph
, n
, fn e
=> List.push(edgeNesting e
, depth
))))
958 val graph
' = subGraph (supGraph graph
,
959 {nodeP
= nodeP depth
, edgeP
= edgeP depth
})
960 val _
= nest
{graph
= graph
', parent
= NONE
}
961 val _
= destNodeNesting ()
962 val _
= destEdgeNesting ()
965 graphToForest
= forestNode
,
967 isHeader
= ! o getIsHeader
,
968 loopNodes
= loopNodes
,
973 fun loopForest
{headers
, graph
, root
}
975 val addEdge
= ignore
o addEdge
977 val {get
= graphNodeInfo
: Node
.t
-> GraphNodeInfo
.t
,
978 set
= setGraphNodeInfo
, ...}
979 = Property
.getSetOnce
980 (Node
.plist
, Property
.initRaise ("graphNodeInfo", Node
.layout
))
981 val forestNode
= #forestNode
o graphNodeInfo
983 val {get
= getIsHeader
: Node
.t
-> bool ref
,
984 set
= setIsHeader
, ...}
985 = Property
.getSetOnce
986 (Node
.plist
, Property
.initFun (fn _
=> ref
false))
988 val {get
= forestNodeInfo
: Node
.t
-> ForestNodeInfo
.t
,
989 set
= setForestNodeInfo
, ...}
990 = Property
.getSetOnce
991 (Node
.plist
, Property
.initRaise ("forestNodeInfo", Node
.layout
))
992 val parent
= #parent
o forestNodeInfo
993 val loopNodes
= #loopNodes
o forestNodeInfo
995 val {get
= subGraphNodeInfo
: Node
.t
-> SubGraphNodeInfo
.t
,
996 set
= setSubGraphNodeInfo
, ...}
997 = Property
.getSetOnce
998 (Node
.plist
, Property
.initRaise ("subGraphNodeInfo", Node
.layout
))
999 val childSubGraphNode
= #childSubGraphNode
o subGraphNodeInfo
1000 val childSubGraphNode
' = ! o childSubGraphNode
1001 val childSubGraphNode
'' = valOf
o childSubGraphNode
'
1002 val graphNode
= #graphNode
o subGraphNodeInfo
1006 fun subGraph
{graph
,
1009 val scc
' = List.map(scc
, #graphNode
o subGraphNodeInfo
)
1010 val headers
= headers scc
'
1011 val _
= List.foreach
1012 (headers
, fn header
=> getIsHeader header
:= true)
1019 val n
' = newNode graph
'
1021 val {childSubGraphNode
, graphNode
, ...}
1022 = subGraphNodeInfo n
1024 childSubGraphNode
:= SOME n
' ;
1027 {childSubGraphNode
= ref NONE
,
1028 graphNode
= graphNode
})
1032 fn n
=> Node
.foreachSuccessor
1036 val to
= Edge
.to (graph
, e
)
1039 (scc
, to
, Node
.equals
)
1042 (headers
, graphNode to
, Node
.equals
))
1044 val from
' = childSubGraphNode
'' from
1045 val to
' = childSubGraphNode
'' to
1047 addEdge (graph
', {from
= from
', to
= to
'})
1054 fun nest
{graph
, parent
}
1056 (stronglyConnectedComponents graph
,
1058 val scc
' = List.map(scc
, graphNode
)
1062 val graph
' = subGraph
{graph
= graph
,
1065 setForestNodeInfo(n
', {loopNodes
= scc
',
1067 nest
{graph
= graph
',
1074 setForestNodeInfo (n
', {loopNodes
= [graphNode n
],
1076 setGraphNodeInfo (graphNode n
, {forestNode
= n
'})
1081 | SOME parent
=> addEdge (F
, {from
= parent
, to
= n
'}) ;
1083 of [n
] => if Node
.hasEdge (graph
, {from
= n
, to
= n
})
1092 val {get
= nodeInfo
': Node
.t
-> Node
.t
,
1096 Property
.initFun (fn node
=> let
1097 val node
' = newNode graph
'
1101 {childSubGraphNode
= ref NONE
,
1102 graphNode
= node
}) ;
1110 val from
' = nodeInfo
' from
1111 val to
= Edge
.to (graph
, e
)
1112 val to
' = nodeInfo
' to
1114 addEdge(graph
', {from
= from
', to
= to
'})
1120 val _
= nest
{graph
= graph
', parent
= NONE
}
1123 graphToForest
= forestNode
,
1125 isHeader
= ! o getIsHeader
,
1126 loopNodes
= loopNodes
,
1130 fun loopForestSteensgaard
{graph
, root
}
1134 val headers
= ref
[]
1137 (graph
, fn (n
, e
) => let
1138 val from
= Edge
.from (graph
, e
)
1139 val to
= Edge
.to (graph
, e
)
1141 if List.contains(X
, to
, Node
.equals
)
1143 not (List.contains(X
, from
, Node
.equals
))
1144 then List.push(headers
, to
)
1147 List.removeDuplicates(!headers
, Node
.equals
)
1160 val to
= Edge
.to (graph
, e
)
1162 if Node
.equals(node
, to
)
1164 List.contains(X
, to
, Node
.equals
)
1166 not (List.contains(X
, from
, Node
.equals
))
1173 loopForest
{headers
= headers
,