Big change to compute logical value numbers for each LiveRange added to an

Interval.  This generalizes the isDefinedOnce mechanism that we used before
to help us coallesce ranges that overlap.  As part of this, every logical
range with a different value is assigned a different number in the interval.
For example, for code that looks like this:

0  X = ...
4  X += ...
  ...
N    = X

We now generate a live interval that contains two ranges: [2,6:0),[6,?:1)
reflecting the fact that there are two different values in the range at
different positions in the code.

Currently we are not using this information at all, so this just slows down
liveintervals.  In the future, this will change.

Note that this change also substantially refactors the joinIntervalsInMachineBB
method to merge the cases for virt-virt and phys-virt joining into a single
case, adds comments, and makes the code a bit easier to follow.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15154 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2004-07-24 02:59:07 +00:00
parent 0f4c076140
commit 7ac2d3146a

View File

@ -106,6 +106,12 @@ bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) {
numIntervals += intervals_.size(); numIntervals += intervals_.size();
#if 1
DEBUG(std::cerr << "********** INTERVALS **********\n");
DEBUG(std::copy(intervals_.begin(), intervals_.end(),
std::ostream_iterator<LiveInterval>(std::cerr, "\n")));
#endif
// join intervals if requested // join intervals if requested
if (EnableJoining) joinIntervals(); if (EnableJoining) joinIntervals();
@ -250,8 +256,9 @@ std::vector<LiveInterval*> LiveIntervals::addIntervalsForSpills(
// the spill weight is now infinity as it // the spill weight is now infinity as it
// cannot be spilled again // cannot be spilled again
nI.weight = HUGE_VAL; nI.weight = HUGE_VAL;
DEBUG(std::cerr << " +" << LiveRange(start, end)); LiveRange LR(start, end, nI.getNextValue());
nI.addRange(LiveRange(start, end)); DEBUG(std::cerr << " +" << LR);
nI.addRange(LR);
added.push_back(&nI); added.push_back(&nI);
// update live variables // update live variables
lv_->addVirtualRegisterKilled(nReg, mi); lv_->addVirtualRegisterKilled(nReg, mi);
@ -286,12 +293,13 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock* mbb,
// done once for the vreg. We use an empty interval to detect the first // done once for the vreg. We use an empty interval to detect the first
// time we see a vreg. // time we see a vreg.
if (interval.empty()) { if (interval.empty()) {
// Assume this interval is singly defined until we find otherwise.
interval.isDefinedOnce = true;
// Get the Idx of the defining instructions. // Get the Idx of the defining instructions.
unsigned defIndex = getDefIndex(getInstructionIndex(mi)); unsigned defIndex = getDefIndex(getInstructionIndex(mi));
unsigned ValNum = interval.getNextValue();
assert(ValNum == 0 && "First value in interval is not 0?");
ValNum = 0; // Clue in the optimizer.
// Loop over all of the blocks that the vreg is defined in. There are // Loop over all of the blocks that the vreg is defined in. There are
// two cases we have to handle here. The most common case is a vreg // two cases we have to handle here. The most common case is a vreg
// whose lifetime is contained within a basic block. In this case there // whose lifetime is contained within a basic block. In this case there
@ -309,8 +317,9 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock* mbb,
if (killIdx > defIndex) { if (killIdx > defIndex) {
assert(vi.AliveBlocks.empty() && assert(vi.AliveBlocks.empty() &&
"Shouldn't be alive across any blocks!"); "Shouldn't be alive across any blocks!");
interval.addRange(LiveRange(defIndex, killIdx)); LiveRange LR(defIndex, killIdx, ValNum);
DEBUG(std::cerr << " +" << LiveRange(defIndex, killIdx) << "\n"); interval.addRange(LR);
DEBUG(std::cerr << " +" << LR << "\n");
return; return;
} }
} }
@ -320,7 +329,7 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock* mbb,
// live into some number of blocks, but gets killed. Start by adding a // live into some number of blocks, but gets killed. Start by adding a
// range that goes from this definition to the end of the defining block. // range that goes from this definition to the end of the defining block.
LiveRange NewLR(defIndex, getInstructionIndex(&mbb->back()) + LiveRange NewLR(defIndex, getInstructionIndex(&mbb->back()) +
InstrSlots::NUM); InstrSlots::NUM, ValNum);
DEBUG(std::cerr << " +" << NewLR); DEBUG(std::cerr << " +" << NewLR);
interval.addRange(NewLR); interval.addRange(NewLR);
@ -332,7 +341,8 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock* mbb,
MachineBasicBlock* mbb = mf_->getBlockNumbered(i); MachineBasicBlock* mbb = mf_->getBlockNumbered(i);
if (!mbb->empty()) { if (!mbb->empty()) {
LiveRange LR(getInstructionIndex(&mbb->front()), LiveRange LR(getInstructionIndex(&mbb->front()),
getInstructionIndex(&mbb->back())+InstrSlots::NUM); getInstructionIndex(&mbb->back())+InstrSlots::NUM,
ValNum);
interval.addRange(LR); interval.addRange(LR);
DEBUG(std::cerr << " +" << LR); DEBUG(std::cerr << " +" << LR);
} }
@ -344,7 +354,7 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock* mbb,
for (unsigned i = 0, e = vi.Kills.size(); i != e; ++i) { for (unsigned i = 0, e = vi.Kills.size(); i != e; ++i) {
MachineInstr *Kill = vi.Kills[i]; MachineInstr *Kill = vi.Kills[i];
LiveRange LR(getInstructionIndex(Kill->getParent()->begin()), LiveRange LR(getInstructionIndex(Kill->getParent()->begin()),
getUseIndex(getInstructionIndex(Kill))+1); getUseIndex(getInstructionIndex(Kill))+1, ValNum);
interval.addRange(LR); interval.addRange(LR);
DEBUG(std::cerr << " +" << LR); DEBUG(std::cerr << " +" << LR);
} }
@ -357,18 +367,44 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock* mbb,
if (mi->getOperand(0).isRegister() && if (mi->getOperand(0).isRegister() &&
mi->getOperand(0).getReg() == interval.reg && mi->getOperand(0).getReg() == interval.reg &&
mi->getOperand(0).isDef() && mi->getOperand(0).isUse()) { mi->getOperand(0).isDef() && mi->getOperand(0).isUse()) {
// If this is a two-address definition, just ignore it. // If this is a two-address definition, then we have already processed
// the live range. The only problem is that we didn't realize there
// are actually two values in the live interval. Because of this we
// need to take the LiveRegion that defines this register and split it
// into two values.
unsigned DefIndex = getDefIndex(getInstructionIndex(vi.DefInst));
unsigned RedefIndex = getDefIndex(getInstructionIndex(mi));
// Delete the initial value, which should be short and continuous,
// becuase the 2-addr copy must be in the same MBB as the redef.
interval.removeRange(DefIndex, RedefIndex);
LiveRange LR(DefIndex, RedefIndex, interval.getNextValue());
DEBUG(std::cerr << " replace range with " << LR);
interval.addRange(LR);
// If this redefinition is dead, we need to add a dummy unit live
// range covering the def slot.
for (LiveVariables::killed_iterator KI = lv_->dead_begin(mi),
E = lv_->dead_end(mi); KI != E; ++KI)
if (KI->second == interval.reg) {
interval.addRange(LiveRange(RedefIndex, RedefIndex+1, 0));
break;
}
DEBUG(std::cerr << "RESULT: " << interval);
} else { } else {
// Otherwise, this must be because of phi elimination. In this case, // Otherwise, this must be because of phi elimination. In this case,
// the defined value will be live until the end of the basic block it // the defined value will be live until the end of the basic block it
// is defined in. // is defined in.
unsigned defIndex = getDefIndex(getInstructionIndex(mi)); unsigned defIndex = getDefIndex(getInstructionIndex(mi));
LiveRange LR(defIndex, LiveRange LR(defIndex,
getInstructionIndex(&mbb->back()) +InstrSlots::NUM); getInstructionIndex(&mbb->back()) + InstrSlots::NUM,
interval.getNextValue());
interval.addRange(LR); interval.addRange(LR);
DEBUG(std::cerr << " +" << LR); DEBUG(std::cerr << " +" << LR);
} }
interval.isDefinedOnce = false;
} }
DEBUG(std::cerr << '\n'); DEBUG(std::cerr << '\n');
@ -402,7 +438,7 @@ void LiveIntervals::handlePhysicalRegisterDef(MachineBasicBlock *MBB,
// If it is not dead on definition, it must be killed by a // If it is not dead on definition, it must be killed by a
// subsequent instruction. Hence its interval is: // subsequent instruction. Hence its interval is:
// [defSlot(def), useSlot(kill)+1) // [defSlot(def), useSlot(kill)+1)
while (1) { while (true) {
++mi; ++mi;
assert(mi != MBB->end() && "physreg was not killed in defining block!"); assert(mi != MBB->end() && "physreg was not killed in defining block!");
baseIndex += InstrSlots::NUM; baseIndex += InstrSlots::NUM;
@ -418,8 +454,9 @@ void LiveIntervals::handlePhysicalRegisterDef(MachineBasicBlock *MBB,
exit: exit:
assert(start < end && "did not find end of interval?"); assert(start < end && "did not find end of interval?");
interval.addRange(LiveRange(start, end)); LiveRange LR(start, end, interval.getNextValue());
DEBUG(std::cerr << " +" << LiveRange(start, end) << '\n'); interval.addRange(LR);
DEBUG(std::cerr << " +" << LR << '\n');
} }
void LiveIntervals::handleRegisterDef(MachineBasicBlock *MBB, void LiveIntervals::handleRegisterDef(MachineBasicBlock *MBB,
@ -472,109 +509,73 @@ void LiveIntervals::computeIntervals()
} }
void LiveIntervals::joinIntervalsInMachineBB(MachineBasicBlock *MBB) { void LiveIntervals::joinIntervalsInMachineBB(MachineBasicBlock *MBB) {
DEBUG(std::cerr << ((Value*)MBB->getBasicBlock())->getName() << ":\n"); DEBUG(std::cerr << ((Value*)MBB->getBasicBlock())->getName() << ":\n");
const TargetInstrInfo& tii = *tm_->getInstrInfo(); const TargetInstrInfo &TII = *tm_->getInstrInfo();
for (MachineBasicBlock::iterator mi = MBB->begin(), mie = MBB->end(); for (MachineBasicBlock::iterator mi = MBB->begin(), mie = MBB->end();
mi != mie; ++mi) { mi != mie; ++mi) {
const TargetInstrDescriptor& tid = tii.get(mi->getOpcode()); DEBUG(std::cerr << getInstructionIndex(mi) << '\t' << *mi);
DEBUG(std::cerr << getInstructionIndex(mi) << '\t';
mi->print(std::cerr, tm_););
// we only join virtual registers with allocatable // we only join virtual registers with allocatable
// physical registers since we do not have liveness information // physical registers since we do not have liveness information
// on not allocatable physical registers // on not allocatable physical registers
unsigned regA, regB; unsigned regA, regB;
if (tii.isMoveInstr(*mi, regA, regB) && if (TII.isMoveInstr(*mi, regA, regB) &&
(MRegisterInfo::isVirtualRegister(regA) || (MRegisterInfo::isVirtualRegister(regA) ||
lv_->getAllocatablePhysicalRegisters()[regA]) && lv_->getAllocatablePhysicalRegisters()[regA]) &&
(MRegisterInfo::isVirtualRegister(regB) || (MRegisterInfo::isVirtualRegister(regB) ||
lv_->getAllocatablePhysicalRegisters()[regB])) { lv_->getAllocatablePhysicalRegisters()[regB])) {
// Get representative registers.
regA = rep(regA);
regB = rep(regB);
// If they are already joined we continue.
if (regA == regB)
continue;
// If they are both physical registers, we cannot join them.
if (MRegisterInfo::isPhysicalRegister(regA) &&
MRegisterInfo::isPhysicalRegister(regB))
continue;
// get representative registers // If they are not of the same register class, we cannot join them.
regA = rep(regA); if (differingRegisterClasses(regA, regB))
regB = rep(regB); continue;
// if they are already joined we continue LiveInterval &IntA = getInterval(regA);
if (regA == regB) LiveInterval &IntB = getInterval(regB);
continue; assert(IntA.reg == regA && IntB.reg == regB &&
"Register mapping is horribly broken!");
bool TriviallyJoinable =
IntA.containsOneValue() && IntB.containsOneValue();
Reg2IntervalMap::iterator r2iA = r2iMap_.find(regA); unsigned MIDefIdx = getDefIndex(getInstructionIndex(mi));
assert(r2iA != r2iMap_.end() && if ((TriviallyJoinable || !IntB.joinable(IntA, MIDefIdx)) &&
"Found unknown vreg in 'isMoveInstr' instruction"); !overlapsAliases(&IntA, &IntB)) {
Reg2IntervalMap::iterator r2iB = r2iMap_.find(regB); IntB.join(IntA, MIDefIdx);
assert(r2iB != r2iMap_.end() &&
"Found unknown vreg in 'isMoveInstr' instruction");
Intervals::iterator intA = r2iA->second; // FIXME: Turn 'intervals_' into an ilist so we don't need to do these
Intervals::iterator intB = r2iB->second; // map lookups!
intervals_.erase(r2iMap_[regA]);
r2iMap_[regA] = r2iMap_[regB];
DEBUG(std::cerr << "\t\tInspecting " << *intA << " and " << *intB if (!MRegisterInfo::isPhysicalRegister(regA)) {
<< ": "); r2rMap_[regA] = regB;
} else {
// both A and B are virtual registers // Otherwise merge the data structures the other way so we don't lose
if (MRegisterInfo::isVirtualRegister(intA->reg) && // the physreg information.
MRegisterInfo::isVirtualRegister(intB->reg)) { r2rMap_[regB] = regA;
IntB.reg = regA;
const TargetRegisterClass *rcA, *rcB;
rcA = mf_->getSSARegMap()->getRegClass(intA->reg);
rcB = mf_->getSSARegMap()->getRegClass(intB->reg);
// if they are not of the same register class we continue
if (rcA != rcB) {
DEBUG(std::cerr << "Differing reg classes.\n");
continue;
}
// if their intervals do not overlap we join them.
if ((intA->containsOneValue() && intB->containsOneValue()) ||
!intB->overlaps(*intA)) {
intA->join(*intB);
++numJoins;
DEBUG(std::cerr << "Joined. Result = " << *intA << "\n");
r2iB->second = r2iA->second;
r2rMap_.insert(std::make_pair(intB->reg, intA->reg));
intervals_.erase(intB);
} else {
DEBUG(std::cerr << "Interference!\n");
}
} else if (!MRegisterInfo::isPhysicalRegister(intA->reg) ||
!MRegisterInfo::isPhysicalRegister(intB->reg)) {
if (MRegisterInfo::isPhysicalRegister(intB->reg)) {
std::swap(regA, regB);
std::swap(intA, intB);
std::swap(r2iA, r2iB);
}
assert(MRegisterInfo::isPhysicalRegister(intA->reg) &&
MRegisterInfo::isVirtualRegister(intB->reg) &&
"A must be physical and B must be virtual");
const TargetRegisterClass *rcA, *rcB;
rcA = mri_->getRegClass(intA->reg);
rcB = mf_->getSSARegMap()->getRegClass(intB->reg);
// if they are not of the same register class we continue
if (rcA != rcB) {
DEBUG(std::cerr << "Differing reg classes.\n");
continue;
}
if (!intA->overlaps(*intB) &&
!overlapsAliases(*intA, *intB)) {
intA->join(*intB);
++numJoins;
DEBUG(std::cerr << "Joined. Result = " << *intA << "\n");
r2iB->second = r2iA->second;
r2rMap_.insert(std::make_pair(intB->reg, intA->reg));
intervals_.erase(intB);
} else {
DEBUG(std::cerr << "Interference!\n");
}
} else {
DEBUG(std::cerr << "Cannot join physregs.\n");
}
} }
DEBUG(std::cerr << "Joined. Result = " << IntB << "\n");
++numJoins;
} else {
DEBUG(std::cerr << "Interference!\n");
}
} }
}
} }
namespace { namespace {
@ -617,16 +618,41 @@ void LiveIntervals::joinIntervals() {
} }
} }
bool LiveIntervals::overlapsAliases(const LiveInterval& lhs, /// Return true if the two specified registers belong to different register
const LiveInterval& rhs) const /// classes. The registers may be either phys or virt regs.
{ bool LiveIntervals::differingRegisterClasses(unsigned RegA,
assert(MRegisterInfo::isPhysicalRegister(lhs.reg) && unsigned RegB) const {
"first interval must describe a physical register"); const TargetRegisterClass *RegClass;
for (const unsigned* as = mri_->getAliasSet(lhs.reg); *as; ++as) { // Get the register classes for the first reg.
Reg2IntervalMap::const_iterator r2i = r2iMap_.find(*as); if (MRegisterInfo::isVirtualRegister(RegA))
RegClass = mf_->getSSARegMap()->getRegClass(RegA);
else
RegClass = mri_->getRegClass(RegA);
// Compare against the regclass for the second reg.
if (MRegisterInfo::isVirtualRegister(RegB))
return RegClass != mf_->getSSARegMap()->getRegClass(RegB);
else
return RegClass != mri_->getRegClass(RegB);
}
bool LiveIntervals::overlapsAliases(const LiveInterval *LHS,
const LiveInterval *RHS) const {
if (!MRegisterInfo::isPhysicalRegister(LHS->reg)) {
if (!MRegisterInfo::isPhysicalRegister(RHS->reg))
return false; // vreg-vreg merge has no aliases!
std::swap(LHS, RHS);
}
assert(MRegisterInfo::isPhysicalRegister(LHS->reg) &&
MRegisterInfo::isVirtualRegister(RHS->reg) &&
"first interval must describe a physical register");
for (const unsigned *AS = mri_->getAliasSet(LHS->reg); *AS; ++AS) {
Reg2IntervalMap::const_iterator r2i = r2iMap_.find(*AS);
assert(r2i != r2iMap_.end() && "alias does not have interval?"); assert(r2i != r2iMap_.end() && "alias does not have interval?");
if (rhs.overlaps(*r2i->second)) if (RHS->overlaps(*r2i->second))
return true; return true;
} }