mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Fix dominator tree algorithm
This commit is contained in:
parent
1cd635afa5
commit
98ec4597d6
|
@ -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);
|
||||
|
|
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