Register allocator almost complete

This commit is contained in:
konsoletyper 2014-01-24 17:26:03 +04:00
parent 73884794a4
commit b7917f2511
4 changed files with 105 additions and 29 deletions

View File

@ -182,7 +182,11 @@ public class Decompiler {
} }
if (node >= 0) { if (node >= 0) {
generator.currentBlock = program.basicBlockAt(node); generator.currentBlock = program.basicBlockAt(node);
generator.nextBlock = next < indexer.size() ? program.basicBlockAt(indexer.nodeAt(next)) : null; int tmp = indexer.nodeAt(next);
if (tmp == -1) {
System.out.println();
}
generator.nextBlock = next < indexer.size() ? program.basicBlockAt(tmp) : null;
generator.statements.clear(); generator.statements.clear();
for (Instruction insn : generator.currentBlock.getInstructions()) { for (Instruction insn : generator.currentBlock.getInstructions()) {
insn.acceptVisitor(generator); insn.acceptVisitor(generator);

View File

@ -163,12 +163,10 @@ public class JavascriptBuilder {
writer.println(")"); writer.println(")");
if (method.getProgram() != null && method.getProgram().basicBlockCount() > 0) { if (method.getProgram() != null && method.getProgram().basicBlockCount() > 0) {
ListingBuilder builder = new ListingBuilder(); ListingBuilder builder = new ListingBuilder();
RegisterAllocator allocator = new RegisterAllocator();
int[] colors = allocator.allocateRegisters(method);
writer.print(builder.buildListing(method.getProgram(), " ")); writer.print(builder.buildListing(method.getProgram(), " "));
writer.print(" Register allocation:"); writer.print(" Register allocation:");
LivenessAnalyzer analyzer = new LivenessAnalyzer();
analyzer.analyze(method.getProgram());
RegisterAllocator allocator = new RegisterAllocator();
int[] colors = allocator.allocateRegisters(method, analyzer);
for (int i = 0; i < colors.length; ++i) { for (int i = 0; i < colors.length; ++i) {
writer.print(i + ":" + colors[i] + " "); writer.print(i + ":" + colors[i] + " ");
} }

View File

@ -15,7 +15,9 @@
*/ */
package org.teavm.model.util; package org.teavm.model.util;
import java.util.ArrayList;
import java.util.BitSet; import java.util.BitSet;
import java.util.List;
import org.teavm.common.Graph; import org.teavm.common.Graph;
/** /**
@ -23,7 +25,25 @@ import org.teavm.common.Graph;
* @author Alexey Andreev * @author Alexey Andreev
*/ */
class GraphColorer { class GraphColorer {
public void colorize(Graph graph, int[] colors) { public void colorize(Graph graph, int[] classes, int[] colors) {
List<List<Integer>> classMembers = new ArrayList<>();
for (int i = 0; i < classes.length; ++i) {
int cls = classes[i];
while (cls >= classMembers.size()) {
classMembers.add(new ArrayList<Integer>());
}
classMembers.get(cls).add(i);
}
for (int i = 0; i < colors.length; ++i) {
int color = colors[i];
if (color != -1) {
int cls = classes[i];
for (int member : classMembers.get(cls)) {
colors[member] = color;
}
classMembers.get(cls).clear();
}
}
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) {
@ -36,7 +56,10 @@ class GraphColorer {
usedColors.set(colors[succ]); usedColors.set(colors[succ]);
} }
} }
colors[v] = usedColors.nextClearBit(0); int color = usedColors.nextClearBit(0);
for (int member : classMembers.get(classes[v])) {
colors[member] = color;
}
} }
} }

View File

@ -20,58 +20,109 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import org.teavm.common.DisjointSet; import org.teavm.common.DisjointSet;
import org.teavm.common.Graph; 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.EmptyInstruction;
import org.teavm.model.instructions.JumpInstruction;
/** /**
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
public class RegisterAllocator { public class RegisterAllocator {
public int[] allocateRegisters(MethodHolder method, LivenessAnalyzer liveness) { public int[] allocateRegisters(MethodHolder method) {
Program program = method.getProgram();
List<PhiArgumentCopy> phiArgsCopies = insertPhiArgumentsCopies(program);
InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder(); InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder();
Graph interferenceGraph = interferenceBuilder.build(method.getProgram(), liveness); LivenessAnalyzer liveness = new LivenessAnalyzer();
int[] congruenceClasses = buildPhiCongruenceClasses(method.getProgram()); liveness.analyze(program);
int[] colors = new int[method.getProgram().variableCount() * 2]; Graph interferenceGraph = interferenceBuilder.build(program, liveness);
DisjointSet congruenceClasses = buildPhiCongruenceClasses(program);
removeRedundantCopies(program, phiArgsCopies, interferenceGraph, congruenceClasses);
int[] classArray = congruenceClasses.pack(program.variableCount());
int[] colors = new int[program.variableCount()];
Arrays.fill(colors, -1); Arrays.fill(colors, -1);
for (int i = 0; i < method.parameterCount(); ++i) { for (int i = 0; i < method.parameterCount(); ++i) {
colors[i] = i; colors[i] = i;
} }
GraphBuilder graphBuilder = new GraphBuilder();
Program program = method.getProgram();
for (int v = 0; v < interferenceGraph.size(); ++v) {
for (int w : interferenceGraph.outgoingEdges(v)) {
if (w <= v) {
continue;
}
if (congruenceClasses[v] == congruenceClasses[w]) {
}
}
}
GraphColorer colorer = new GraphColorer(); GraphColorer colorer = new GraphColorer();
colorer.colorize(interferenceGraph, colors); colorer.colorize(interferenceGraph, classArray, colors);
return colors; return colors;
} }
private static class PhiArgumentCopy { private static class PhiArgumentCopy {
Incoming incoming; Incoming incoming;
int original; int original;
int index;
BasicBlock block;
int var;
} }
private List<PhiArgumentCopy> insertPhiArgumentsCopies(Program program) { private List<PhiArgumentCopy> insertPhiArgumentsCopies(Program program) {
List<PhiArgumentCopy> copies = new ArrayList<>(); List<PhiArgumentCopy> copies = new ArrayList<>();
for (int i = 0; i < program.basicBlockCount(); ++i) { for (int i = 0; i < program.basicBlockCount(); ++i) {
for (Phi phi : program.basicBlockAt(i).getPhis()) { for (final Phi phi : program.basicBlockAt(i).getPhis()) {
for (Incoming incoming : phi.getIncomings()) { for (Incoming incoming : phi.getIncomings()) {
PhiArgumentCopy copy = new PhiArgumentCopy();
copy.incoming = incoming;
copy.original = incoming.getValue().getIndex();
AssignInstruction copyInstruction = new AssignInstruction();
copyInstruction.setReceiver(program.createVariable());
copyInstruction.setAssignee(incoming.getValue());
copy.var = copyInstruction.getReceiver().getIndex();
if (incoming.getSource().getLastInstruction() instanceof JumpInstruction) {
copy.index = incoming.getSource().getInstructions().size() - 1;
copy.block = incoming.getSource();
copy.block.getInstructions().add(copy.index, copyInstruction);
} else {
final BasicBlock copyBlock = program.createBasicBlock();
copyBlock.getInstructions().add(copyInstruction);
JumpInstruction jumpInstruction = new JumpInstruction();
jumpInstruction.setTarget(phi.getBasicBlock());
copyBlock.getInstructions().add(jumpInstruction);
incoming.getSource().getLastInstruction().acceptVisitor(new BasicBlockMapper() {
@Override protected BasicBlock map(BasicBlock block) {
if (block == phi.getBasicBlock()) {
return copyBlock;
} else {
return block;
}
}
});
incoming.setSource(copyBlock);
copy.index = 0;
copy.block = incoming.getSource();
}
copies.add(copy);
} }
} }
} }
return copies; return copies;
} }
private int[] buildPhiCongruenceClasses(Program program) { private void removeRedundantCopies(Program program, List<PhiArgumentCopy> copies, Graph inteferenceGraph,
DisjointSet congruenceClasses) {
for (PhiArgumentCopy copy : copies) {
boolean interfere = false;
for (int neighbour : inteferenceGraph.outgoingEdges(copy.original)) {
if (neighbour == copy.var || neighbour == copy.original) {
continue;
}
if (congruenceClasses.find(neighbour) == congruenceClasses.find(copy.var) ||
congruenceClasses.find(neighbour) == congruenceClasses.find(copy.original)) {
interfere = true;
break;
}
}
if (!interfere) {
congruenceClasses.union(copy.var, copy.original);
copy.block.getInstructions().set(copy.index, new EmptyInstruction());
copy.incoming.setValue(program.variableAt(copy.original));
}
}
}
private DisjointSet buildPhiCongruenceClasses(Program program) {
DisjointSet classes = new DisjointSet(); DisjointSet classes = new DisjointSet();
for (int i = 0; i < program.variableCount(); ++i) { for (int i = 0; i < program.variableCount(); ++i) {
classes.create(); classes.create();
@ -84,6 +135,6 @@ public class RegisterAllocator {
} }
} }
} }
return classes.pack(program.variableCount()); return classes;
} }
} }