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