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
|
(*
* This is Reif and Tarjan's algorithm (SIAM J Computing 1981)
* for computing approximate birthpoints for expressions.
* For each basic block B,
* idef(x) = { defs(v_i) | i = 1 ... n in all paths
* idom(x) v_1 v_2 ... v_n x where n >= 1 and
* v_i <> idom(x) for all 1 <= i <= n
* }
* -- Allen
*)
structure IDefs : IDEFS =
struct
structure G = Graph
structure SL = SortedList
structure A = Array
structure Rev = ReversedGraphView
type var = int
fun compute_idefs {def_use, cfg} =
let val CFG as G.GRAPH cfg = cfg
val N = #capacity cfg ()
val DU = A.array(N,([],[]))
val _ = #forall_nodes cfg
(fn (b,b') => let val (d,u) = def_use(b,b')
in A.update(DU,b,(SL.uniq d,SL.uniq u))
end)
fun dump(name,a) =
(print(name^"=");
A.appi (fn (i,v) =>
print(Int.toString i ^ "=" ^Int.toString v^" "))
(a,0,NONE);
print "\n")
fun tarjan_lengauer(G.GRAPH cfg) =
let val [ENTRY] = #entries cfg ()
val vertex = A.array(N,~1)
val parent = A.array(N,~1)
val semi = A.array(N,~1)
val bucket = A.array(N,[])
val dom = A.array(N,~1)
val sdefuse = A.array(N,([],[]))
val idefuse = A.array(N,([],[]))
val ancestor = A.array(N,~1)
val treeparent = A.array(N,~1)
val label = A.array(N,~1)
fun dfs(p,n,i) =
if A.sub(semi,i) <> ~1 then n
else
(A.update(parent,i,p);
A.update(semi,i,n);
A.update(vertex,n,i);
A.update(label,i,i);
dfs'(i,n+1,#succ cfg i)
)
and dfs'(p,n,[]) = n
| dfs'(p,n,i::is) = dfs'(p,dfs(p,n,i),is)
val n = dfs(~1,0,ENTRY)
fun COMPRESS v =
if A.sub(ancestor,A.sub(ancestor,v)) <> ~1 then
(COMPRESS(A.sub(ancestor,v));
let val label_ancestor_v = A.sub(label,A.sub(ancestor,v))
val label_v = A.sub(label,v)
in if A.sub(semi,label_ancestor_v) <
A.sub(semi,label_v) then
A.update(label,v,label_ancestor_v)
else ()
end;
A.update(ancestor,v,A.sub(ancestor,A.sub(ancestor,v)))
)
else ()
fun LINK(v,w) = (A.update(ancestor,w,v);
A.update(treeparent,w,v))
fun EVAL v =
if A.sub(ancestor,v) = ~1 then v
else (COMPRESS v; A.sub(label,v))
fun EVALDEFUSE v =
let fun up(v,D,U) =
let val p = A.sub(treeparent,v)
in if p = ~1 then (D,U)
else let val (d,u) = A.sub(DU,v)
val (d',u') = A.sub(sdefuse,v)
in up(p,SL.merge(d,SL.merge(d',D)),
SL.merge(u,SL.merge(u',U)))
end
end
in
up(v,[],[])
end
fun step2_3 0 = ()
| step2_3 i =
let val w = A.sub(vertex,i)
val parent_w = A.sub(parent,w)
fun step2 [] = ()
| step2 ((v,_,_)::vs) =
let val u = EVAL v
val semi_u = A.sub(semi,u)
in if semi_u < A.sub(semi,w) then
A.update(semi,w,semi_u)
else ();
let val (d,u) = EVALDEFUSE v
val (d',u') = A.sub(sdefuse,w)
in A.update(sdefuse,w,(SL.merge(d,d'),
SL.merge(u,u')))
end;
step2 vs
end
val _ = step2(#in_edges cfg w)
val vertex_semi_w = A.sub(vertex,A.sub(semi,w))
val _ = A.update(bucket,vertex_semi_w,
w::A.sub(bucket,vertex_semi_w))
val _ = LINK(parent_w,w)
fun step3 [] = ()
| step3 (v::vs) =
let val u = EVAL v
in A.update(dom,v,if A.sub(semi,u) < A.sub(semi,v)
then u else parent_w);
let val (d,u) = A.sub(sdefuse,v)
val (d',u') = EVALDEFUSE(A.sub(parent,v))
in A.update(idefuse,v,(SL.merge(d,d'),
SL.merge(u,u')))
end;
step3 vs
end
val _ = step3 (A.sub(bucket,parent_w))
val _ = A.update(bucket,parent_w,[])
in step2_3(i-1)
end
val _ = step2_3(n-1)
(*
val _ = print("n = "^Int.toString n^"\n")
val _ = dump("vertex",vertex)
val _ = dump("parent",parent)
val _ = dump("semi",semi)
val _ = dump("dom",dom)
val _ = dump("ancestor",ancestor)
val _ = dump("label",label)
*)
fun step4 i =
if i = n then ()
else let val w = A.sub(vertex,i)
in if A.sub(dom,w) <> A.sub(vertex,A.sub(semi,w)) then
let val (d,u) = A.sub(idefuse,A.sub(dom,w))
val (d',u') = A.sub(idefuse,w)
in A.update(idefuse,w,(SL.merge(d,d'),
SL.merge(u,u')));
A.update(dom,w,A.sub(dom,A.sub(dom,w)))
end
else ();
step4(i+1)
end
val _ = step4 1
in idefuse
end
in
{idefuse = fn _ => tarjan_lengauer(CFG),
ipostdefuse = fn _ => tarjan_lengauer(Rev.rev_view CFG)
}
end
end
|