Further implementation of node splitting

This commit is contained in:
Alexey Andreev 2015-02-27 23:26:28 +03:00
parent 9adbb1ae93
commit 8ad58ce2d2
2 changed files with 118 additions and 7 deletions

View File

@ -36,9 +36,14 @@ public class DJGraph {
private int[] spanningTreeIndex;
private int[][] levelContent;
private int[] mergeRoot;
private int[] weight;
private IntegerArray[] mergeClasses;
public DJGraph(Graph src) {
public DJGraph(Graph src, int[] weight) {
if (src.size() != weight.length) {
throw new IllegalArgumentException("Node count " + src.size() + " is not equal to weight array " +
weight.length);
}
this.cfg = new MutableDirectedGraph(src);
domTree = GraphUtils.buildDominatorTree(src);
buildGraph(src);
@ -50,6 +55,7 @@ public class DJGraph {
mergeRoot[i] = i;
mergeClasses[i] = IntegerArray.of(i);
}
weight = Arrays.copyOf(weight, weight.length);
}
private void buildGraph(Graph src) {
@ -160,6 +166,18 @@ public class DJGraph {
return c != i && c != j;
}
public int weightOf(int node) {
return weight[node];
}
public int weightOf(int... nodes) {
int result = 0;
for (int node : nodes) {
result += weight[node];
}
return result;
}
public int levelOf(int node) {
return domTree.levelOf(mergeRoot[node]);
}
@ -202,6 +220,7 @@ public class DJGraph {
cls.addAll(mergeClasses[node.value].getAll());
mergeClasses[node.value].clear();
}
weight[top] += weight[node.value];
}
// Alter graphs

View File

@ -15,10 +15,9 @@
*/
package org.teavm.common.irreducible;
import org.teavm.common.*;
import com.carrotsearch.hppc.IntOpenHashSet;
import com.carrotsearch.hppc.IntSet;
import org.teavm.common.Graph;
import org.teavm.common.GraphNodeFilter;
import org.teavm.common.GraphUtils;
/**
* <p>Converts irreducible graph to reducible one using node splitting algorithm described at
@ -28,15 +27,21 @@ import org.teavm.common.GraphUtils;
* @author Alexey Andreev
*/
public class IrreducibleGraphConverter {
private Graph cfg;
private GraphSplittingBackend backend;
public void convertToReducible(Graph cfg, GraphSplittingBackend backend) {
public void convertToReducible(Graph cfg, int[] weight, GraphSplittingBackend backend) {
this.backend = backend;
handleLoops(new DJGraph(cfg));
int[] identityNodeMap = new int[cfg.size()];
for (int i = 0; i < identityNodeMap.length; ++i) {
identityNodeMap[i] = i;
}
this.cfg = cfg;
handleLoops(new DJGraph(cfg, weight), identityNodeMap);
this.backend = null;
}
private void handleLoops(DJGraph djGraph) {
private void handleLoops(DJGraph djGraph, int[] nodeMap) {
for (int level = djGraph.levelCount() - 1; level >= 0; --level) {
boolean irreducible = false;
for (int node : djGraph.level(level)) {
@ -52,6 +57,10 @@ public class IrreducibleGraphConverter {
}
DJGraphNodeFilter filter = new DJGraphNodeFilter(djGraph, level, null);
int[][] sccs = GraphUtils.findStronglyConnectedComponents(djGraph.getGraph(), djGraph.level(level), filter);
for (int[] scc : sccs) {
handleStronglyConnectedComponent(djGraph, scc, nodeMap);
djGraph.collapse(scc);
}
}
}
@ -60,6 +69,89 @@ public class IrreducibleGraphConverter {
return null;
}
private void handleStronglyConnectedComponent(DJGraph djGraph, int[] scc, int[] nodeMap) {
// Find shared dominator
int sharedDom = scc[0];
for (int i = 1; i < scc.length; ++i) {
sharedDom = djGraph.getDomTree().commonDominatorOf(sharedDom, scc[i]);
}
// Partition SCC into domains
DisjointSet partitions = new DisjointSet();
for (int i = 0; i < scc.length; ++i) {
partitions.create();
}
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);
}
}
int[] domains = partitions.pack(scc.length);
int domainCount = 0;
for (int domain : domains) {
domainCount = Math.max(domainCount, domain + 1);
}
// For each domain calculate its weight
int[] domainWeight = new int [domainCount];
for (int i = 0; i < scc.length; ++i) {
int node = scc[i];
domainWeight[domains[node]] += djGraph.weightOf(node);
}
// Find domain to split around
int domain = 0;
int maxWeight = domainWeight[0];
for (int i = 1; i < domainWeight.length; ++i) {
if (domainWeight[i] > maxWeight) {
domain = i;
maxWeight = domainWeight[i];
}
}
// Find header of this domain
IntSet domainNodes = new IntOpenHashSet(scc.length);
for (int i = 0; i < scc.length; ++i) {
int node = scc[i];
if (domains[node] == domain) {
domainNodes.add(node);
}
}
// Split
int[] newNodes = splitStronglyConnectedComponent(domainNodes, scc, nodeMap);
// Construct DJ-subgraph
int[] newNodeMap = new int[1 + scc.length + newNodes.length];
for (int i = 0; i < scc.length; ++i) {
newNodeMap[i + 1] = nodeMap[scc[i]];
}
for (int i = 0; i < newNodes.length; ++i) {
newNodeMap[i + 1 + scc.length] = newNodes[i];
}
GraphBuilder builder = new GraphBuilder(newNodeMap.length);
for (int i = 0; i < scc.length; ++i) {
}
}
private int[] splitStronglyConnectedComponent(IntSet domain, int[] scc, int[] nodeMap) {
IntegerArray nonDomain = new IntegerArray(scc.length);
for (int node : scc) {
if (!domain.contains(node)) {
nonDomain.add(node);
}
}
int[] mappedNonDomain = new int[nonDomain.size()];
for (int i = 0; i < nonDomain.size(); ++i) {
mappedNonDomain[i] = nodeMap[nonDomain.get(i)];
}
return backend.split(mappedNonDomain);
}
static class DJGraphNodeFilter implements GraphNodeFilter {
private DJGraph graph;
private int level;