mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Further attempts to get node splitting work
This commit is contained in:
parent
b6df37115f
commit
043d6f587f
|
@ -122,6 +122,9 @@ public final class GraphUtils {
|
|||
while (!stack.isEmpty()) {
|
||||
int node = stack.pop();
|
||||
if (visitIndex[node] > 0) {
|
||||
if (headerIndex[node] > 0) {
|
||||
continue;
|
||||
}
|
||||
currentComponent.add(node);
|
||||
int hdr = visitIndex[node];
|
||||
for (int successor : graph.outgoingEdges(node)) {
|
||||
|
|
|
@ -147,11 +147,11 @@ public class DJGraph {
|
|||
}
|
||||
|
||||
public boolean isBackJoin(int i, int j) {
|
||||
return isJoinEdge(i, j) && !domTree.dominates(mergeRoot[j], mergeRoot[i]);
|
||||
return isJoinEdge(i, j) && domTree.dominates(mergeRoot[j], mergeRoot[i]);
|
||||
}
|
||||
|
||||
public boolean isCrossJoin(int i, int j) {
|
||||
return isJoinEdge(i, j) && domTree.dominates(mergeRoot[j], mergeRoot[i]);
|
||||
return isJoinEdge(i, j) && !domTree.dominates(mergeRoot[j], mergeRoot[i]);
|
||||
}
|
||||
|
||||
public boolean isSpanningBack(int i, int j) {
|
||||
|
@ -200,7 +200,7 @@ public class DJGraph {
|
|||
return mergeRoot[node];
|
||||
}
|
||||
|
||||
public void collapse(int[] nodes) {
|
||||
public int collapse(int[] nodes) {
|
||||
// Replace nodes with their classes and find common dominator among them
|
||||
IntSet set = new IntOpenHashSet();
|
||||
int top = nodes[0];
|
||||
|
@ -244,5 +244,6 @@ public class DJGraph {
|
|||
cfg.detachNode(node.value);
|
||||
}
|
||||
}
|
||||
return top;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.teavm.common.*;
|
|||
*/
|
||||
public class IrreducibleGraphConverter {
|
||||
private Graph cfg;
|
||||
private int totalNodeCount;
|
||||
private GraphSplittingBackend backend;
|
||||
|
||||
public void convertToReducible(Graph cfg, int[] weight, GraphSplittingBackend backend) {
|
||||
|
@ -39,6 +40,7 @@ public class IrreducibleGraphConverter {
|
|||
identityNodeMap[i] = new int[] { i };
|
||||
}
|
||||
this.cfg = cfg;
|
||||
totalNodeCount = cfg.size();
|
||||
handleLoops(new DJGraph(cfg, weight), identityNodeMap);
|
||||
this.backend = null;
|
||||
}
|
||||
|
@ -46,23 +48,34 @@ public class IrreducibleGraphConverter {
|
|||
private void handleLoops(DJGraph djGraph, int[][] nodeMap) {
|
||||
for (int level = djGraph.levelCount() - 1; level >= 0; --level) {
|
||||
boolean irreducible = false;
|
||||
levelScan:
|
||||
for (int node : djGraph.level(level)) {
|
||||
for (int pred : djGraph.getGraph().incomingEdges(node)) {
|
||||
if (djGraph.isCrossJoin(pred, node)) {
|
||||
if (!irreducible && djGraph.isSpanningBack(node, pred)) {
|
||||
irreducible = true;
|
||||
}
|
||||
} else if (djGraph.isBackJoin(node, pred)) {
|
||||
djGraph.collapse(reachUnder(djGraph, pred, node));
|
||||
if (djGraph.isCrossJoin(pred, node) && djGraph.isSpanningBack(node, pred)) {
|
||||
irreducible = true;
|
||||
break levelScan;
|
||||
}
|
||||
}
|
||||
}
|
||||
DJGraphNodeFilter filter = new DJGraphNodeFilter(djGraph, level);
|
||||
int[][] sccs = GraphUtils.findStronglyConnectedComponents(djGraph.getGraph(), djGraph.level(level), filter);
|
||||
for (int[] scc : sccs) {
|
||||
if (scc.length > 1) {
|
||||
handleStronglyConnectedComponent(djGraph, scc, nodeMap);
|
||||
djGraph.collapse(scc);
|
||||
if (irreducible) {
|
||||
DJGraphNodeFilter filter = new DJGraphNodeFilter(djGraph, level);
|
||||
int[][] sccs = GraphUtils.findStronglyConnectedComponents(djGraph.getGraph(),
|
||||
djGraph.level(level), filter);
|
||||
for (int[] scc : sccs) {
|
||||
if (scc.length > 1) {
|
||||
handleStronglyConnectedComponent(djGraph, scc, nodeMap);
|
||||
int cls = djGraph.collapse(scc);
|
||||
IntegerArray nodes = new IntegerArray(djGraph.getGraph().size());
|
||||
for (int representative : djGraph.classRepresentatives(cls)) {
|
||||
for (int node : nodeMap[representative]) {
|
||||
nodes.add(node);
|
||||
}
|
||||
}
|
||||
for (int representative : djGraph.classRepresentatives(cls)) {
|
||||
nodeMap[representative] = new int[0];
|
||||
}
|
||||
nodeMap[cls] = nodes.getAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -93,14 +106,16 @@ public class IrreducibleGraphConverter {
|
|||
|
||||
// Partition SCC into domains
|
||||
DisjointSet partitions = new DisjointSet();
|
||||
int[] sccBack = new int[djGraph.getGraph().size()];
|
||||
for (int i = 0; i < scc.length; ++i) {
|
||||
partitions.create();
|
||||
sccBack[scc[i]] = i;
|
||||
}
|
||||
for (int i = 0; i < scc.length; ++i) {
|
||||
int node = scc[i];
|
||||
int idom = djGraph.getDomTree().immediateDominatorOf(node);
|
||||
if (idom != sharedDom) {
|
||||
partitions.union(node, idom);
|
||||
partitions.union(i, sccBack[idom]);
|
||||
}
|
||||
}
|
||||
int[] domains = partitions.pack(scc.length);
|
||||
|
@ -110,10 +125,10 @@ public class IrreducibleGraphConverter {
|
|||
}
|
||||
|
||||
// For each domain calculate its weight
|
||||
int[] domainWeight = new int [domainCount];
|
||||
int[] domainWeight = new int[domainCount];
|
||||
for (int i = 0; i < scc.length; ++i) {
|
||||
int node = scc[i];
|
||||
domainWeight[domains[node]] += djGraph.weightOf(node);
|
||||
domainWeight[domains[i]] += djGraph.weightOf(node);
|
||||
}
|
||||
|
||||
// Find domain to split around
|
||||
|
@ -130,7 +145,7 @@ public class IrreducibleGraphConverter {
|
|||
IntSet domainNodes = new IntOpenHashSet(scc.length);
|
||||
for (int i = 0; i < scc.length; ++i) {
|
||||
int node = scc[i];
|
||||
if (domains[node] == domain) {
|
||||
if (domains[i] == domain) {
|
||||
domainNodes.add(node);
|
||||
}
|
||||
}
|
||||
|
@ -144,6 +159,7 @@ public class IrreducibleGraphConverter {
|
|||
|
||||
private void splitStronglyConnectedComponent(DJGraph djGraph, IntSet domain, int sharedDom,
|
||||
int[] scc, int[][] nodeMap) {
|
||||
Arrays.sort(scc);
|
||||
// Find SCC \ domain
|
||||
int[][] mappedNonDomain = new int[scc.length - domain.size()][];
|
||||
int[] domainNodes = new int[domain.size()];
|
||||
|
@ -166,10 +182,13 @@ public class IrreducibleGraphConverter {
|
|||
|
||||
// Delegate splitting to domain
|
||||
int[][] newNodes = backend.split(mappedDomain, mappedNonDomain);
|
||||
for (int[] nodes : newNodes) {
|
||||
totalNodeCount += nodes.length;
|
||||
}
|
||||
|
||||
// Calculate mappings
|
||||
int[][] newNodeMap = new int[1 + scc.length + newNodes.length][];
|
||||
int[] newNodeBackMap = new int[cfg.size()];
|
||||
int[] newNodeBackMap = new int[totalNodeCount];
|
||||
int[] mappedWeight = new int[newNodeMap.length];
|
||||
Arrays.fill(newNodeBackMap, -1);
|
||||
newNodeMap[0] = nodeMap[sharedDom];
|
||||
|
@ -203,12 +222,12 @@ public class IrreducibleGraphConverter {
|
|||
}
|
||||
}
|
||||
for (int i = 1; i <= mappedDomain.length; ++i) {
|
||||
for (int succ : djGraph.getCfg().outgoingEdges(domainNodes[i])) {
|
||||
for (int succ : djGraph.getCfg().outgoingEdges(domainNodes[i - 1])) {
|
||||
int j = newNodeBackMap[succ];
|
||||
if (j > mappedDomain.length) {
|
||||
builder.addEdge(i, j);
|
||||
} else if (j >= 0) {
|
||||
builder.addEdge(i, j + mappedNonDomain.length);
|
||||
} else if (j >= 0) {
|
||||
builder.addEdge(i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -219,9 +238,9 @@ public class IrreducibleGraphConverter {
|
|||
if (j >= 0) {
|
||||
builder.addEdge(i, j);
|
||||
if (j > mappedDomain.length) {
|
||||
builder.addEdge(i + mappedNonDomain.length, j);
|
||||
} else {
|
||||
builder.addEdge(i + mappedNonDomain.length, j + mappedNonDomain.length);
|
||||
} else {
|
||||
builder.addEdge(i + mappedNonDomain.length, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,12 +48,51 @@ public class GraphTest {
|
|||
builder.addEdge(12, 13);
|
||||
Graph graph = builder.build();
|
||||
|
||||
int[][] sccs = GraphUtils.findStronglyConnectedComponents(graph, new int[] { 0 }, new GraphNodeFilter() {
|
||||
int[][] sccs = GraphUtils.findStronglyConnectedComponents(graph, new int[] { 0 }, filter);
|
||||
sortSccs(sccs);
|
||||
|
||||
assertThat(sccs.length, is(6));
|
||||
assertThat(sccs[0], is(new int[] { 0 }));
|
||||
assertThat(sccs[1], is(new int[] { 1, 2, 3, 4, 5, 6, 7, 8 }));
|
||||
assertThat(sccs[2], is(new int[] { 9 }));
|
||||
assertThat(sccs[3], is(new int[] { 10 }));
|
||||
assertThat(sccs[4], is(new int[] { 11, 12 }));
|
||||
assertThat(sccs[5], is(new int[] { 13 }));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stronglyConnectedComponentCalculated2() {
|
||||
GraphBuilder builder = new GraphBuilder();
|
||||
builder.addEdge(0, 1);
|
||||
builder.addEdge(0, 2);
|
||||
builder.addEdge(0, 3);
|
||||
builder.addEdge(1, 2);
|
||||
builder.addEdge(2, 1);
|
||||
builder.addEdge(3, 2);
|
||||
builder.addEdge(2, 4);
|
||||
builder.addEdge(4, 5);
|
||||
builder.addEdge(4, 1);
|
||||
builder.addEdge(5, 3);
|
||||
Graph graph = builder.build();
|
||||
|
||||
int[][] sccs = GraphUtils.findStronglyConnectedComponents(graph, new int[] { 1, 2, 3 }, new GraphNodeFilter() {
|
||||
@Override public boolean match(int node) {
|
||||
return true;
|
||||
return node != 0;
|
||||
}
|
||||
});
|
||||
sortSccs(sccs);
|
||||
|
||||
assertThat(sccs.length, is(1));
|
||||
assertThat(sccs[0], is(new int[] { 1, 2, 3, 4, 5 }));
|
||||
}
|
||||
|
||||
private GraphNodeFilter filter = new GraphNodeFilter() {
|
||||
@Override public boolean match(int node) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
private void sortSccs(int[][] sccs) {
|
||||
for (int i = 0; i < sccs.length; ++i) {
|
||||
Arrays.sort(sccs[i]);
|
||||
}
|
||||
|
@ -62,12 +101,5 @@ public class GraphTest {
|
|||
return Integer.compare(o1[0], o2[0]);
|
||||
}
|
||||
});
|
||||
|
||||
assertThat(sccs[0], is(new int[] { 0 }));
|
||||
assertThat(sccs[1], is(new int[] { 1, 2, 3, 4, 5, 6, 7, 8 }));
|
||||
assertThat(sccs[2], is(new int[] { 9 }));
|
||||
assertThat(sccs[3], is(new int[] { 10 }));
|
||||
assertThat(sccs[4], is(new int[] { 11, 12 }));
|
||||
assertThat(sccs[5], is(new int[] { 13 }));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user