void ValueNumberer::breakClass(MDefinition *def) { if (def->valueNumber() == def->id()) { IonSpew(IonSpew_GVN, "Breaking congruence with itself: %d", def->id()); ValueNumberData *defdata = def->valueNumberData(); JS_ASSERT(defdata->classPrev == NULL); // If the def was the only member of the class, then there is nothing to do. if (defdata->classNext == NULL) return; // If upon closer inspection, we are still equivalent to this class // then there isn't anything for us to do. MDefinition *newRep = findSplit(def); if (!newRep) return; ValueNumberData *newdata = newRep->valueNumberData(); // Right now, |defdata| is at the front of the list, and |newdata| is // somewhere in the middle. // // We want to move |defdata| and everything up to but excluding // |newdata| to a new list, with |defdata| still as the canonical // element. // // We then want to take |newdata| and everything after, and // mark them for processing (since |newdata| is now a new canonical // element). // MDefinition *lastOld = newdata->classPrev; JS_ASSERT(lastOld); // newRep is NOT the first element of the list. JS_ASSERT(lastOld->valueNumberData()->classNext == newRep); //lastOld is now the last element of the old list (congruent to //|def|) lastOld->valueNumberData()->classNext = NULL; #ifdef DEBUG for (MDefinition *tmp = def; tmp != NULL; tmp = tmp->valueNumberData()->classNext) { JS_ASSERT(tmp->valueNumber() == def->valueNumber()); JS_ASSERT(tmp->congruentTo(def)); JS_ASSERT(tmp != newRep); } #endif //|newRep| is now the first element of a new list, therefore it is the //new canonical element. Mark the remaining elements in the list //(including |newRep|) newdata->classPrev = NULL; IonSpew(IonSpew_GVN, "Choosing a new representative: %d", newRep->id()); // make the VN of every member in the class the VN of the new representative number. for (MDefinition *tmp = newRep; tmp != NULL; tmp = tmp->valueNumberData()->classNext) { // if this instruction is already scheduled to be processed, don't do anything. if (tmp->isInWorklist()) continue; IonSpew(IonSpew_GVN, "Moving to a new congruence class: %d", tmp->id()); tmp->setValueNumber(newRep->id()); markConsumers(tmp); markDefinition(tmp); } // Insert the new representative => number mapping into the table // Logically, there should not be anything in the table currently, but // old values are never removed, so there's a good chance something will // already be there. values.put(newRep, newRep->id()); } else { // The element that is breaking from the list isn't the representative element // just strip it from the list ValueNumberData *defdata = def->valueNumberData(); if (defdata->classPrev) defdata->classPrev->valueNumberData()->classNext = defdata->classNext; if (defdata->classNext) defdata->classNext->valueNumberData()->classPrev = defdata->classPrev; // Make sure there is no nastinees accidentally linking elements into the old list later. defdata->classPrev = NULL; defdata->classNext = NULL; } }