mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-08 07:54:11 -08:00
Trying to implement register allocator with phi function elimination
This commit is contained in:
parent
24d40c3c41
commit
e5a083b4c7
|
@ -41,6 +41,23 @@ public class DisjointSet {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int[] pack(int count) {
|
||||||
|
int[] packed = new int[count];
|
||||||
|
int[] packedIndexes = new int[size];
|
||||||
|
Arrays.fill(packedIndexes, -1);
|
||||||
|
int lastIndex = 0;
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
int cls = find(i);
|
||||||
|
int packedIndex = packedIndexes[cls];
|
||||||
|
if (packedIndex < 0) {
|
||||||
|
packedIndex = lastIndex++;
|
||||||
|
packedIndexes[cls] = packedIndex;
|
||||||
|
}
|
||||||
|
packed[i] = packedIndex;
|
||||||
|
}
|
||||||
|
return packed;
|
||||||
|
}
|
||||||
|
|
||||||
private void ensureCapacity(int size) {
|
private void ensureCapacity(int size) {
|
||||||
if (parent.length >= size) {
|
if (parent.length >= size) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -21,15 +21,11 @@ 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.*;
|
||||||
import org.teavm.model.util.InterferenceGraphBuilder;
|
|
||||||
import org.teavm.model.util.ListingBuilder;
|
|
||||||
import org.teavm.model.util.LivenessAnalyzer;
|
|
||||||
import org.teavm.optimization.ClassSetOptimizer;
|
import org.teavm.optimization.ClassSetOptimizer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -171,11 +167,8 @@ public class JavascriptBuilder {
|
||||||
writer.print(" Register allocation:");
|
writer.print(" Register allocation:");
|
||||||
LivenessAnalyzer analyzer = new LivenessAnalyzer();
|
LivenessAnalyzer analyzer = new LivenessAnalyzer();
|
||||||
analyzer.analyze(method.getProgram());
|
analyzer.analyze(method.getProgram());
|
||||||
InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder();
|
RegisterAllocator allocator = new RegisterAllocator();
|
||||||
Graph interferenceGraph = interferenceBuilder.build(method.getProgram(), analyzer);
|
int[] colors = allocator.allocateRegisters(method, 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) {
|
for (int i = 0; i < colors.length; ++i) {
|
||||||
writer.print(i + ":" + colors[i] + " ");
|
writer.print(i + ":" + colors[i] + " ");
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,30 +22,22 @@ import org.teavm.common.Graph;
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public class GraphColorer {
|
class GraphColorer {
|
||||||
public int[] colorize(Graph graph, int preservedColors) {
|
public void colorize(Graph graph, int[] colors) {
|
||||||
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();
|
BitSet usedColors = new BitSet();
|
||||||
for (int v : getOrdering(graph)) {
|
for (int v : getOrdering(graph)) {
|
||||||
if (v < preservedColors) {
|
if (colors[v] >= 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
usedColors.clear();
|
usedColors.clear();
|
||||||
usedColors.set(0);
|
usedColors.set(0);
|
||||||
for (int succ : graph.outgoingEdges(v)) {
|
for (int succ : graph.outgoingEdges(v)) {
|
||||||
if (visited[succ]) {
|
if (colors[succ] >= 0) {
|
||||||
usedColors.set(colors[succ]);
|
usedColors.set(colors[succ]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
colors[v] = usedColors.nextClearBit(0);
|
colors[v] = usedColors.nextClearBit(0);
|
||||||
visited[v] = true;
|
|
||||||
}
|
}
|
||||||
return colors;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int[] getOrdering(Graph graph) {
|
private int[] getOrdering(Graph graph) {
|
||||||
|
|
|
@ -24,7 +24,7 @@ import org.teavm.model.*;
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public class InterferenceGraphBuilder {
|
class InterferenceGraphBuilder {
|
||||||
public Graph build(Program program, LivenessAnalyzer liveness) {
|
public Graph build(Program program, LivenessAnalyzer liveness) {
|
||||||
List<Set<Integer>> edges = new ArrayList<>();
|
List<Set<Integer>> edges = new ArrayList<>();
|
||||||
for (int i = 0; i < program.variableCount(); ++i) {
|
for (int i = 0; i < program.variableCount(); ++i) {
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.model.util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import org.teavm.common.DisjointSet;
|
||||||
|
import org.teavm.common.Graph;
|
||||||
|
import org.teavm.common.GraphBuilder;
|
||||||
|
import org.teavm.model.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class RegisterAllocator {
|
||||||
|
public int[] allocateRegisters(MethodHolder method, LivenessAnalyzer liveness) {
|
||||||
|
InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder();
|
||||||
|
Graph interferenceGraph = interferenceBuilder.build(method.getProgram(), liveness);
|
||||||
|
int[] congruenceClasses = buildPhiCongruenceClasses(method.getProgram());
|
||||||
|
int[] colors = new int[method.getProgram().variableCount() * 2];
|
||||||
|
Arrays.fill(colors, -1);
|
||||||
|
for (int i = 0; i < method.parameterCount(); ++i) {
|
||||||
|
colors[i] = i;
|
||||||
|
}
|
||||||
|
List<List<Incoming>> involvedIncomings = getInvolvedIncomings(method.getProgram());
|
||||||
|
GraphBuilder graphBuilder = new GraphBuilder();
|
||||||
|
Program program = method.getProgram();
|
||||||
|
for (int v = 0; v < program.variableCount(); ++v) {
|
||||||
|
for (int w : interferenceGraph.outgoingEdges(v)) {
|
||||||
|
if (w <= v) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (congruenceClasses[v] == congruenceClasses[w]) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GraphColorer colorer = new GraphColorer();
|
||||||
|
colorer.colorize(interferenceGraph, colors);
|
||||||
|
return colors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<List<Incoming>> getInvolvedIncomings(Program program) {
|
||||||
|
List<List<Incoming>> involvedIncomings = new ArrayList<>();
|
||||||
|
for (int i = 0; i < program.variableCount(); ++i) {
|
||||||
|
involvedIncomings.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()) {
|
||||||
|
involvedIncomings.get(incoming.getValue().getIndex()).add(incoming);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return involvedIncomings;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int[] buildPhiCongruenceClasses(Program program) {
|
||||||
|
DisjointSet classes = new DisjointSet();
|
||||||
|
for (int i = 0; i < program.variableCount(); ++i) {
|
||||||
|
classes.create();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
|
BasicBlock block = program.basicBlockAt(i);
|
||||||
|
for (Phi phi : block.getPhis()) {
|
||||||
|
for (Incoming incoming : phi.getIncomings()) {
|
||||||
|
classes.union(phi.getReceiver().getIndex(), incoming.getValue().getIndex());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return classes.pack(program.variableCount());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user