/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.compilers.opt.regalloc;
import java.util.HashMap;
import org.jikesrvm.compilers.opt.ir.Register;
import org.jikesrvm.compilers.opt.util.GraphEdge;
import org.jikesrvm.compilers.opt.util.SpaceEffGraph;
import org.jikesrvm.compilers.opt.util.SpaceEffGraphEdge;
import org.jikesrvm.compilers.opt.util.SpaceEffGraphNode;
import org.jikesrvm.compilers.opt.util.SpaceEffGraphNode.GraphEdgeEnumeration;
/**
* This class represents a graph, where
* <ul>
* <li> the nodes are registers
* <li> the edge weights represent affinities between registers.
* </ul>
* <p>
* This graph is used to drive coalescing during register allocation.
* <p>
* Implementation: this is meant to be an undirected graph. By
* convention, we enforce that the register with the lower number is the
* source of an edge.
*/
class CoalesceGraph extends SpaceEffGraph {
/**
* Mapping register -> Node
*/
final HashMap<Register, Node> nodeMap = new HashMap<Register, Node>();
private Node findOrCreateNode(Register r) {
Node n = nodeMap.get(r);
if (n == null) {
n = new Node(r);
nodeMap.put(r, n);
addGraphNode(n);
}
return n;
}
Node findNode(Register r) {
return nodeMap.get(r);
}
private Edge findOrCreateEdge(Node src, Node dest) {
Edge edge = null;
for (GraphEdgeEnumeration<GraphEdge> e = src.outEdges(); e.hasMoreElements();) {
Edge candidate = (Edge)e.next();
if (candidate.toNode() == dest) {
edge = candidate;
break;
}
}
if (edge == null) {
edge = new Edge(src, dest);
addGraphEdge(edge);
}
return edge;
}
void addAffinity(int w, Register r1, Register r2) {
Node src;
Node dest;
if (r1.getNumber() == r2.getNumber()) return;
// the register with the smaller number is the source of the edge.
if (r1.getNumber() < r2.getNumber()) {
src = findOrCreateNode(r1);
dest = findOrCreateNode(r2);
} else {
src = findOrCreateNode(r2);
dest = findOrCreateNode(r1);
}
Edge edge = findOrCreateEdge(src, dest);
edge.addWeight(w);
}
static class Node extends SpaceEffGraphNode {
final Register r;
Node(Register r) {
this.r = r;
}
Register getRegister() {
return r;
}
}
static class Edge extends SpaceEffGraphEdge {
private int w;
Edge(Node src, Node dest) {
super(src, dest);
}
void addWeight(int x) {
w += x;
}
int getWeight() {
return w;
}
}
}