One more speed-up of register allocation

This commit is contained in:
konsoletyper 2014-03-15 14:58:27 +04:00
parent 8d0c412634
commit aacc7e08d2
5 changed files with 99 additions and 82 deletions

View File

@ -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 {

View File

@ -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();
}
}

View File

@ -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;
}

View File

@ -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) {

View File

@ -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) {