File: clusterGraph.sml

package info (click to toggle)
smlnj 110.79-8
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, sid
  • size: 82,564 kB
  • sloc: ansic: 32,532; asm: 6,314; sh: 2,296; makefile: 1,821; perl: 1,170; pascal: 295; yacc: 190; cs: 78; python: 77; lisp: 19
file content (185 lines) | stat: -rw-r--r-- 6,224 bytes parent folder | download | duplicates (7)
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
(*
 * This gives a cluster a graph view so that all graph based algorithms
 * can be applied on the cluster.  The view is readonly though.
 *
 * -- Allen
 *)
functor ClusterGraph(F : FLOWGRAPH) : CLUSTER_GRAPH =
struct

   structure F = F
   structure I = F.I
   structure W = F.W
   structure G = Graph
   structure A = Array

   datatype info = INFO of F.cluster * F.block A.array

   type block = F.block
   type edge_info = W.freq ref

   type cfg = (block,edge_info,info) Graph.graph

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

   fun table(G.GRAPH{graph_info=INFO(_,table),...}) = table
   fun cluster(G.GRAPH{graph_info=INFO(cluster,_),...}) = cluster

   (* In a cluster the basic blocks are numbered consecutively.
    *)
   fun isTakenBranch(i,j,_) = i+1 <> j 

   fun annotations(G.GRAPH{graph_info=INFO(F.CLUSTER{annotations=a, ...},_),
                      ...}) = a
   (*
    * Extract the node frequency of a block
    *)
   fun freq(F.BBLOCK{freq,...}) = freq
     | freq(F.ENTRY{freq,...})  = freq
     | freq(F.EXIT{freq,...})   = freq
     | freq _ = error "freq"

   (*
    * Extract the instructions 
    *)
   fun insns(F.BBLOCK{insns, ...}) = insns
     | insns _ = error "insns"

   (*
    * Extract the liveOut set
    *)
   fun liveOut(F.BBLOCK{liveOut, ...}) = !liveOut
     | liveOut _ = I.C.empty

   fun clusterGraph(cluster as F.CLUSTER{blocks,blkCounter,exit,entry,...}) =
   let fun readonly _ = raise G.Readonly
       fun do_nothing _ = ()
       val table = A.array(!blkCounter,F.LABEL(Label.newLabel "dummy"))
       fun number(F.BBLOCK{blknum,...}) = blknum
         | number(F.ENTRY{blknum,...}) = blknum
         | number(F.EXIT{blknum,...}) = blknum
         | number _ = raise G.Graph "clusterGraph"
       fun fill([],size,order,entry,exit) = (size,order,entry,exit)
         | fill((b as F.ENTRY{blknum,succ,...})::rest,size,order,entry,exit) =
             (A.update(table,blknum,b); 
              fill(rest,size+length(!succ),order+1,blknum,exit)
             )
         | fill((b as F.EXIT{blknum,...})::rest,size,order,entry,exit) =
             (A.update(table,blknum,b); 
              fill(rest,size,order+1,entry,blknum)
             )
         | fill((b as F.BBLOCK{blknum,succ,...})::rest,size,order,entry,exit) =
             (A.update(table,blknum,b); 
              fill(rest,size+length(!succ),order+1,entry,exit)
             )
         | fill(_::rest,size,order,entry,exit) =
             fill(rest,size,order,entry,exit)
       val (size,order,entryId,exitId) = fill(entry::exit::blocks,0,0,~1,~1)
       fun nodes() = A.foldri(fn (_,F.LABEL _,rest) => rest
                               | (b,b',rest) => (b,b')::rest) [] (table,0,NONE)
       fun edges() = 
       let fun f(i,succ,es) = 
              foldr (fn ((j,e),es) => (i,number j,e)::es) es (!succ)
       in  A.foldri
           (fn (i,F.BBLOCK{succ,...},es) => f(i,succ,es)
             | (i,F.ENTRY{succ,...},es) => f(i,succ,es)
             | (_,_,es) => es) [] (table,0,NONE)
       end    

       fun out_edges i = 
       let fun f succ = map (fn (j,e) => (i,number j,e)) (!succ)
       in  case A.sub(table,i) of
               F.BBLOCK{succ,...} => f succ
            |  F.ENTRY{succ,...} => f succ
            |  _ => []
       end

       fun in_edges j = 
       let fun f pred = map (fn (i,e) => (number i,j,e)) (!pred)
       in  case A.sub(table,j) of
               F.BBLOCK{pred,...} => f pred
            |  F.EXIT{pred,...} => f pred
            |  _ => []
       end

       fun succ i =
       let fun f succ = map (fn (j,e) => number j) (!succ)
       in  case A.sub(table,i) of
               F.BBLOCK{succ,...} => f succ
            |  F.ENTRY{succ,...} => f succ
            |  _ => []
       end
          
       fun pred j = 
       let fun f pred = map (fn (i,e) => number i) (!pred)
       in  case A.sub(table,j) of
               F.BBLOCK{pred,...} => f pred
            |  F.EXIT{pred,...} => f pred
            |  _ => []
       end

       fun has_edge(i,j) =
       let fun find [] = false
             | find((k,_)::es) = j = number k orelse find es
       in  case A.sub(table,i) of
               F.BBLOCK{succ,...} => find(!succ)
            |  F.ENTRY{succ,...} => find(!succ)
            |  _ => false
       end handle _ => false

       fun has_node i =
           (case A.sub(table,i) of
              F.BBLOCK _ => true
            | F.ENTRY _ => true
            | F.EXIT _ => true
            | _ => false
           ) handle _ => false

       fun node_info i = A.sub(table,i) handle _ => raise G.NotFound

       fun empty _ = []
       fun forall_nodes f =
           A.appi (fn (i,i' as F.LABEL _) => ()
                    | (i,i') => f(i,i')) (table,0,NONE)
       fun forall_edges f =
       let fun g(_,[]) = ()
             | g(i,(j,e)::es) = (f(i,number j,e); g(i,es))
       in  A.appi (fn (i,F.BBLOCK{succ,...}) => g(i,!succ) 
                    | (i,F.ENTRY{succ,...}) => g(i,!succ)
                    | _ => ()) (table,0,NONE)
       end

   in  G.GRAPH
       {  name            = "cluster",
          graph_info      = INFO(cluster,table),
          new_id          = readonly,
          add_node        = readonly,
          add_edge        = readonly,
          remove_node     = readonly,
          set_out_edges   = readonly,
          set_in_edges    = readonly,
          set_entries     = readonly,
          set_exits       = readonly,
          garbage_collect = do_nothing,
          nodes           = nodes,
          edges           = edges,
          order           = fn _ => order,
          size            = fn _ => size,
          capacity        = fn _ => !blkCounter,
          succ            = succ,
          pred            = pred,
          out_edges       = out_edges,
          in_edges        = in_edges,
          has_edge        = has_edge,
          has_node        = has_node,
          node_info       = node_info,
          entries         = fn _ => [entryId],
          exits           = fn _ => [exitId],
          entry_edges     = empty,
          exit_edges      = empty,
          forall_nodes    = forall_nodes,
          forall_edges    = forall_edges
       }
   end

end