File: e-djgraph.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 (198 lines) | stat: -rw-r--r-- 7,336 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
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
186
187
188
189
190
191
192
193
194
195
196
197
198
(* 
 * This is my E-compressed DJ-graph data structure
 * --Allen
 *)

functor E_DJGraph (Dom : DOMINATOR_TREE) : DJ_GRAPH =
struct

   structure G       = Graph
   structure Dom     = Dom
   structure A       = Array

   fun error msg = MLRiscErrorMsg.error("E-DJGraph",msg)

   val stats          = false (* collect statistics? *)
   val visitCount     = MLRiscControl.getCounter "dj-visit-count"
   val idfCount       = MLRiscControl.getCounter "dj-IDF-count"
   val idfSize        = MLRiscControl.getCounter "dj-IDF-size"
   val liveVisitCount = MLRiscControl.getCounter "dj-live-visit-count"

   datatype tree = NODE of int * tree list

   datatype ('n,'e,'g) dj_graph = 
      DJGRAPH of
        { dom    : ('n,'e,'g) Dom.dominator_tree,
          trees  : tree option A.array,
          jedges : int list A.array
        }

   fun DJ(Dom as G.GRAPH dom) = 
   let val G.GRAPH cfg = Dom.cfg Dom
       val L           = Dom.max_levels Dom
       val N           = #capacity dom ()
       val levelsMap   = Dom.levelsMap Dom
       val rank_J      = A.array(N, 0)
       val trees       = A.array(N, NONE)
       val jedges      = A.array(N, [])
       val buckets     = A.array(L, [])

       fun ExitTrees a =   
       let fun foreachDedge [] = ()
             | foreachDedge((_,b,_)::es) = (ExitTrees b; foreachDedge es)
           val _     = foreachDedge (#out_edges dom a)
           val lvl_a = A.sub(levelsMap, a)
           fun foreachJedge([], rank) = A.update(rank_J,a,rank)
             | foreachJedge((a,b,_)::es, rank) = 
               let val lvl_b = A.sub(levelsMap, b)  
               in  if lvl_b <= lvl_a then 
                      foreachJedge(es, if lvl_b < rank then lvl_b else rank)
                   else 
                      foreachJedge(es, rank)
               end
           val _ = foreachJedge (#out_edges cfg a, L+1)
           fun buildTree([], succ) = NODE(a,succ)
             | buildTree((_,b,_)::es, succ) = 
               (case A.sub(trees, b) of
                  NONE   => buildTree(es, succ)
                | SOME t => buildTree(es, t::succ)
               )
           val t_a = buildTree(#out_edges dom a, []) 
       in  A.update(trees, a, pruneTree(A.sub(levelsMap, a), t_a))
       end

       and pruneTree(lvl_a, NODE(x,succ)) =
           let fun foreachSucc([], subtrees) = subtrees
                 | foreachSucc(t::ts, subtrees) = 
                     foreachSucc(ts, 
                        case pruneTree(lvl_a, t) of 
                           NONE => subtrees 
                         | SOME t => t::subtrees
                     )
               val subtrees = foreachSucc(succ, []) 
           in  case (A.sub(rank_J,x) <= lvl_a, subtrees) of
                 (false,[])  => NONE
               | (false,[t]) => SOME t
               | (_,ts)      => SOME(NODE(x,ts))
           end

       fun fillJedges l =
           if l < 0 then () else
           let fun fill [] = ()
                 | fill ((a,b)::es) = 
                    (A.update(jedges, a, b::A.sub(jedges, a)); fill es)   
           in  fill(A.sub(buckets, l));
               fillJedges(l-1)
           end

       val [ENTRY] = #entries dom ()
   in  ExitTrees ENTRY;
       fillJedges(L-1); 
       DJGRAPH{dom=Dom, trees=trees, jedges=jedges}
   end

   (* Compute dominance frontier *)
   fun DF _ = error "DF"

   (* Compute iterated dominance frontier *)
   fun IDFs _ = error "IDFs"

   (* Compute iterated dominance frontier with liveness *)
   fun LiveIDFs(DJGRAPH{dom=Dom as G.GRAPH dom, jedges, trees}) = 
   let val G.GRAPH cfg = Dom.cfg Dom
       val L           = Dom.max_levels Dom
       val N           = #capacity dom ()
       val levels      = Dom.levelsMap Dom
       val in_phi      = A.array(N,0)  (* has appeared in the DF set? *)
       val liveIn      = A.array(N,0)
       val stamp       = ref 0
       fun new_stamp() = let val s = !stamp + 1 in stamp := s; s end

       val in_alpha  = A.array(N,0)  (* has appeared in N_alpha? *)
       val visited   = A.array(N,0)  (* has it been visited *)
       val piggybank = A.array(L,[]) (* nodes in the piggy bank *)

       fun LiveIDFs{defs=xs, localLiveIn=[]} = []
         | LiveIDFs{defs=xs, localLiveIn} =
       let val stamp = new_stamp()
           val _ = if stats then idfCount := !idfCount + 1 else ()
           fun init([],l) = l
             | init(x::xs,l) = 
               let val l_x = A.sub(levels,x)
               in  A.update(in_alpha,x,stamp);
                   A.update(piggybank,l_x,x::A.sub(piggybank,l_x));
                   init(xs,if l < l_x then l_x else l)
               end 

           fun markLiveIn(b) =
           let fun markPred [] = ()
                 | markPred((j,_,_)::es) =
                    (if A.sub(liveIn,j) <> stamp andalso
                        A.sub(in_alpha,j) <> stamp then
                       markLiveIn j
                     else ();
                     markPred es
                    )
           in  A.update(liveIn,b,stamp);
               if stats then liveVisitCount := !liveVisitCount + 1 else ();
               markPred(#in_edges cfg b)
           end

           fun initLiveIn [] = ()
             | initLiveIn(x::xs) = (markLiveIn x; initLiveIn xs)

           fun isLive b = A.sub(liveIn,b) = stamp 

           fun visit(x,S) = 
               case A.sub(trees,x) of
                 NONE => S
               | SOME t => walk(t,A.sub(levels,x),S)

           and walk(NODE(y,succ_y),level_x,S) = 
           if A.sub(visited,y) <> stamp then
           let val _ = A.update(visited,y,stamp)
               fun foreachJedge([],S) = S
                 | foreachJedge(z::zs,S) =
                   let val level_z = A.sub(levels,z)
                   in  if level_z <= level_x then 
                          if isLive z andalso A.sub(in_phi,z) <> stamp 
                           (* z is a new IDF^+ candidate; 
                            * make sure it is live.
                            *)
                          then (A.update(in_phi,z,stamp);
                                if A.sub(in_alpha,z) <> stamp
                                then A.update(piggybank,level_z,
                                              z::A.sub(piggybank,level_z))
                                else ();
                                foreachJedge(zs,z::S)
                               )
                          else foreachJedge(zs,S)
                       else S
                   end
               fun foreachEedge([], S) = S
                 | foreachEedge((t as NODE(z,_))::ts,S) = 
                     foreachEedge(ts,if isLive z then walk(t,level_x,S) else S)

               val _ = if stats then visitCount := !visitCount + 1 else ();
           in  foreachEedge(succ_y, foreachJedge(A.sub(jedges, y),S))
           end
           else S

           fun visitAll(~1,S) = S
             | visitAll(l,S) =
               case A.sub(piggybank,l) of
                 [] => visitAll(l-1,S)
               | x::xs => (A.update(piggybank,l,xs);
                           visitAll(l,visit(x,S)))

           val L   = init(xs,~1) 
           val _   = initLiveIn localLiveIn
           val IDF = visitAll(L,[])
       in  if stats then idfSize := !idfSize + length IDF else ();
           IDF
       end

   in  LiveIDFs
   end

end