/** Merge the congruence classes containing vertices v1 and v2.; */ public void mergeClasses(OPT_ValueGraphVertex v1, OPT_ValueGraphVertex v2) { if (DEBUG) { System.out.println("@@@@ mergeClasses called with v1 = " + v1 + " ; v2 = " + v2); } int val1 = v1.getValueNumber(); int val2 = v2.getValueNumber(); if (val1 == val2) return; OPT_GVCongruenceClass class1 = (OPT_GVCongruenceClass) B.get(val1); while (true) { OPT_GVCongruenceClass class2 = (OPT_GVCongruenceClass) B.get(val2); Iterator i = class2.iterator(); if (!i.hasNext()) break; OPT_ValueGraphVertex v = (OPT_ValueGraphVertex) i.next(); if (DEBUG) System.out.println("@@@@ moving vertex " + v + " from class " + val2 + " to class " + val1); class1.addVertex(v); class2.removeVertex(v); v.setValueNumber(val1); } // Null out entry for val2 B.set(val2, null); }
/** Print the value numbers for each node in the value graph. */ public void printValueNumbers() { for (Enumeration e = valueGraph.enumerateVertices(); e.hasMoreElements(); ) { OPT_ValueGraphVertex v = (OPT_ValueGraphVertex) e.nextElement(); int valueNumber = v.getValueNumber(); OPT_GVCongruenceClass c = (OPT_GVCongruenceClass) B.get(valueNumber); System.out.println(v.name + " " + valueNumber + " " + c.getLabel()); } }
/** * Does vertex v belong to any congruence class in a vector? If so, returns the value number of * the matching congruence class. If none found, returns -1. * * @param vector a vector of congruence classes * @param v the vertex to search for * @return the value number corresponding to the congruence class containing v. -1 iff no such * class is found. */ private int findCongruenceMatch(ArrayList vector, OPT_ValueGraphVertex v) { for (int i = 0; i < vector.size(); i++) { OPT_GVCongruenceClass klass = (OPT_GVCongruenceClass) vector.get(i); if (checkCongruence(v, klass)) { return klass.getValueNumber(); } } return -1; }
/** * Initialize the congruence classes, assuming that all nodes with the same label are congruent. */ private void initialize() { // store a map from label -> congruenceClass HashMap labelMap = new HashMap(10); for (Enumeration e = valueGraph.enumerateVertices(); e.hasMoreElements(); ) { OPT_ValueGraphVertex v = (OPT_ValueGraphVertex) e.nextElement(); Object label = v.getLabel(); OPT_GVCongruenceClass c = findOrCreateCongruenceClass(label, labelMap); // add this node to the congruence class c.addVertex(v); // set the value number for the node v.setValueNumber(c.getValueNumber()); } }
/** * Initialize the work list. A congruence class gets put on the work list if any two nodes in the * class point to corresponding targets in separate partitions. */ private void initializeWorkList() { for (Iterator it = B.iterator(); it.hasNext(); ) { OPT_GVCongruenceClass c = (OPT_GVCongruenceClass) it.next(); if (c.size() == 1) continue; // store a reference to the first node in c Iterator i = c.iterator(); OPT_ValueGraphVertex first = (OPT_ValueGraphVertex) i.next(); // now check that each other target matches the first element // if not, add this class to the work list congruenceClass: for (; i.hasNext(); ) { OPT_ValueGraphVertex v = (OPT_ValueGraphVertex) i.next(); if (!checkCongruence(first, v)) { workList.push(c); break congruenceClass; } } } }
/** * Assuming congruence class c has changed: find all other classes that might be affected, and add * them to the worklist * * @param c the congruence class that has changed */ private void addDependentClassesToWorklist(OPT_GVCongruenceClass c) { // for each element of this congruence class: for (Iterator elements = c.iterator(); elements.hasNext(); ) { OPT_ValueGraphVertex v = (OPT_ValueGraphVertex) elements.next(); // for each vertex which points to v in the value graph for (Enumeration e = v.inNodes(); e.hasMoreElements(); ) { OPT_ValueGraphVertex in = (OPT_ValueGraphVertex) e.nextElement(); int vn = in.getValueNumber(); OPT_GVCongruenceClass x = (OPT_GVCongruenceClass) B.get(vn); workList.push(x); } } }
/** * Definitely-different relation for two value numbers. Returns true for the following cases: * * <ul> * <li>v1 and v2 are both constants, but don't match * <li>v1 and v2 both result from NEW statements, but don't match * <li>one of v1 and v2 is a parameter, and the other results from a new statement * </ul> * * <p>TODO: add more smarts * * @param v1 first value number * @param v2 second value number * @return true iff the value numbers for two variables are definitely different */ public boolean DD(int v1, int v2) { if ((v1 == -1) || (v2 == -1)) return false; OPT_GVCongruenceClass class1 = (OPT_GVCongruenceClass) B.get(v1); OPT_GVCongruenceClass class2 = (OPT_GVCongruenceClass) B.get(v2); Object label1 = class1.getLabel(); Object label2 = class2.getLabel(); // if one is a constant, they must both be ... if (isConstant(label1) && !isConstant(label2)) return false; if (!isConstant(label1) && isConstant(label2)) return false; if (isConstant(label1)) return (v1 != v2); // handle DD for allocations if (isBornAtAllocation(label1)) { if (isBornAtAllocation(label2)) { // both are NEW. Are they dd? return (v1 != v2); } else if (class2.containsParameter()) { // one is NEW, other is parameter. They are DD. return true; } } else { if (isBornAtAllocation(label2)) { if (class1.containsParameter()) { // one is NEW, other is parameter. They are DD. return true; } } } // assume parameters are not aliased? if (NO_PARAM_ALIAS) { if (v1 != v2) { if (class1.containsParameter()) { if (class2.containsParameter()) { return true; } } } } // if we haven't figured out they're DD, return false; return false; }
/** * Does the current state of the algorithm optimistically assume that a vertex v is congruent to * the vertices in a congruence class? Note: this can return true even if if the value numbers * don't currently match. * * @param v the vertex in question * @param c the congurence class to check * @return true or false */ private boolean checkCongruence(OPT_ValueGraphVertex v, OPT_GVCongruenceClass c) { OPT_ValueGraphVertex r = c.getRepresentative(); boolean result = checkCongruence(r, v); return result; }
/** * Partition a congruence class. * * @param partition the class to partition */ private void partitionClass(OPT_GVCongruenceClass partition) { // store a reference to the first node in c, which will serve // as a representative for this class Iterator i = partition.iterator(); OPT_ValueGraphVertex first = (OPT_ValueGraphVertex) i.next(); ArrayList newClasses = new ArrayList(); // now check each other node in c, to see if it matches the // representative ArrayList toRemove = new ArrayList(); for (; i.hasNext(); ) { OPT_ValueGraphVertex v = (OPT_ValueGraphVertex) i.next(); if (!checkCongruence(first, v)) { // NOT CONGRUENT!! split the partition. first check if // v fits in any other newly created congruence classes int index = findCongruenceMatch(newClasses, v); if (index > -1) { // MATCH FOUND!! place v in newClasses[index] OPT_GVCongruenceClass match = (OPT_GVCongruenceClass) B.get(index); match.addVertex(v); v.setValueNumber(match.getValueNumber()); } else { // NO MATCH FOUND!! create a new congruence class // find the appropriate label for the new congruence class // and create a new congruence class with this label OPT_GVCongruenceClass c = createCongruenceClass(v); newClasses.add(c); c.addVertex(v); v.setValueNumber(c.getValueNumber()); } // mark v as to be removed from partition // (Can't remove it yet while iterating over the set); toRemove.add(v); } } // remove necessary vertices for (Iterator it = toRemove.iterator(); it.hasNext(); ) { OPT_ValueGraphVertex v = (OPT_ValueGraphVertex) it.next(); partition.removeVertex(v); } // if needed place the original partition back on the work list if ((newClasses.size() > 0) && (partition.size() > 1)) { workList.push(partition); } // place any new congruence classes with size > 1 on the worklist // also place any classes which might indirectly be affected for (int j = 0; j < newClasses.size(); j++) { OPT_GVCongruenceClass c = (OPT_GVCongruenceClass) newClasses.get(j); if (c.size() > 1) workList.push(c); addDependentClassesToWorklist(c); } }