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