One more speed-up of register allocation

This commit is contained in:
konsoletyper 2014-03-15 14:58:27 +04:00
parent 8d0c412634
commit aacc7e08d2
5 changed files with 99 additions and 82 deletions

View File

@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.model.util; package org.teavm.common;
/** /**
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
class MutableGraphEdge { public class MutableGraphEdge {
MutableGraphEdge back; MutableGraphEdge back;
MutableGraphNode first; MutableGraphNode first;
MutableGraphNode second; MutableGraphNode second;
@ -44,6 +44,7 @@ class MutableGraphEdge {
first.edges.remove(this.second); first.edges.remove(this.second);
if (!second.edges.containsKey(first)) { if (!second.edges.containsKey(first)) {
this.second = second; this.second = second;
back.first = second;
second.edges.put(first, back); second.edges.put(first, back);
first.edges.put(second, this); first.edges.put(second, this);
} else { } else {

View File

@ -13,17 +13,15 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.model.util; package org.teavm.common;
import java.util.Collection; import java.util.*;
import java.util.HashMap;
import java.util.Map;
/** /**
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
class MutableGraphNode { public class MutableGraphNode {
int tag; int tag;
Map<MutableGraphNode, MutableGraphEdge> edges = new HashMap<>(); Map<MutableGraphNode, MutableGraphEdge> edges = new HashMap<>();
@ -48,6 +46,12 @@ class MutableGraphNode {
return edge; return edge;
} }
public void connectAll(Collection<MutableGraphNode> nodes) {
for (MutableGraphNode node : nodes) {
connect(node);
}
}
public Collection<MutableGraphEdge> getEdges() { public Collection<MutableGraphEdge> getEdges() {
return edges.values(); return edges.values();
} }
@ -55,4 +59,22 @@ class MutableGraphNode {
public int getTag() { public int getTag() {
return tag; return tag;
} }
public void setTag(int tag) {
this.tag = tag;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(tag).append(":");
Iterator<MutableGraphEdge> edges = this.edges.values().iterator();
if (edges.hasNext()) {
sb.append(edges.next().getSecond().getTag());
}
while (edges.hasNext()) {
sb.append(',').append(edges.next().getSecond().getTag());
}
return sb.toString();
}
} }

View File

@ -16,14 +16,16 @@
package org.teavm.model.util; package org.teavm.model.util;
import java.util.BitSet; import java.util.BitSet;
import org.teavm.common.Graph; import java.util.List;
import org.teavm.common.MutableGraphEdge;
import org.teavm.common.MutableGraphNode;
/** /**
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
class GraphColorer { class GraphColorer {
public void colorize(Graph graph, int[] colors) { public void colorize(List<MutableGraphNode> graph, int[] colors) {
BitSet usedColors = new BitSet(); BitSet usedColors = new BitSet();
for (int v : getOrdering(graph)) { for (int v : getOrdering(graph)) {
if (colors[v] >= 0) { if (colors[v] >= 0) {
@ -31,7 +33,8 @@ class GraphColorer {
} }
usedColors.clear(); usedColors.clear();
usedColors.set(0); usedColors.set(0);
for (int succ : graph.outgoingEdges(v)) { for (MutableGraphEdge edge : graph.get(v).getEdges()) {
int succ = edge.getSecond().getTag();
if (colors[succ] >= 0) { if (colors[succ] >= 0) {
usedColors.set(colors[succ]); usedColors.set(colors[succ]);
} }
@ -40,7 +43,7 @@ class GraphColorer {
} }
} }
private int[] getOrdering(Graph graph) { private int[] getOrdering(List<MutableGraphNode> graph) {
boolean[] visited = new boolean[graph.size()]; boolean[] visited = new boolean[graph.size()];
int[] ordering = new int[graph.size()]; int[] ordering = new int[graph.size()];
int index = 0; int index = 0;
@ -62,7 +65,8 @@ class GraphColorer {
} }
visited[v] = true; visited[v] = true;
ordering[index++] = v; ordering[index++] = v;
for (int succ : graph.outgoingEdges(v)) { for (MutableGraphEdge edge : graph.get(v).getEdges()) {
int succ = edge.getSecond().getTag();
if (visited[succ]) { if (visited[succ]) {
continue; continue;
} }

View File

@ -15,10 +15,8 @@
*/ */
package org.teavm.model.util; package org.teavm.model.util;
import com.carrotsearch.hppc.IntOpenHashSet;
import java.util.*; import java.util.*;
import org.teavm.common.Graph; import org.teavm.common.MutableGraphNode;
import org.teavm.common.GraphBuilder;
import org.teavm.model.*; import org.teavm.model.*;
/** /**
@ -26,15 +24,16 @@ import org.teavm.model.*;
* @author Alexey Andreev * @author Alexey Andreev
*/ */
class InterferenceGraphBuilder { class InterferenceGraphBuilder {
public Graph build(Program program, int paramCount, LivenessAnalyzer liveness) { public List<MutableGraphNode> build(Program program, int paramCount, LivenessAnalyzer liveness) {
List<IntOpenHashSet> edges = new ArrayList<>(); List<MutableGraphNode> nodes = new ArrayList<>();
for (int i = 0; i < program.variableCount(); ++i) { for (int i = 0; i < program.variableCount(); ++i) {
edges.add(new IntOpenHashSet()); nodes.add(new MutableGraphNode(i));
} }
UsageExtractor useExtractor = new UsageExtractor(); UsageExtractor useExtractor = new UsageExtractor();
DefinitionExtractor defExtractor = new DefinitionExtractor(); DefinitionExtractor defExtractor = new DefinitionExtractor();
InstructionTransitionExtractor succExtractor = new InstructionTransitionExtractor(); InstructionTransitionExtractor succExtractor = new InstructionTransitionExtractor();
List<List<Incoming>> outgoings = getOutgoings(program); List<List<Incoming>> outgoings = getOutgoings(program);
Set<MutableGraphNode> live = new HashSet<>(128);
for (int i = 0; i < program.basicBlockCount(); ++i) { for (int i = 0; i < program.basicBlockCount(); ++i) {
BasicBlock block = program.basicBlockAt(i); BasicBlock block = program.basicBlockAt(i);
block.getLastInstruction().acceptVisitor(succExtractor); block.getLastInstruction().acceptVisitor(succExtractor);
@ -42,75 +41,49 @@ class InterferenceGraphBuilder {
for (BasicBlock succ : succExtractor.getTargets()) { for (BasicBlock succ : succExtractor.getTargets()) {
liveOut.or(liveness.liveIn(succ.getIndex())); liveOut.or(liveness.liveIn(succ.getIndex()));
} }
IntOpenHashSet live = new IntOpenHashSet(8); live.clear();
for (int j = 0; j < liveOut.length(); ++j) { for (int j = 0; j < liveOut.length(); ++j) {
if (liveOut.get(j)) { if (liveOut.get(j)) {
live.add(j); live.add(nodes.get(j));
} }
} }
for (Incoming outgoing : outgoings.get(i)) { for (Incoming outgoing : outgoings.get(i)) {
live.add(outgoing.getValue().getIndex()); live.add(nodes.get(outgoing.getValue().getIndex()));
} }
for (int j = block.getInstructions().size() - 1; j >= 0; --j) { for (int j = block.getInstructions().size() - 1; j >= 0; --j) {
Instruction insn = block.getInstructions().get(j); Instruction insn = block.getInstructions().get(j);
insn.acceptVisitor(useExtractor); insn.acceptVisitor(useExtractor);
insn.acceptVisitor(defExtractor); insn.acceptVisitor(defExtractor);
for (Variable var : defExtractor.getDefinedVariables()) { for (Variable var : defExtractor.getDefinedVariables()) {
edges.get(var.getIndex()).addAll(live); nodes.get(var.getIndex()).connectAll(live);
} }
for (Variable var : defExtractor.getDefinedVariables()) { for (Variable var : defExtractor.getDefinedVariables()) {
live.remove(var.getIndex()); live.remove(nodes.get(var.getIndex()));
} }
for (Variable var : useExtractor.getUsedVariables()) { for (Variable var : useExtractor.getUsedVariables()) {
live.add(var.getIndex()); live.add(nodes.get(var.getIndex()));
} }
} }
if (block.getIndex() == 0) { if (block.getIndex() == 0) {
for (int j = 0; j <= paramCount; ++j) { for (int j = 0; j <= paramCount; ++j) {
edges.get(j).addAll(live); nodes.get(j).connectAll(live);
} }
} }
BitSet liveIn = liveness.liveIn(i); BitSet liveIn = liveness.liveIn(i);
live = new IntOpenHashSet(); live.clear();
for (int j = 0; j < liveOut.length(); ++j) { for (int j = 0; j < liveOut.length(); ++j) {
if (liveIn.get(j)) { if (liveIn.get(j)) {
live.add(j); live.add(nodes.get(j));
} }
} }
for (Phi phi : block.getPhis()) { for (Phi phi : block.getPhis()) {
live.add(phi.getReceiver().getIndex()); live.add(nodes.get(phi.getReceiver().getIndex()));
} }
for (Phi phi : block.getPhis()) { for (Phi phi : block.getPhis()) {
edges.get(phi.getReceiver().getIndex()).addAll(live); nodes.get(phi.getReceiver().getIndex()).connectAll(live);
} }
} }
GraphBuilder builder = new GraphBuilder(edges.size()); return nodes;
List<IntOpenHashSet> backEdges = new ArrayList<>(edges.size());
for (int i = 0; i < edges.size(); ++i) {
backEdges.add(new IntOpenHashSet(8));
}
for (int i = 0; i < edges.size(); ++i) {
IntOpenHashSet edgeSet = edges.get(i);
for (int j = 0; j < edgeSet.allocated.length; ++j) {
if (edgeSet.allocated[j]) {
backEdges.get(edgeSet.keys[j]).add(i);
}
}
for (int j = 0; j < edgeSet.allocated.length; ++j) {
if (edgeSet.allocated[j]) {
backEdges.get(i).add(edgeSet.keys[j]);
}
}
}
for (int i = 0; i < edges.size(); ++i) {
IntOpenHashSet edgeSet = backEdges.get(i);
for (int j = 0; j < edgeSet.allocated.length; ++j) {
if (edgeSet.allocated[j]) {
builder.addEdge(edgeSet.keys[j], i);
}
}
}
return builder.build();
} }
private List<List<Incoming>> getOutgoings(Program program) { private List<List<Incoming>> getOutgoings(Program program) {

View File

@ -16,9 +16,7 @@
package org.teavm.model.util; package org.teavm.model.util;
import java.util.*; import java.util.*;
import org.teavm.common.DisjointSet; import org.teavm.common.*;
import org.teavm.common.Graph;
import org.teavm.common.GraphBuilder;
import org.teavm.model.*; import org.teavm.model.*;
import org.teavm.model.instructions.AssignInstruction; import org.teavm.model.instructions.AssignInstruction;
import org.teavm.model.instructions.EmptyInstruction; import org.teavm.model.instructions.EmptyInstruction;
@ -34,10 +32,11 @@ public class RegisterAllocator {
InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder(); InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder();
LivenessAnalyzer liveness = new LivenessAnalyzer(); LivenessAnalyzer liveness = new LivenessAnalyzer();
liveness.analyze(program); liveness.analyze(program);
Graph interferenceGraph = interferenceBuilder.build(program, method.parameterCount(), liveness); List<MutableGraphNode> interferenceGraph = interferenceBuilder.build(
program, method.parameterCount(), liveness);
DisjointSet congruenceClasses = buildPhiCongruenceClasses(program); DisjointSet congruenceClasses = buildPhiCongruenceClasses(program);
List<MutableGraphNode> classInterferenceGraph = makeMutableGraph(interferenceGraph, congruenceClasses); joinClassNodes(interferenceGraph, congruenceClasses);
removeRedundantCopies(program, classInterferenceGraph, congruenceClasses); removeRedundantCopies(program, interferenceGraph, congruenceClasses);
int[] classArray = congruenceClasses.pack(program.variableCount()); int[] classArray = congruenceClasses.pack(program.variableCount());
renameVariables(program, classArray); renameVariables(program, classArray);
int[] colors = new int[program.variableCount()]; int[] colors = new int[program.variableCount()];
@ -45,30 +44,33 @@ public class RegisterAllocator {
for (int i = 0; i <= method.parameterCount(); ++i) { for (int i = 0; i <= method.parameterCount(); ++i) {
colors[i] = i; colors[i] = i;
} }
renameInterferenceGraph(interferenceGraph, congruenceClasses, classArray);
GraphColorer colorer = new GraphColorer(); GraphColorer colorer = new GraphColorer();
colorer.colorize(renameInterferenceGraph(interferenceGraph, classArray), colors); colorer.colorize(interferenceGraph, colors);
for (int i = 0; i < colors.length; ++i) { for (int i = 0; i < colors.length; ++i) {
program.variableAt(i).setRegister(colors[i]); program.variableAt(i).setRegister(colors[i]);
} }
} }
private static List<MutableGraphNode> makeMutableGraph(Graph graph, DisjointSet classes) { private static void joinClassNodes(List<MutableGraphNode> graph, DisjointSet classes) {
List<MutableGraphNode> mutableGraph = new ArrayList<>(); int sz = graph.size();
for (int i = 0; i < graph.size(); ++i) { for (int i = 0; i < sz; ++i) {
int cls = classes.find(i); int cls = classes.find(i);
while (cls >= mutableGraph.size()) { while (cls >= graph.size()) {
mutableGraph.add(new MutableGraphNode(mutableGraph.size())); graph.add(new MutableGraphNode(graph.size()));
} }
MutableGraphNode node = mutableGraph.get(cls); if (cls != i) {
for (int j : graph.outgoingEdges(i)) { for (MutableGraphEdge edge : graph.get(i).getEdges().toArray(new MutableGraphEdge[0])) {
int otherCls = classes.find(j); if (edge.getFirst() == graph.get(i)) {
while (otherCls >= mutableGraph.size()) { edge.setFirst(graph.get(cls));
mutableGraph.add(new MutableGraphNode(mutableGraph.size()));
} }
node.connect(mutableGraph.get(otherCls)); if (edge.getSecond() == graph.get(i)) {
edge.setSecond(graph.get(cls));
}
}
graph.set(i, graph.get(cls));
} }
} }
return mutableGraph;
} }
private void insertPhiArgumentsCopies(Program program) { private void insertPhiArgumentsCopies(Program program) {
@ -167,17 +169,25 @@ public class RegisterAllocator {
} }
for (MutableGraphEdge edge : interferenceGraph.get(origClass).getEdges() for (MutableGraphEdge edge : interferenceGraph.get(origClass).getEdges()
.toArray(new MutableGraphEdge[0])) { .toArray(new MutableGraphEdge[0])) {
if (edge.getFirst() != null) { if (edge.getFirst() == interferenceGraph.get(origClass)) {
edge.setFirst(interferenceGraph.get(newClass)); edge.setFirst(interferenceGraph.get(newClass));
} }
if (edge.getSecond() == interferenceGraph.get(origClass)) {
edge.setSecond(interferenceGraph.get(newClass));
}
} }
for (MutableGraphEdge edge : interferenceGraph.get(copyClass).getEdges() for (MutableGraphEdge edge : interferenceGraph.get(copyClass).getEdges()
.toArray(new MutableGraphEdge[0])) { .toArray(new MutableGraphEdge[0])) {
if (edge.getFirst() != null) { if (edge.getFirst() == interferenceGraph.get(copyClass)) {
edge.setFirst(interferenceGraph.get(newClass)); edge.setFirst(interferenceGraph.get(newClass));
} }
if (edge.getSecond() == interferenceGraph.get(copyClass)) {
edge.setSecond(interferenceGraph.get(newClass));
} }
} }
interferenceGraph.set(copyClass, interferenceGraph.get(newClass));
interferenceGraph.set(origClass, interferenceGraph.get(newClass));
}
} }
} }
} }
@ -206,14 +216,21 @@ public class RegisterAllocator {
} }
} }
private Graph renameInterferenceGraph(Graph graph, final int[] varMap) { private void renameInterferenceGraph(List<MutableGraphNode> graph, DisjointSet classes, final int[] varMap) {
GraphBuilder renamedGraph = new GraphBuilder(); List<MutableGraphNode> newGraph = new ArrayList<>();
for (int i = 0; i < graph.size(); ++i) { for (int i = 0; i < graph.size(); ++i) {
for (int j : graph.outgoingEdges(i)) { int mapped = varMap[i];
renamedGraph.addEdge(varMap[i], varMap[j]); while (newGraph.size() <= mapped) {
newGraph.add(null);
}
if (newGraph.get(mapped) == null) {
int cls = classes.find(i);
newGraph.set(mapped, graph.get(cls));
graph.get(cls).setTag(mapped);
} }
} }
return renamedGraph.build(); graph.clear();
graph.addAll(newGraph);
} }
private DisjointSet buildPhiCongruenceClasses(Program program) { private DisjointSet buildPhiCongruenceClasses(Program program) {