in internal/gocore/dominator.go [199:266]
func (d *ltDom) calculate() {
// name -> bucket (a name), per Georgiadis.
buckets := make([]vName, d.nVertices)
for i := range buckets {
buckets[i] = vName(i)
}
for i := vNumber(len(d.vertices)) - 1; i > 0; i-- {
w := d.vertices[i]
// Step 3. Implicitly define the immediate dominator of each node.
for v := buckets[w]; v != w; v = buckets[v] {
u := d.eval(v)
if d.semis[u] < d.semis[v] {
d.idom[v] = u
} else {
d.idom[v] = w
}
}
// Step 2. Compute the semidominators of all nodes.
root, obj := d.findVertexByName(w)
// This loop never visits the pseudo-root.
if root != nil {
u := d.eval(pseudoRoot)
if d.semis[u] < d.semis[w] {
d.semis[w] = d.semis[u]
}
} else {
d.p.ForEachReversePtr(obj, func(x Object, r *Root, _, _ int64) bool {
var v int
if r != nil {
v = d.p.findRootIndex(r) + 1
} else {
v, _ = d.p.findObjectIndex(d.p.Addr(x))
v += d.nRoots + 1
}
u := d.eval(vName(v))
if d.semis[u] < d.semis[w] {
d.semis[w] = d.semis[u]
}
return true
})
}
d.link(d.parents[w], w)
if d.parents[w] == d.vertices[d.semis[w]] {
d.idom[w] = d.parents[w]
} else {
buckets[w] = buckets[d.vertices[d.semis[w]]]
buckets[d.vertices[d.semis[w]]] = w
}
}
// The final 'Step 3' is now outside the loop.
for v := buckets[pseudoRoot]; v != pseudoRoot; v = buckets[v] {
d.idom[v] = pseudoRoot
}
// Step 4. Explicitly define the immediate dominator of each
// node, in preorder.
for _, w := range d.vertices[1:] {
if d.idom[w] != d.vertices[d.semis[w]] {
d.idom[w] = d.idom[d.idom[w]]
}
}
}