/** 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);
   }
 }