mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Register allocator almost complete
This commit is contained in:
parent
73884794a4
commit
b7917f2511
|
@ -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);
|
||||||
|
|
|
@ -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] + " ");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user