/// multiple LiveIntervals.
void ConnectedVNInfoEqClasses::Connect(unsigned a, unsigned b) {
- // Add new eq classes as needed.
- for (unsigned i = eqClass_.size(), m = std::max(a, b); i <= m; ++i)
- eqClass_.push_back(i);
-
- unsigned eqa = eqClass_[a];
- unsigned eqb = eqClass_[b];
- if (eqa == eqb)
- return;
- if (eqa > eqb)
- std::swap(eqa, eqb);
- // Now, eqa < eqb. Switch all eqb members over to eqa.
- for (unsigned i = eqb, e = eqClass_.size(); i != e; ++i)
- if (eqClass_[i] == eqb)
- eqClass_[i] = eqa;
+ while (eqClass_[a] != eqClass_[b]) {
+ if (eqClass_[a] > eqClass_[b])
+ std::swap(a, b);
+ unsigned t = eqClass_[b];
+ assert(t <= b && "Invariant broken");
+ eqClass_[b] = eqClass_[a];
+ b = t;
+ }
}
unsigned ConnectedVNInfoEqClasses::Renumber() {
- // No values at all.
- if (eqClass_.empty())
- return 0;
-
- // Common case: A single connected component.
- if (eqClass_.back() == 0)
- return 1;
-
- // Renumber classes. We use the fact that eqClass_[i] == i for class leaders.
+ // Assign final class numbers.
+ // We use the fact that eqClass_[i] == i for class leaders.
+ // For others, eqClass_[i] points to an earlier value in the same class.
unsigned count = 0;
for (unsigned i = 0, e = eqClass_.size(); i != e; ++i) {
unsigned q = eqClass_[i];
- if (q == i)
- eqClass_[i] = count++;
- else
- eqClass_[i] = eqClass_[q];
+ assert(q <= i && "Invariant broken");
+ eqClass_[i] = q == i ? count++ : eqClass_[q];
}
return count;
}
unsigned ConnectedVNInfoEqClasses::Classify(const LiveInterval *LI) {
- // Determine connections.
+ // Create initial equivalence classes.
eqClass_.clear();
+ eqClass_.reserve(LI->getNumValNums());
+ for (unsigned i = 0, e = LI->getNumValNums(); i != e; ++i)
+ eqClass_.push_back(i);
+
+ const VNInfo *used = 0, *unused = 0;
+
+ // Determine connections.
for (LiveInterval::const_vni_iterator I = LI->vni_begin(), E = LI->vni_end();
I != E; ++I) {
const VNInfo *VNI = *I;
- if (VNI->id == eqClass_.size())
- eqClass_.push_back(VNI->id);
- assert(!VNI->isUnused() && "Cannot handle unused values");
+ // Group all unused values into one class.
+ if (VNI->isUnused()) {
+ if (unused)
+ Connect(unused->id, VNI->id);
+ unused = VNI;
+ continue;
+ }
+ used = VNI;
if (VNI->isPHIDef()) {
const MachineBasicBlock *MBB = lis_.getMBBFromIndex(VNI->def);
assert(MBB && "Phi-def has no defining MBB");
Connect(VNI->id, UVNI->id);
}
}
+
+ // Lump all the unused values in with the last used value.
+ if (used && unused)
+ Connect(used->id, unused->id);
+
return Renumber();
}
++J;
for (LiveInterval::iterator I = J; I != E; ++I) {
if (unsigned eq = eqClass_[I->valno->id]) {
- assert(LIV[eq]->empty() || LIV[eq]->expiredAt(I->start) &&
+ assert((LIV[eq]->empty() || LIV[eq]->expiredAt(I->start)) &&
"New intervals should be empty");
LIV[eq]->ranges.push_back(*I);
} else