Fixes register allocator

This commit is contained in:
konsoletyper 2014-01-23 13:16:20 +04:00
parent ba67c34b20
commit 24d40c3c41
6 changed files with 100 additions and 28 deletions

View File

@ -21,11 +21,15 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.teavm.codegen.*; import org.teavm.codegen.*;
import org.teavm.common.Graph;
import org.teavm.dependency.DependencyChecker; import org.teavm.dependency.DependencyChecker;
import org.teavm.javascript.ast.ClassNode; import org.teavm.javascript.ast.ClassNode;
import org.teavm.model.*; import org.teavm.model.*;
import org.teavm.model.resource.ClasspathClassHolderSource; 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.ListingBuilder;
import org.teavm.model.util.LivenessAnalyzer;
import org.teavm.optimization.ClassSetOptimizer; import org.teavm.optimization.ClassSetOptimizer;
/** /**
@ -161,9 +165,23 @@ public class JavascriptBuilder {
printType(writer, parameterTypes[i]); printType(writer, parameterTypes[i]);
} }
writer.println(")"); writer.println(")");
if (method.getProgram() != null) { if (method.getProgram() != null && method.getProgram().basicBlockCount() > 0) {
ListingBuilder builder = new ListingBuilder(); ListingBuilder builder = new ListingBuilder();
writer.println(builder.buildListing(method.getProgram(), " ")); writer.print(builder.buildListing(method.getProgram(), " "));
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()));
for (int i = 0; i < colors.length; ++i) {
writer.print(i + ":" + colors[i] + " ");
}
writer.println();
writer.println();
writer.flush();
} else { } else {
writer.println(); writer.println();
} }

View File

@ -15,6 +15,7 @@
*/ */
package org.teavm.model.util; package org.teavm.model.util;
import java.util.BitSet;
import org.teavm.common.Graph; import org.teavm.common.Graph;
/** /**
@ -22,30 +23,64 @@ import org.teavm.common.Graph;
* @author Alexey Andreev * @author Alexey Andreev
*/ */
public class GraphColorer { public class GraphColorer {
public void colorize(Graph graph) { 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;
}
BitSet usedColors = new BitSet();
for (int v : getOrdering(graph)) {
if (v < preservedColors) {
continue;
}
usedColors.clear();
usedColors.set(0);
for (int succ : graph.outgoingEdges(v)) {
if (visited[succ]) {
usedColors.set(colors[succ]);
}
}
colors[v] = usedColors.nextClearBit(0);
visited[v] = true;
}
return colors;
} }
private int[] getOrdering(Graph graph) { private int[] getOrdering(Graph graph) {
boolean[] visited = new boolean[graph.size()]; boolean[] visited = new boolean[graph.size()];
int[] sets = new int[graph.size()]; int[] ordering = new int[graph.size()];
int[] next = new int[graph.size()]; int index = 0;
for (int i = 0; i < next.length; ++i) { int[] queue = new int[graph.size() * 2];
next[i] = i + 1; for (int root = 0; root < graph.size(); ++root) {
} if (visited[root]) {
int node = 0;
while (node < next.length) {
if (visited[node]) {
continue; continue;
} }
visited[node] = true; int head = 0;
for (int succ : graph.outgoingEdges(node)) { int tail = 0;
queue[head++] = root;
while (head != tail) {
int v = queue[tail++];
if (tail == queue.length) {
tail = 0;
}
if (visited[v]) {
continue;
}
visited[v] = true;
ordering[index++] = v;
for (int succ : graph.outgoingEdges(v)) {
if (visited[succ]) { if (visited[succ]) {
continue;
}
if (++head == queue.length) {
head = 0;
}
queue[head] = succ;
} }
} }
graph.outgoingEdges(node);
} }
return next; return ordering;
} }
} }

View File

@ -253,7 +253,7 @@ public class InstructionStringifier implements InstructionVisitor {
} else { } else {
sb.append(insn.getField().getClassName()); sb.append(insn.getField().getClassName());
} }
sb.append(".").append(insn.getField()); sb.append(".").append(insn.getField().getFieldName());
} }
@Override @Override
@ -263,7 +263,7 @@ public class InstructionStringifier implements InstructionVisitor {
} else { } else {
sb.append(insn.getField().getClassName()); sb.append(insn.getField().getClassName());
} }
sb.append(".").append(insn.getField()).append(" := @").append(insn.getValue().getIndex()); sb.append(".").append(insn.getField().getFieldName()).append(" := @").append(insn.getValue().getIndex());
} }
@Override @Override
@ -332,7 +332,7 @@ public class InstructionStringifier implements InstructionVisitor {
@Override @Override
public void visit(UnwrapArrayInstruction insn) { public void visit(UnwrapArrayInstruction insn) {
sb.append("@").append(insn.getReceiver().getIndex()).append(" := @") sb.append("@").append(insn.getReceiver().getIndex()).append(" := @")
.append(insn.getArray()).append(".data"); .append(insn.getArray().getIndex()).append(".data");
} }
@Override @Override

View File

@ -33,6 +33,7 @@ public class InterferenceGraphBuilder {
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);
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);
@ -46,6 +47,9 @@ public class InterferenceGraphBuilder {
live.add(j); live.add(j);
} }
} }
for (Incoming outgoing : outgoings.get(i)) {
live.add(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);
@ -83,4 +87,20 @@ public class InterferenceGraphBuilder {
} }
return builder.build(); return builder.build();
} }
private List<List<Incoming>> getOutgoings(Program program) {
List<List<Incoming>> outgoings = new ArrayList<>();
for (int i = 0; i < program.basicBlockCount(); ++i) {
outgoings.add(new ArrayList<Incoming>());
}
for (int i = 0; i < program.basicBlockCount(); ++i) {
BasicBlock block = program.basicBlockAt(i);
for (Phi phi : block.getPhis()) {
for(Incoming incoming : phi.getIncomings()) {
outgoings.get(incoming.getSource().getIndex()).add(incoming);
}
}
}
return outgoings;
}
} }

View File

@ -77,7 +77,7 @@ public class LivenessAnalyzer {
} }
} }
while (stack.isEmpty()) { while (!stack.isEmpty()) {
Task task = stack.pop(); Task task = stack.pop();
if (liveVars[task.block].get(task.var) || !dominates(definitions[task.var], task.block)) { if (liveVars[task.block].get(task.var) || !dominates(definitions[task.var], task.block)) {
continue; continue;
@ -98,23 +98,21 @@ public class LivenessAnalyzer {
int index = 1; int index = 1;
int[] stack = new int[domGraph.size() * 2]; int[] stack = new int[domGraph.size() * 2];
int top = 0; int top = 0;
for (int i = domGraph.size(); i >= 0; --i) { for (int i = domGraph.size() - 1; i >= 0; --i) {
if (domGraph.incomingEdgesCount(i) == 0) { if (domGraph.incomingEdgesCount(i) == 0) {
stack[top++] = i; stack[top++] = i;
} }
} }
while (top > 0) { while (top > 0) {
int v = stack[top--]; int v = stack[--top];
if (domLeft[v] == 0) { if (domLeft[v] == 0) {
domLeft[v] = index++; domLeft[v] = index++;
stack[top++] = v;
for (int succ : domGraph.outgoingEdges(v)) { for (int succ : domGraph.outgoingEdges(v)) {
stack[top++] = succ; stack[top++] = succ;
} }
} else if (domRight[v] == 0) { } else if (domRight[v] == 0) {
domRight[v] = index++; domRight[v] = index++;
if (domGraph.incomingEdgesCount(0) > 0) {
stack[top++] = domGraph.incomingEdges(v)[0];
}
} }
} }
} }

View File

@ -184,12 +184,13 @@ public class UsageExtractor implements InstructionVisitor {
public void visit(InvokeInstruction insn) { public void visit(InvokeInstruction insn) {
if (insn.getInstance() != null) { if (insn.getInstance() != null) {
usedVariables = new Variable[insn.getArguments().size() + 1]; usedVariables = new Variable[insn.getArguments().size() + 1];
insn.getArguments().toArray(usedVariables);
usedVariables[insn.getArguments().size()] = insn.getInstance(); usedVariables[insn.getArguments().size()] = insn.getInstance();
} else { } else {
usedVariables = new Variable[insn.getArguments().size()]; usedVariables = new Variable[insn.getArguments().size()];
}
insn.getArguments().toArray(usedVariables); insn.getArguments().toArray(usedVariables);
} }
}
@Override @Override
public void visit(IsInstanceInstruction insn) { public void visit(IsInstanceInstruction insn) {