diff --git a/teavm-core/src/main/java/org/teavm/common/DisjointSet.java b/teavm-core/src/main/java/org/teavm/common/DisjointSet.java index 87b8a8cbc..aa9c2bb52 100644 --- a/teavm-core/src/main/java/org/teavm/common/DisjointSet.java +++ b/teavm-core/src/main/java/org/teavm/common/DisjointSet.java @@ -41,6 +41,23 @@ public class DisjointSet { return node; } + public int[] pack(int count) { + int[] packed = new int[count]; + int[] packedIndexes = new int[size]; + Arrays.fill(packedIndexes, -1); + int lastIndex = 0; + for (int i = 0; i < count; ++i) { + int cls = find(i); + int packedIndex = packedIndexes[cls]; + if (packedIndex < 0) { + packedIndex = lastIndex++; + packedIndexes[cls] = packedIndex; + } + packed[i] = packedIndex; + } + return packed; + } + private void ensureCapacity(int size) { if (parent.length >= size) { return; diff --git a/teavm-core/src/main/java/org/teavm/javascript/JavascriptBuilder.java b/teavm-core/src/main/java/org/teavm/javascript/JavascriptBuilder.java index 68e25b7ec..bddfd4caf 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/JavascriptBuilder.java +++ b/teavm-core/src/main/java/org/teavm/javascript/JavascriptBuilder.java @@ -21,15 +21,11 @@ import java.util.List; import java.util.Map; import java.util.Set; import org.teavm.codegen.*; -import org.teavm.common.Graph; import org.teavm.dependency.DependencyChecker; import org.teavm.javascript.ast.ClassNode; import org.teavm.model.*; import org.teavm.model.resource.ClasspathClassHolderSource; -import org.teavm.model.util.GraphColorer; -import org.teavm.model.util.InterferenceGraphBuilder; -import org.teavm.model.util.ListingBuilder; -import org.teavm.model.util.LivenessAnalyzer; +import org.teavm.model.util.*; import org.teavm.optimization.ClassSetOptimizer; /** @@ -171,11 +167,8 @@ public class JavascriptBuilder { writer.print(" Register allocation:"); LivenessAnalyzer analyzer = new LivenessAnalyzer(); analyzer.analyze(method.getProgram()); - InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder(); - Graph interferenceGraph = interferenceBuilder.build(method.getProgram(), analyzer); - GraphColorer colorer = new GraphColorer(); - int[] colors = colorer.colorize(interferenceGraph, - Math.min(method.parameterCount() + 1, interferenceGraph.size())); + RegisterAllocator allocator = new RegisterAllocator(); + int[] colors = allocator.allocateRegisters(method, analyzer); for (int i = 0; i < colors.length; ++i) { writer.print(i + ":" + colors[i] + " "); } diff --git a/teavm-core/src/main/java/org/teavm/model/util/GraphColorer.java b/teavm-core/src/main/java/org/teavm/model/util/GraphColorer.java index 1fc8fff1c..2277129e9 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/GraphColorer.java +++ b/teavm-core/src/main/java/org/teavm/model/util/GraphColorer.java @@ -22,30 +22,22 @@ import org.teavm.common.Graph; * * @author Alexey Andreev */ -public class GraphColorer { - public int[] colorize(Graph graph, int preservedColors) { - int[] colors = new int[graph.size()]; - boolean[] visited = new boolean[graph.size()]; - for (int i = 0; i < preservedColors; ++i) { - colors[i] = i; - visited[i] = true; - } +class GraphColorer { + public void colorize(Graph graph, int[] colors) { BitSet usedColors = new BitSet(); for (int v : getOrdering(graph)) { - if (v < preservedColors) { + if (colors[v] >= 0) { continue; } usedColors.clear(); usedColors.set(0); for (int succ : graph.outgoingEdges(v)) { - if (visited[succ]) { + if (colors[succ] >= 0) { usedColors.set(colors[succ]); } } colors[v] = usedColors.nextClearBit(0); - visited[v] = true; } - return colors; } private int[] getOrdering(Graph graph) { diff --git a/teavm-core/src/main/java/org/teavm/model/util/InterferenceGraphBuilder.java b/teavm-core/src/main/java/org/teavm/model/util/InterferenceGraphBuilder.java index 563ccca9b..5006fb30e 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/InterferenceGraphBuilder.java +++ b/teavm-core/src/main/java/org/teavm/model/util/InterferenceGraphBuilder.java @@ -24,7 +24,7 @@ import org.teavm.model.*; * * @author Alexey Andreev */ -public class InterferenceGraphBuilder { +class InterferenceGraphBuilder { public Graph build(Program program, LivenessAnalyzer liveness) { List> edges = new ArrayList<>(); for (int i = 0; i < program.variableCount(); ++i) { diff --git a/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java b/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java new file mode 100644 index 000000000..027010f1a --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java @@ -0,0 +1,89 @@ +/* + * Copyright 2014 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.model.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.teavm.common.DisjointSet; +import org.teavm.common.Graph; +import org.teavm.common.GraphBuilder; +import org.teavm.model.*; + +/** + * + * @author Alexey Andreev + */ +public class RegisterAllocator { + public int[] allocateRegisters(MethodHolder method, LivenessAnalyzer liveness) { + InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder(); + Graph interferenceGraph = interferenceBuilder.build(method.getProgram(), liveness); + int[] congruenceClasses = buildPhiCongruenceClasses(method.getProgram()); + int[] colors = new int[method.getProgram().variableCount() * 2]; + Arrays.fill(colors, -1); + for (int i = 0; i < method.parameterCount(); ++i) { + colors[i] = i; + } + List> involvedIncomings = getInvolvedIncomings(method.getProgram()); + GraphBuilder graphBuilder = new GraphBuilder(); + Program program = method.getProgram(); + for (int v = 0; v < program.variableCount(); ++v) { + for (int w : interferenceGraph.outgoingEdges(v)) { + if (w <= v) { + continue; + } + if (congruenceClasses[v] == congruenceClasses[w]) { + + } + } + } + GraphColorer colorer = new GraphColorer(); + colorer.colorize(interferenceGraph, colors); + return colors; + } + + private List> getInvolvedIncomings(Program program) { + List> involvedIncomings = new ArrayList<>(); + for (int i = 0; i < program.variableCount(); ++i) { + involvedIncomings.add(new ArrayList()); + } + for (int i = 0; i < program.basicBlockCount(); ++i) { + BasicBlock block = program.basicBlockAt(i); + for (Phi phi : block.getPhis()) { + for (Incoming incoming : phi.getIncomings()) { + involvedIncomings.get(incoming.getValue().getIndex()).add(incoming); + } + } + } + return involvedIncomings; + } + + private int[] buildPhiCongruenceClasses(Program program) { + DisjointSet classes = new DisjointSet(); + for (int i = 0; i < program.variableCount(); ++i) { + classes.create(); + } + for (int i = 0; i < program.basicBlockCount(); ++i) { + BasicBlock block = program.basicBlockAt(i); + for (Phi phi : block.getPhis()) { + for (Incoming incoming : phi.getIncomings()) { + classes.union(phi.getReceiver().getIndex(), incoming.getValue().getIndex()); + } + } + } + return classes.pack(program.variableCount()); + } +}