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;
import java.util.Arrays;
class DefaultDominatorTree implements DominatorTree {
private LCATree lcaTree;
private int[] indexes;
@ -24,7 +26,7 @@ class DefaultDominatorTree implements DominatorTree {
lcaTree = new LCATree(dominators.length + 1);
indexes = 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) {
int v = vertices[i];
if (v < 0) {
@ -58,9 +60,6 @@ class DefaultDominatorTree implements DominatorTree {
@Override
public int immediateDominatorOf(int a) {
if (a == 0) {
return -1;
}
int result = lcaTree.parentOf(indexes[a + 1]);
return result >= 0 ? nodes[result] : -1;
}

View File

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

View File

@ -307,7 +307,11 @@ public final class GraphUtils {
}
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();
return new DefaultDominatorTree(builder.dominators, builder.vertices);
}