internal/gocore/dominator.go
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]]
		}
	}
}
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]]
		}
	}
}
// calculate runs the main part of LT.