mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-07 07:24:11 -08:00
One more speed-up of register allocation
This commit is contained in:
parent
8d0c412634
commit
aacc7e08d2
teavm-core/src/main/java/org/teavm
|
@ -13,13 +13,13 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.model.util;
|
||||
package org.teavm.common;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
class MutableGraphEdge {
|
||||
public class MutableGraphEdge {
|
||||
MutableGraphEdge back;
|
||||
MutableGraphNode first;
|
||||
MutableGraphNode second;
|
||||
|
@ -44,6 +44,7 @@ class MutableGraphEdge {
|
|||
first.edges.remove(this.second);
|
||||
if (!second.edges.containsKey(first)) {
|
||||
this.second = second;
|
||||
back.first = second;
|
||||
second.edges.put(first, back);
|
||||
first.edges.put(second, this);
|
||||
} else {
|
|
@ -13,17 +13,15 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.model.util;
|
||||
package org.teavm.common;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
class MutableGraphNode {
|
||||
public class MutableGraphNode {
|
||||
int tag;
|
||||
Map<MutableGraphNode, MutableGraphEdge> edges = new HashMap<>();
|
||||
|
||||
|
@ -48,6 +46,12 @@ class MutableGraphNode {
|
|||
return edge;
|
||||
}
|
||||
|
||||
public void connectAll(Collection<MutableGraphNode> nodes) {
|
||||
for (MutableGraphNode node : nodes) {
|
||||
connect(node);
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<MutableGraphEdge> getEdges() {
|
||||
return edges.values();
|
||||
}
|
||||
|
@ -55,4 +59,22 @@ class MutableGraphNode {
|
|||
public int getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public void setTag(int tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(tag).append(":");
|
||||
Iterator<MutableGraphEdge> edges = this.edges.values().iterator();
|
||||
if (edges.hasNext()) {
|
||||
sb.append(edges.next().getSecond().getTag());
|
||||
}
|
||||
while (edges.hasNext()) {
|
||||
sb.append(',').append(edges.next().getSecond().getTag());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
|
@ -16,14 +16,16 @@
|
|||
package org.teavm.model.util;
|
||||
|
||||
import java.util.BitSet;
|
||||
import org.teavm.common.Graph;
|
||||
import java.util.List;
|
||||
import org.teavm.common.MutableGraphEdge;
|
||||
import org.teavm.common.MutableGraphNode;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
class GraphColorer {
|
||||
public void colorize(Graph graph, int[] colors) {
|
||||
public void colorize(List<MutableGraphNode> graph, int[] colors) {
|
||||
BitSet usedColors = new BitSet();
|
||||
for (int v : getOrdering(graph)) {
|
||||
if (colors[v] >= 0) {
|
||||
|
@ -31,7 +33,8 @@ class GraphColorer {
|
|||
}
|
||||
usedColors.clear();
|
||||
usedColors.set(0);
|
||||
for (int succ : graph.outgoingEdges(v)) {
|
||||
for (MutableGraphEdge edge : graph.get(v).getEdges()) {
|
||||
int succ = edge.getSecond().getTag();
|
||||
if (colors[succ] >= 0) {
|
||||
usedColors.set(colors[succ]);
|
||||
}
|
||||
|
@ -40,7 +43,7 @@ class GraphColorer {
|
|||
}
|
||||
}
|
||||
|
||||
private int[] getOrdering(Graph graph) {
|
||||
private int[] getOrdering(List<MutableGraphNode> graph) {
|
||||
boolean[] visited = new boolean[graph.size()];
|
||||
int[] ordering = new int[graph.size()];
|
||||
int index = 0;
|
||||
|
@ -62,7 +65,8 @@ class GraphColorer {
|
|||
}
|
||||
visited[v] = true;
|
||||
ordering[index++] = v;
|
||||
for (int succ : graph.outgoingEdges(v)) {
|
||||
for (MutableGraphEdge edge : graph.get(v).getEdges()) {
|
||||
int succ = edge.getSecond().getTag();
|
||||
if (visited[succ]) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -15,10 +15,8 @@
|
|||
*/
|
||||
package org.teavm.model.util;
|
||||
|
||||
import com.carrotsearch.hppc.IntOpenHashSet;
|
||||
import java.util.*;
|
||||
import org.teavm.common.Graph;
|
||||
import org.teavm.common.GraphBuilder;
|
||||
import org.teavm.common.MutableGraphNode;
|
||||
import org.teavm.model.*;
|
||||
|
||||
/**
|
||||
|
@ -26,15 +24,16 @@ import org.teavm.model.*;
|
|||
* @author Alexey Andreev
|
||||
*/
|
||||
class InterferenceGraphBuilder {
|
||||
public Graph build(Program program, int paramCount, LivenessAnalyzer liveness) {
|
||||
List<IntOpenHashSet> edges = new ArrayList<>();
|
||||
public List<MutableGraphNode> build(Program program, int paramCount, LivenessAnalyzer liveness) {
|
||||
List<MutableGraphNode> nodes = new ArrayList<>();
|
||||
for (int i = 0; i < program.variableCount(); ++i) {
|
||||
edges.add(new IntOpenHashSet());
|
||||
nodes.add(new MutableGraphNode(i));
|
||||
}
|
||||
UsageExtractor useExtractor = new UsageExtractor();
|
||||
DefinitionExtractor defExtractor = new DefinitionExtractor();
|
||||
InstructionTransitionExtractor succExtractor = new InstructionTransitionExtractor();
|
||||
List<List<Incoming>> outgoings = getOutgoings(program);
|
||||
Set<MutableGraphNode> live = new HashSet<>(128);
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
BasicBlock block = program.basicBlockAt(i);
|
||||
block.getLastInstruction().acceptVisitor(succExtractor);
|
||||
|
@ -42,75 +41,49 @@ class InterferenceGraphBuilder {
|
|||
for (BasicBlock succ : succExtractor.getTargets()) {
|
||||
liveOut.or(liveness.liveIn(succ.getIndex()));
|
||||
}
|
||||
IntOpenHashSet live = new IntOpenHashSet(8);
|
||||
live.clear();
|
||||
for (int j = 0; j < liveOut.length(); ++j) {
|
||||
if (liveOut.get(j)) {
|
||||
live.add(j);
|
||||
live.add(nodes.get(j));
|
||||
}
|
||||
}
|
||||
for (Incoming outgoing : outgoings.get(i)) {
|
||||
live.add(outgoing.getValue().getIndex());
|
||||
live.add(nodes.get(outgoing.getValue().getIndex()));
|
||||
}
|
||||
for (int j = block.getInstructions().size() - 1; j >= 0; --j) {
|
||||
Instruction insn = block.getInstructions().get(j);
|
||||
insn.acceptVisitor(useExtractor);
|
||||
insn.acceptVisitor(defExtractor);
|
||||
for (Variable var : defExtractor.getDefinedVariables()) {
|
||||
edges.get(var.getIndex()).addAll(live);
|
||||
nodes.get(var.getIndex()).connectAll(live);
|
||||
}
|
||||
for (Variable var : defExtractor.getDefinedVariables()) {
|
||||
live.remove(var.getIndex());
|
||||
live.remove(nodes.get(var.getIndex()));
|
||||
}
|
||||
for (Variable var : useExtractor.getUsedVariables()) {
|
||||
live.add(var.getIndex());
|
||||
live.add(nodes.get(var.getIndex()));
|
||||
}
|
||||
}
|
||||
if (block.getIndex() == 0) {
|
||||
for (int j = 0; j <= paramCount; ++j) {
|
||||
edges.get(j).addAll(live);
|
||||
nodes.get(j).connectAll(live);
|
||||
}
|
||||
}
|
||||
BitSet liveIn = liveness.liveIn(i);
|
||||
live = new IntOpenHashSet();
|
||||
live.clear();
|
||||
for (int j = 0; j < liveOut.length(); ++j) {
|
||||
if (liveIn.get(j)) {
|
||||
live.add(j);
|
||||
live.add(nodes.get(j));
|
||||
}
|
||||
}
|
||||
for (Phi phi : block.getPhis()) {
|
||||
live.add(phi.getReceiver().getIndex());
|
||||
live.add(nodes.get(phi.getReceiver().getIndex()));
|
||||
}
|
||||
for (Phi phi : block.getPhis()) {
|
||||
edges.get(phi.getReceiver().getIndex()).addAll(live);
|
||||
nodes.get(phi.getReceiver().getIndex()).connectAll(live);
|
||||
}
|
||||
}
|
||||
GraphBuilder builder = new GraphBuilder(edges.size());
|
||||
List<IntOpenHashSet> backEdges = new ArrayList<>(edges.size());
|
||||
for (int i = 0; i < edges.size(); ++i) {
|
||||
backEdges.add(new IntOpenHashSet(8));
|
||||
}
|
||||
for (int i = 0; i < edges.size(); ++i) {
|
||||
IntOpenHashSet edgeSet = edges.get(i);
|
||||
for (int j = 0; j < edgeSet.allocated.length; ++j) {
|
||||
if (edgeSet.allocated[j]) {
|
||||
backEdges.get(edgeSet.keys[j]).add(i);
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < edgeSet.allocated.length; ++j) {
|
||||
if (edgeSet.allocated[j]) {
|
||||
backEdges.get(i).add(edgeSet.keys[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < edges.size(); ++i) {
|
||||
IntOpenHashSet edgeSet = backEdges.get(i);
|
||||
for (int j = 0; j < edgeSet.allocated.length; ++j) {
|
||||
if (edgeSet.allocated[j]) {
|
||||
builder.addEdge(edgeSet.keys[j], i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private List<List<Incoming>> getOutgoings(Program program) {
|
||||
|
|
|
@ -16,9 +16,7 @@
|
|||
package org.teavm.model.util;
|
||||
|
||||
import java.util.*;
|
||||
import org.teavm.common.DisjointSet;
|
||||
import org.teavm.common.Graph;
|
||||
import org.teavm.common.GraphBuilder;
|
||||
import org.teavm.common.*;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.model.instructions.AssignInstruction;
|
||||
import org.teavm.model.instructions.EmptyInstruction;
|
||||
|
@ -34,10 +32,11 @@ public class RegisterAllocator {
|
|||
InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder();
|
||||
LivenessAnalyzer liveness = new LivenessAnalyzer();
|
||||
liveness.analyze(program);
|
||||
Graph interferenceGraph = interferenceBuilder.build(program, method.parameterCount(), liveness);
|
||||
List<MutableGraphNode> interferenceGraph = interferenceBuilder.build(
|
||||
program, method.parameterCount(), liveness);
|
||||
DisjointSet congruenceClasses = buildPhiCongruenceClasses(program);
|
||||
List<MutableGraphNode> classInterferenceGraph = makeMutableGraph(interferenceGraph, congruenceClasses);
|
||||
removeRedundantCopies(program, classInterferenceGraph, congruenceClasses);
|
||||
joinClassNodes(interferenceGraph, congruenceClasses);
|
||||
removeRedundantCopies(program, interferenceGraph, congruenceClasses);
|
||||
int[] classArray = congruenceClasses.pack(program.variableCount());
|
||||
renameVariables(program, classArray);
|
||||
int[] colors = new int[program.variableCount()];
|
||||
|
@ -45,30 +44,33 @@ public class RegisterAllocator {
|
|||
for (int i = 0; i <= method.parameterCount(); ++i) {
|
||||
colors[i] = i;
|
||||
}
|
||||
renameInterferenceGraph(interferenceGraph, congruenceClasses, classArray);
|
||||
GraphColorer colorer = new GraphColorer();
|
||||
colorer.colorize(renameInterferenceGraph(interferenceGraph, classArray), colors);
|
||||
colorer.colorize(interferenceGraph, colors);
|
||||
for (int i = 0; i < colors.length; ++i) {
|
||||
program.variableAt(i).setRegister(colors[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<MutableGraphNode> makeMutableGraph(Graph graph, DisjointSet classes) {
|
||||
List<MutableGraphNode> mutableGraph = new ArrayList<>();
|
||||
for (int i = 0; i < graph.size(); ++i) {
|
||||
private static void joinClassNodes(List<MutableGraphNode> graph, DisjointSet classes) {
|
||||
int sz = graph.size();
|
||||
for (int i = 0; i < sz; ++i) {
|
||||
int cls = classes.find(i);
|
||||
while (cls >= mutableGraph.size()) {
|
||||
mutableGraph.add(new MutableGraphNode(mutableGraph.size()));
|
||||
while (cls >= graph.size()) {
|
||||
graph.add(new MutableGraphNode(graph.size()));
|
||||
}
|
||||
MutableGraphNode node = mutableGraph.get(cls);
|
||||
for (int j : graph.outgoingEdges(i)) {
|
||||
int otherCls = classes.find(j);
|
||||
while (otherCls >= mutableGraph.size()) {
|
||||
mutableGraph.add(new MutableGraphNode(mutableGraph.size()));
|
||||
if (cls != i) {
|
||||
for (MutableGraphEdge edge : graph.get(i).getEdges().toArray(new MutableGraphEdge[0])) {
|
||||
if (edge.getFirst() == graph.get(i)) {
|
||||
edge.setFirst(graph.get(cls));
|
||||
}
|
||||
if (edge.getSecond() == graph.get(i)) {
|
||||
edge.setSecond(graph.get(cls));
|
||||
}
|
||||
}
|
||||
node.connect(mutableGraph.get(otherCls));
|
||||
graph.set(i, graph.get(cls));
|
||||
}
|
||||
}
|
||||
return mutableGraph;
|
||||
}
|
||||
|
||||
private void insertPhiArgumentsCopies(Program program) {
|
||||
|
@ -167,16 +169,24 @@ public class RegisterAllocator {
|
|||
}
|
||||
for (MutableGraphEdge edge : interferenceGraph.get(origClass).getEdges()
|
||||
.toArray(new MutableGraphEdge[0])) {
|
||||
if (edge.getFirst() != null) {
|
||||
if (edge.getFirst() == interferenceGraph.get(origClass)) {
|
||||
edge.setFirst(interferenceGraph.get(newClass));
|
||||
}
|
||||
if (edge.getSecond() == interferenceGraph.get(origClass)) {
|
||||
edge.setSecond(interferenceGraph.get(newClass));
|
||||
}
|
||||
}
|
||||
for (MutableGraphEdge edge : interferenceGraph.get(copyClass).getEdges()
|
||||
.toArray(new MutableGraphEdge[0])) {
|
||||
if (edge.getFirst() != null) {
|
||||
if (edge.getFirst() == interferenceGraph.get(copyClass)) {
|
||||
edge.setFirst(interferenceGraph.get(newClass));
|
||||
}
|
||||
if (edge.getSecond() == interferenceGraph.get(copyClass)) {
|
||||
edge.setSecond(interferenceGraph.get(newClass));
|
||||
}
|
||||
}
|
||||
interferenceGraph.set(copyClass, interferenceGraph.get(newClass));
|
||||
interferenceGraph.set(origClass, interferenceGraph.get(newClass));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -206,14 +216,21 @@ public class RegisterAllocator {
|
|||
}
|
||||
}
|
||||
|
||||
private Graph renameInterferenceGraph(Graph graph, final int[] varMap) {
|
||||
GraphBuilder renamedGraph = new GraphBuilder();
|
||||
private void renameInterferenceGraph(List<MutableGraphNode> graph, DisjointSet classes, final int[] varMap) {
|
||||
List<MutableGraphNode> newGraph = new ArrayList<>();
|
||||
for (int i = 0; i < graph.size(); ++i) {
|
||||
for (int j : graph.outgoingEdges(i)) {
|
||||
renamedGraph.addEdge(varMap[i], varMap[j]);
|
||||
int mapped = varMap[i];
|
||||
while (newGraph.size() <= mapped) {
|
||||
newGraph.add(null);
|
||||
}
|
||||
if (newGraph.get(mapped) == null) {
|
||||
int cls = classes.find(i);
|
||||
newGraph.set(mapped, graph.get(cls));
|
||||
graph.get(cls).setTag(mapped);
|
||||
}
|
||||
}
|
||||
return renamedGraph.build();
|
||||
graph.clear();
|
||||
graph.addAll(newGraph);
|
||||
}
|
||||
|
||||
private DisjointSet buildPhiCongruenceClasses(Program program) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user