File: default-block-placement.sml

package info (click to toggle)
mlton 20210117%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 58,464 kB
  • sloc: ansic: 27,682; sh: 4,455; asm: 3,569; lisp: 2,879; makefile: 2,347; perl: 1,169; python: 191; pascal: 68; javascript: 7
file content (105 lines) | stat: -rw-r--r-- 3,252 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
(* default-block-placement.sml
 *
 * COPYRIGHT (c) 2001 Bell Labs, Lucent Technologies
 *
 * Place blocks in an order that respects the FALLSTHRU and BRANCH(false)
 * edges and is otherwise the order of block generation.
 *)

functor DefaultBlockPlacement (CFG : CONTROL_FLOW_GRAPH) : BLOCK_PLACEMENT =
  struct

    structure CFG=CFG
    structure G = Graph

  (* flags *)
    val dumpBlocks = MLRiscControl.mkFlag (
	  "dump-block-list",
	  "whether block list is shown")
    val dumpCFG = MLRiscControl.mkFlag (
	  "dump-cfg-after-placement",
	  "whether CFG is shown after block placement")
    val dumpStrm = MLRiscControl.debug_stream

    fun blockToString (id', CFG.BLOCK{id, ...}) =
	  concat["<", Int.toString id', ":", Int.toString id, ">"]

    fun error msg = MLRiscErrorMsg.error ("DefaultBlockPlacement", msg)

    fun blockPlacement (cfg as G.GRAPH graph) = let
	  val placed = Array.array(#capacity graph (), false)
	  fun isMarked id = Array.sub(placed, id)
	  fun mark id = Array.update(placed, id, true)
	  fun assertNotMarked id = if isMarked id
		then error "conflicting placement constraints"
		else ()
	(* special case the entry and exit blocks *)
	  fun getBlk id = (id, #node_info graph id)
	  val entry = CFG.entry cfg
	  val exit = CFG.exit cfg
	  val _ = mark(#1 exit)	(* we place exit at the end *)
	(* return true if the edge must connect adjacent nodes *)
	  fun adjEdge (_, _, CFG.EDGE{k=CFG.FALLSTHRU, ...}) = true
	    | adjEdge (_, _, CFG.EDGE{k=CFG.BRANCH false, ...}) = true
	    | adjEdge _ = false
	  val findAdjEdge = List.find adjEdge
	(* place nodes by assuming that the initial order is close to
	 * correct.
	 *)
	  fun placeNodes ([], l) = List.rev (exit::l)
	    | placeNodes ((nd1 as (id1, b1))::r1, l) = if isMarked id1
		then placeNodes (r1, l)
		else (
		  case r1
		   of [] => List.rev (exit::nd1::l)
		    | (nd2 as (id2, b2))::r2 => if isMarked id2
			  then placeNodes(nd1::r2, l)
			  else (
			  (* Here we know that both nd1 and nd2 have not been
			   * placed.  We need to check for placement constraints
			   * in nd1's out edges and nd2's in edges.
			   *)
			    mark id1;
			    case findAdjEdge (#out_edges graph id1)
			     of NONE => let
				  fun pushPredChain (nd as (id, _), r) = (
					case findAdjEdge (#in_edges graph id)
					 of NONE => nd::r
					  | SOME(src, _, _) => (
					      assertNotMarked src;
					      pushPredChain (getBlk src, nd::r))
					(* end case *))
				  in
				    placeNodes (pushPredChain(nd2, r2), nd1::l)
				  end
			      | SOME(_, dst, _) => if (dst = id2)
				  then placeNodes(r1, nd1::l)
				  else (
				    assertNotMarked dst;
				    placeNodes (getBlk dst::r1, nd1::l))
			    (* end case *))
		    (* end case *))
	  val blocks = placeNodes (entry :: #nodes graph (), [])
	  in
	    if !dumpBlocks
	      then let
		fun say s = TextIO.output(!dumpStrm, s)
		in
		  say "Block placement order:\n";
		  List.app
		    (fn b => say(concat["  ", blockToString b, "\n"]))
		      blocks
		end
	      else ();
	    if !dumpCFG
	      then let
		val prBlock = CFG.dumpBlock (!dumpStrm, cfg)
		in
		  TextIO.output(!dumpStrm, "[ after block placement ]\n");
		  List.app prBlock blocks
		end
	      else ();
	    (cfg, blocks)
	  end

  end