Fix dominator tree builder, make it possible to choose starting node

This commit is contained in:
Alexey Andreev 2021-03-25 16:35:31 +03:00
parent d710870c65
commit c89bc11d02
3 changed files with 25 additions and 18 deletions

View File

@ -15,6 +15,8 @@
*/ */
package org.teavm.common; package org.teavm.common;
import java.util.Arrays;
class DefaultDominatorTree implements DominatorTree { class DefaultDominatorTree implements DominatorTree {
private LCATree lcaTree; private LCATree lcaTree;
private int[] indexes; private int[] indexes;
@ -24,7 +26,7 @@ class DefaultDominatorTree implements DominatorTree {
lcaTree = new LCATree(dominators.length + 1); lcaTree = new LCATree(dominators.length + 1);
indexes = new int[dominators.length + 1]; indexes = new int[dominators.length + 1];
nodes = new int[dominators.length + 1]; nodes = new int[dominators.length + 1];
indexes[0] = -1; Arrays.fill(nodes, -1);
for (int i = 0; i < dominators.length; ++i) { for (int i = 0; i < dominators.length; ++i) {
int v = vertices[i]; int v = vertices[i];
if (v < 0) { if (v < 0) {
@ -58,9 +60,6 @@ class DefaultDominatorTree implements DominatorTree {
@Override @Override
public int immediateDominatorOf(int a) { public int immediateDominatorOf(int a) {
if (a == 0) {
return -1;
}
int result = lcaTree.parentOf(indexes[a + 1]); int result = lcaTree.parentOf(indexes[a + 1]);
return result >= 0 ? nodes[result] : -1; return result >= 0 ? nodes[result] : -1;
} }

View File

@ -32,20 +32,23 @@ class DominatorTreeBuilder {
private IntegerArray[] bucket; private IntegerArray[] bucket;
private int[] path; private int[] path;
private int effectiveSize; private int effectiveSize;
private int start;
public DominatorTreeBuilder(Graph graph) { DominatorTreeBuilder(Graph graph, int start) {
this.graph = graph; this.graph = graph;
this.start = start;
semidominators = new int[graph.size()]; semidominators = new int[graph.size()];
vertices = new int[graph.size()]; vertices = new int[graph.size()];
parents = new int[graph.size()]; parents = new int[graph.size()];
dominators = new int[graph.size()]; dominators = new int[graph.size()];
Arrays.fill(dominators, -1);
ancestors = new int[graph.size()]; ancestors = new int[graph.size()];
labels = new int[graph.size()]; labels = new int[graph.size()];
path = new int[graph.size()]; path = new int[graph.size()];
bucket = new IntegerArray[graph.size()]; bucket = new IntegerArray[graph.size()];
} }
public void build() { void build() {
for (int i = 0; i < labels.length; ++i) { for (int i = 0; i < labels.length; ++i) {
labels[i] = i; labels[i] = i;
} }
@ -56,12 +59,14 @@ class DominatorTreeBuilder {
if (parents[w] < 0) { if (parents[w] < 0) {
continue; continue;
} }
if (w != start) {
for (int v : graph.incomingEdges(w)) { for (int v : graph.incomingEdges(w)) {
int u = eval(v); int u = eval(v);
if (semidominators[u] >= 0) { if (semidominators[u] >= 0) {
semidominators[w] = Math.min(semidominators[w], semidominators[u]); semidominators[w] = Math.min(semidominators[w], semidominators[u]);
} }
} }
}
addToBucket(vertices[semidominators[w]], w); addToBucket(vertices[semidominators[w]], w);
link(parents[w], w); link(parents[w], w);
for (int v : getBucket(w)) { for (int v : getBucket(w)) {
@ -70,7 +75,7 @@ class DominatorTreeBuilder {
} }
bucket[w] = null; bucket[w] = null;
} }
for (int i = 0; i < graph.size(); ++i) { for (int i = 0; i < effectiveSize; ++i) {
int w = vertices[i]; int w = vertices[i];
if (w < 0 || parents[w] < 0) { if (w < 0 || parents[w] < 0) {
continue; continue;
@ -79,6 +84,7 @@ class DominatorTreeBuilder {
dominators[w] = dominators[dominators[w]]; dominators[w] = dominators[dominators[w]];
} }
} }
dominators[start] = -1;
} }
private void addToBucket(int v, int w) { private void addToBucket(int v, int w) {
@ -126,18 +132,15 @@ class DominatorTreeBuilder {
Arrays.fill(semidominators, -1); Arrays.fill(semidominators, -1);
Arrays.fill(vertices, -1); Arrays.fill(vertices, -1);
IntegerStack stack = new IntegerStack(graph.size()); IntegerStack stack = new IntegerStack(graph.size());
for (int i = graph.size() - 1; i >= 0; --i) { stack.push(start);
if (graph.incomingEdgesCount(i) == 0) { Arrays.fill(parents, -1);
stack.push(i);
parents[i] = -1;
}
}
int i = 0; int i = 0;
while (!stack.isEmpty()) { while (!stack.isEmpty()) {
int v = stack.pop(); int v = stack.pop();
if (semidominators[v] >= 0) { if (semidominators[v] >= 0) {
continue; continue;
} }
dominators[v] = start;
// We don't need vertex index after its dominator has computed. // We don't need vertex index after its dominator has computed.
semidominators[v] = i; semidominators[v] = i;
vertices[i++] = v; vertices[i++] = v;
@ -149,5 +152,6 @@ class DominatorTreeBuilder {
} }
} }
effectiveSize = i; effectiveSize = i;
dominators[start] = start;
} }
} }

View File

@ -307,7 +307,11 @@ public final class GraphUtils {
} }
public static DominatorTree buildDominatorTree(Graph graph) { public static DominatorTree buildDominatorTree(Graph graph) {
DominatorTreeBuilder builder = new DominatorTreeBuilder(graph); return buildDominatorTree(graph, 0);
}
public static DominatorTree buildDominatorTree(Graph graph, int start) {
DominatorTreeBuilder builder = new DominatorTreeBuilder(graph, start);
builder.build(); builder.build();
return new DefaultDominatorTree(builder.dominators, builder.vertices); return new DefaultDominatorTree(builder.dominators, builder.vertices);
} }