/**
  * Return the (integer) value number for a given variable
  *
  * @param name name of the variable to look up
  * @return its value number
  */
 int getValueNumber(Object name) {
   ValueGraphVertex v = valueGraph.getVertex(name);
   if (v == null) {
     return UNKNOWN;
   }
   return v.getValueNumber();
 }
 /** Print the value numbers for each node in the value graph. */
 void printValueNumbers() {
   for (Enumeration<GraphNode> e = valueGraph.enumerateVertices(); e.hasMoreElements(); ) {
     ValueGraphVertex v = (ValueGraphVertex) e.nextElement();
     int valueNumber = v.getValueNumber();
     GVCongruenceClass c = B.get(valueNumber);
     System.out.println(v.getName() + " " + valueNumber + " " + c.getLabel());
   }
 }
 /**
  * Initialize the congruence classes, assuming that all nodes with the same label are congruent.
  */
 private void initialize() {
   // store a map from label -> congruenceClass
   HashMap<Object, GVCongruenceClass> labelMap = new HashMap<Object, GVCongruenceClass>(10);
   for (Enumeration<GraphNode> e = valueGraph.enumerateVertices(); e.hasMoreElements(); ) {
     ValueGraphVertex v = (ValueGraphVertex) e.nextElement();
     Object label = v.getLabel();
     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());
   }
 }
 /**
  * Compute node congruence over the value number graph.
  *
  * <p>Algorithm: Muchnick pp. 348-355
  *
  * <p>Note: the Muchnick algorithm is buggy. In particular, it does not put all needed congruence
  * classes on the worklist.
  *
  * <p>Two nodes in the value graph are congruent if one of the following holds:
  *
  * <ul>
  *   <li>they are the same node
  *   <li>their labels are identical constants
  *   <li>they have the same operators and their operands are congruent
  * </ul>
  *
  * <p>Optimistic algorithm:
  *
  * <ul>
  *   <li>Initially assume all nodes with the same label are congruent
  *   <li>start a work list with all congruence classes that have multiple operands
  *   <li>choose a congruence class from the worklist. partition its elements into new congruence
  *       classes if we can discover that they are not congruent.
  *   <li>Add any newly created congruence classes to the work list.
  *   <li>(Here's the step Muchnick omits:) For each class C which has a dependence on any of the
  *       newly created congruence classes, add C to the work list
  *   <li>repeat until work list is empty
  * </ul>
  *
  * <p>The following method breaks Muchnick's algorithm, which will assign m and n the same value
  * number. Muchnick's problem is that it does not put the congruence class for 'int_mul' back on
  * the worklist when we discover, for example, that i is not congruent to k
  *
  * <pre>
  *   public int foo(int a, int b, int c, int d, int e, int f, int g, int h) {
  *      int i = a+b;
  *      int j = c+d;
  *      int k = e+f;
  *      int l = g+h;
  *      int m = i * j;
  *      int n = k * l;
  *      int o = m/n;
  *      return o;
  *   }
  *  </pre>
  */
 private void globalValueNumber() {
   if (DEBUG) {
     VM.sysWrite(valueGraph.toString());
   }
   // initialize the congurence classes
   initialize();
   // initialize the work list
   initializeWorkList();
   // drain the work list
   while (!workList.empty()) {
     GVCongruenceClass partition = workList.pop();
     partitionClass(partition);
   }
   // all done
   if (DEBUG) {
     printValueNumbers();
   }
 }
 GVCongruenceClass congruenceClass(Object name) {
   ValueGraphVertex v = valueGraph.getVertex(name);
   return B.get(v.getValueNumber());
 }
 /**
  * Definitely-different relation. Returns true for the following cases:
  *
  * <ul>
  *   <li>name1 and name2 are both constants, but don't match
  *   <li>name1 and name2 both result from NEW statements, but don't match
  *   <li>one of name1 and name2 is a parameter, and the other results from a new statement
  * </ul>
  *
  * <p>TODO: add more smarts
  *
  * @param name1 name of first object to compare
  * @param name2 name of second object to compare
  * @return true iff the value numbers for two variables are definitely different
  */
 boolean DD(Object name1, Object name2) {
   ValueGraphVertex v1 = valueGraph.getVertex(name1);
   ValueGraphVertex v2 = valueGraph.getVertex(name2);
   return DD(v1.getValueNumber(), v2.getValueNumber());
 }
 /**
  * Definitely-same relation.
  *
  * @param name1 first variable
  * @param name2 second variable
  * @return true iff the value numbers for two variables are equal
  */
 boolean DS(Object name1, Object name2) {
   ValueGraphVertex v1 = valueGraph.getVertex(name1);
   ValueGraphVertex v2 = valueGraph.getVertex(name2);
   return v1.getValueNumber() == v2.getValueNumber();
 }