Fix dominator tree algorithm

This commit is contained in:
Alexey Andreev 2023-09-22 10:21:26 +02:00
parent 1cd635afa5
commit 98ec4597d6
2 changed files with 102 additions and 34 deletions

View File

@ -30,7 +30,6 @@ class DominatorTreeBuilder {
private int[] labels;
int[] dominators;
private IntegerArray[] bucket;
private int[] path;
private int effectiveSize;
private int start;
@ -44,7 +43,6 @@ class DominatorTreeBuilder {
Arrays.fill(dominators, -1);
ancestors = new int[graph.size()];
labels = new int[graph.size()];
path = new int[graph.size()];
bucket = new IntegerArray[graph.size()];
}
@ -54,32 +52,22 @@ class DominatorTreeBuilder {
}
Arrays.fill(ancestors, -1);
dfs();
for (int i = effectiveSize - 1; i >= 0; --i) {
for (int i = effectiveSize - 1; i > 0; --i) {
int w = vertices[i];
if (parents[w] < 0) {
continue;
}
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]);
}
}
for (int v : graph.incomingEdges(w)) {
int u = eval(v);
semidominators[w] = Math.min(semidominators[w], semidominators[u]);
}
addToBucket(vertices[semidominators[w]], w);
link(parents[w], w);
for (int v : getBucket(w)) {
for (int v : getBucket(parents[w])) {
int u = eval(v);
dominators[v] = semidominators[u] < semidominators[v] ? u : parents[w];
}
bucket[w] = null;
}
for (int i = 0; i < effectiveSize; ++i) {
for (int i = 1; i < effectiveSize; ++i) {
int w = vertices[i];
if (w < 0 || parents[w] < 0) {
continue;
}
if (dominators[w] != vertices[semidominators[w]]) {
dominators[w] = dominators[dominators[w]];
}
@ -107,27 +95,23 @@ class DominatorTreeBuilder {
private int eval(int v) {
int ancestor = ancestors[v];
if (ancestor == -1) {
if (ancestor < 0) {
return v;
}
int i = 0;
while (ancestor >= 0) {
path[i++] = v;
v = ancestor;
ancestor = ancestors[v];
}
ancestor = v;
while (--i >= 0) {
v = path[i];
if (semidominators[labels[v]] > semidominators[labels[ancestor]]) {
labels[v] = labels[ancestor];
}
ancestors[v] = ancestor;
ancestor = v;
}
compress(v);
return labels[v];
}
private void compress(int v) {
if (ancestors[ancestors[v]] >= 0) {
compress(ancestors[v]);
if (semidominators[labels[ancestors[v]]] < semidominators[labels[v]]) {
labels[v] = labels[ancestors[v]];
}
ancestors[v] = ancestors[ancestors[v]];
}
}
private void dfs() {
Arrays.fill(semidominators, -1);
Arrays.fill(vertices, -1);

View File

@ -0,0 +1,84 @@
/*
* Copyright 2023 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.common;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class DomTreeTest {
@Test
public void domTree1() {
var builder = new GraphBuilder();
addEdges(builder, 0, 16, 17);
addEdges(builder, 1, 14);
addEdges(builder, 2, 18);
addEdges(builder, 3, 6, 7, 15);
addEdges(builder, 4, 11, 15, 26);
addEdges(builder, 5, 11, 15, 30);
addEdges(builder, 6);
addEdges(builder, 7, 15, 34);
addEdges(builder, 8, 15);
addEdges(builder, 9, 13, 15, 38);
addEdges(builder, 10, 11, 15, 42);
addEdges(builder, 11, 8, 9, 15);
addEdges(builder, 12, 8, 15);
addEdges(builder, 13, 8, 15);
addEdges(builder, 14, 10, 15);
addEdges(builder, 15);
addEdges(builder, 16, 1, 2);
addEdges(builder, 17, 16, 20, 24, 28, 32, 36, 40, 44);
addEdges(builder, 18, 19, 21);
addEdges(builder, 19, 22);
addEdges(builder, 20, 18);
addEdges(builder, 21);
addEdges(builder, 22, 23, 25);
addEdges(builder, 23);
addEdges(builder, 24, 22);
addEdges(builder, 25);
addEdges(builder, 26, 11, 15, 27, 29);
addEdges(builder, 27, 5, 11, 15);
addEdges(builder, 28, 26);
addEdges(builder, 29);
addEdges(builder, 30, 11, 15, 31, 33);
addEdges(builder, 31, 3, 4, 11, 15);
addEdges(builder, 32, 30);
addEdges(builder, 33);
addEdges(builder, 34, 15, 35, 37);
addEdges(builder, 35, 6, 15);
addEdges(builder, 36, 34);
addEdges(builder, 37);
addEdges(builder, 38, 13, 15, 39, 41);
addEdges(builder, 39, 12, 13, 15);
addEdges(builder, 40, 38);
addEdges(builder, 41);
addEdges(builder, 42, 11, 15, 43, 45);
addEdges(builder, 43, 5, 11, 15);
addEdges(builder, 44, 42);
addEdges(builder, 45);
var graph = builder.build();
var dom = GraphUtils.buildDominatorTree(graph);
assertEquals(0, dom.immediateDominatorOf(8));
assertEquals(17, dom.immediateDominatorOf(44));
assertEquals(11, dom.immediateDominatorOf(9));
}
private static void addEdges(GraphBuilder builder, int from, int... to) {
for (int target : to) {
builder.addEdge(from, target);
}
}
}