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.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.optimization.ClassSetOptimizer;
/**
@ -161,9 +165,23 @@ public class JavascriptBuilder {
printType(writer, parameterTypes[i]);
}
writer.println(")");
if (method.getProgram() != null) {
if (method.getProgram() != null && method.getProgram().basicBlockCount() > 0) {
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 {
writer.println();
}

View File

@ -15,6 +15,7 @@
*/
package org.teavm.model.util;
import java.util.BitSet;
import org.teavm.common.Graph;
/**
@ -22,30 +23,64 @@ import org.teavm.common.Graph;
* @author Alexey Andreev
*/
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) {
boolean[] visited = new boolean[graph.size()];
int[] sets = new int[graph.size()];
int[] next = new int[graph.size()];
for (int i = 0; i < next.length; ++i) {
next[i] = i + 1;
}
int node = 0;
while (node < next.length) {
if (visited[node]) {
int[] ordering = new int[graph.size()];
int index = 0;
int[] queue = new int[graph.size() * 2];
for (int root = 0; root < graph.size(); ++root) {
if (visited[root]) {
continue;
}
visited[node] = true;
for (int succ : graph.outgoingEdges(node)) {
if (visited[succ]) {
int head = 0;
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]) {
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 {
sb.append(insn.getField().getClassName());
}
sb.append(".").append(insn.getField());
sb.append(".").append(insn.getField().getFieldName());
}
@Override
@ -263,7 +263,7 @@ public class InstructionStringifier implements InstructionVisitor {
} else {
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
@ -332,7 +332,7 @@ public class InstructionStringifier implements InstructionVisitor {
@Override
public void visit(UnwrapArrayInstruction insn) {
sb.append("@").append(insn.getReceiver().getIndex()).append(" := @")
.append(insn.getArray()).append(".data");
.append(insn.getArray().getIndex()).append(".data");
}
@Override

View File

@ -33,6 +33,7 @@ public class InterferenceGraphBuilder {
UsageExtractor useExtractor = new UsageExtractor();
DefinitionExtractor defExtractor = new DefinitionExtractor();
InstructionTransitionExtractor succExtractor = new InstructionTransitionExtractor();
List<List<Incoming>> outgoings = getOutgoings(program);
for (int i = 0; i < program.basicBlockCount(); ++i) {
BasicBlock block = program.basicBlockAt(i);
block.getLastInstruction().acceptVisitor(succExtractor);
@ -46,6 +47,9 @@ public class InterferenceGraphBuilder {
live.add(j);
}
}
for (Incoming outgoing : outgoings.get(i)) {
live.add(outgoing.getValue().getIndex());
}
for (int j = block.getInstructions().size() - 1; j >= 0; --j) {
Instruction insn = block.getInstructions().get(j);
insn.acceptVisitor(useExtractor);
@ -83,4 +87,20 @@ public class InterferenceGraphBuilder {
}
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();
if (liveVars[task.block].get(task.var) || !dominates(definitions[task.var], task.block)) {
continue;
@ -98,23 +98,21 @@ public class LivenessAnalyzer {
int index = 1;
int[] stack = new int[domGraph.size() * 2];
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) {
stack[top++] = i;
}
}
while (top > 0) {
int v = stack[top--];
int v = stack[--top];
if (domLeft[v] == 0) {
domLeft[v] = index++;
stack[top++] = v;
for (int succ : domGraph.outgoingEdges(v)) {
stack[top++] = succ;
}
} else if (domRight[v] == 0) {
domRight[v] = index++;
if (domGraph.incomingEdgesCount(0) > 0) {
stack[top++] = domGraph.incomingEdges(v)[0];
}
}
}
}

View File

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