mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-03 05:44:10 -08:00
Fix dominator tree algorithm
This commit is contained in:
parent
1cd635afa5
commit
98ec4597d6
|
@ -30,7 +30,6 @@ class DominatorTreeBuilder {
|
||||||
private int[] labels;
|
private int[] labels;
|
||||||
int[] dominators;
|
int[] dominators;
|
||||||
private IntegerArray[] bucket;
|
private IntegerArray[] bucket;
|
||||||
private int[] path;
|
|
||||||
private int effectiveSize;
|
private int effectiveSize;
|
||||||
private int start;
|
private int start;
|
||||||
|
|
||||||
|
@ -44,7 +43,6 @@ class DominatorTreeBuilder {
|
||||||
Arrays.fill(dominators, -1);
|
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()];
|
|
||||||
bucket = new IntegerArray[graph.size()];
|
bucket = new IntegerArray[graph.size()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,32 +52,22 @@ class DominatorTreeBuilder {
|
||||||
}
|
}
|
||||||
Arrays.fill(ancestors, -1);
|
Arrays.fill(ancestors, -1);
|
||||||
dfs();
|
dfs();
|
||||||
for (int i = effectiveSize - 1; i >= 0; --i) {
|
for (int i = effectiveSize - 1; i > 0; --i) {
|
||||||
int w = vertices[i];
|
int w = vertices[i];
|
||||||
if (parents[w] < 0) {
|
for (int v : graph.incomingEdges(w)) {
|
||||||
continue;
|
int u = eval(v);
|
||||||
}
|
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);
|
addToBucket(vertices[semidominators[w]], w);
|
||||||
link(parents[w], w);
|
link(parents[w], w);
|
||||||
for (int v : getBucket(w)) {
|
for (int v : getBucket(parents[w])) {
|
||||||
int u = eval(v);
|
int u = eval(v);
|
||||||
dominators[v] = semidominators[u] < semidominators[v] ? u : parents[w];
|
dominators[v] = semidominators[u] < semidominators[v] ? u : parents[w];
|
||||||
}
|
}
|
||||||
bucket[w] = null;
|
bucket[w] = null;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < effectiveSize; ++i) {
|
for (int i = 1; i < effectiveSize; ++i) {
|
||||||
int w = vertices[i];
|
int w = vertices[i];
|
||||||
if (w < 0 || parents[w] < 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (dominators[w] != vertices[semidominators[w]]) {
|
if (dominators[w] != vertices[semidominators[w]]) {
|
||||||
dominators[w] = dominators[dominators[w]];
|
dominators[w] = dominators[dominators[w]];
|
||||||
}
|
}
|
||||||
|
@ -107,27 +95,23 @@ class DominatorTreeBuilder {
|
||||||
|
|
||||||
private int eval(int v) {
|
private int eval(int v) {
|
||||||
int ancestor = ancestors[v];
|
int ancestor = ancestors[v];
|
||||||
if (ancestor == -1) {
|
if (ancestor < 0) {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
int i = 0;
|
compress(v);
|
||||||
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;
|
|
||||||
}
|
|
||||||
return labels[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() {
|
private void dfs() {
|
||||||
Arrays.fill(semidominators, -1);
|
Arrays.fill(semidominators, -1);
|
||||||
Arrays.fill(vertices, -1);
|
Arrays.fill(vertices, -1);
|
||||||
|
|
84
core/src/test/java/org/teavm/common/DomTreeTest.java
Normal file
84
core/src/test/java/org/teavm/common/DomTreeTest.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user