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