[llvm-commits] CVS: llvm/lib/CodeGen/RegAllocLinearScan.cpp LiveIntervals.cpp

Alkis Evlogimenos alkis at niobe.cs.uiuc.edu
Fri Feb 20 00:23:41 PST 2004


Changes in directory llvm/lib/CodeGen:

RegAllocLinearScan.cpp updated: 1.51 -> 1.52
LiveIntervals.cpp updated: 1.54 -> 1.55

---
Log message:

Too many changes in one commit:

1. LiveIntervals now implement a 4 slot per instruction model. Load,
   Use, Def and a Store slot. This is required in order to correctly
   represent caller saved register clobbering on function calls,
   register reuse in the same instruction (def resues last use) and
   also spill code added later by the allocator. The previous
   representation (2 slots per instruction) was insufficient and as a
   result was causing subtle bugs.

2. Fixes in spill code generation. This was the major cause of
   failures in the test suite.

3. Linear scan now has core support for folding memory operands. This
   is untested and not enabled (the live interval update function does
   not attempt to fold loads/stores in instructions).

4. Lots of improvements in the debugging output of both live intervals
   and linear scan. Give it a try... it is beautiful :-)

In summary the above fixes all the issues with the recent reserved
register elimination changes and get the allocator very close to the
next big step: folding memory operands.


---
Diffs of the changes:  (+226 -168)

Index: llvm/lib/CodeGen/RegAllocLinearScan.cpp
diff -u llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.51 llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.52
--- llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.51	Thu Feb 19 13:24:17 2004
+++ llvm/lib/CodeGen/RegAllocLinearScan.cpp	Fri Feb 20 00:15:39 2004
@@ -85,6 +85,7 @@
     private:
         MachineFunction* mf_;
         const TargetMachine* tm_;
+        const TargetInstrInfo* tii_;
         const MRegisterInfo* mri_;
         LiveIntervals* li_;
         typedef std::list<LiveIntervals::Interval*> IntervalPtrs;
@@ -182,12 +183,12 @@
             for (Virt2PhysMap::const_iterator
                      i = v2pMap_.begin(), e = v2pMap_.end(); i != e; ++i) {
                 assert(i->second != 0);
-                std::cerr << '[' << i->first << ','
+                std::cerr << "[reg" << i->first << " -> "
                           << mri_->getName(i->second) << "]\n";
             }
             for (Virt2StackSlotMap::const_iterator
                      i = v2ssMap_.begin(), e = v2ssMap_.end(); i != e; ++i) {
-                std::cerr << '[' << i->first << ",ss#" << i->second << "]\n";
+                std::cerr << '[' << i->first << " -> ss#" << i->second << "]\n";
             }
             std::cerr << '\n';
         }
@@ -197,7 +198,7 @@
                             RA::IntervalPtrs::const_iterator e) const {
             if (str) std::cerr << str << " intervals:\n";
             for (; i != e; ++i) {
-                std::cerr << "\t\t" << **i << " -> ";
+                std::cerr << "\t" << **i << " -> ";
                 unsigned reg = (*i)->reg;
                 if (MRegisterInfo::isVirtualRegister(reg)) {
                     Virt2PhysMap::const_iterator it = v2pMap_.find(reg);
@@ -240,6 +241,7 @@
 bool RA::runOnMachineFunction(MachineFunction &fn) {
     mf_ = &fn;
     tm_ = &fn.getTarget();
+    tii_ = &tm_->getInstrInfo();
     mri_ = tm_->getRegisterInfo();
     li_ = &getAnalysis<LiveIntervals>();
     prt_ = PhysRegTracker(mf_);
@@ -247,12 +249,14 @@
     initIntervalSets(li_->getIntervals());
 
     // linear scan algorithm
-    DEBUG(std::cerr << "Machine Function\n");
-
-    DEBUG(printIntervals("\tunhandled", unhandled_.begin(), unhandled_.end()));
-    DEBUG(printIntervals("\tfixed", fixed_.begin(), fixed_.end()));
-    DEBUG(printIntervals("\tactive", active_.begin(), active_.end()));
-    DEBUG(printIntervals("\tinactive", inactive_.begin(), inactive_.end()));
+    DEBUG(std::cerr << "********** LINEAR SCAN **********\n");
+    DEBUG(std::cerr << "********** Function: "
+          << mf_->getFunction()->getName() << '\n');
+
+    DEBUG(printIntervals("unhandled", unhandled_.begin(), unhandled_.end()));
+    DEBUG(printIntervals("fixed", fixed_.begin(), fixed_.end()));
+    DEBUG(printIntervals("active", active_.begin(), active_.end()));
+    DEBUG(printIntervals("inactive", inactive_.begin(), inactive_.end()));
 
     while (!unhandled_.empty() || !fixed_.empty()) {
         // pick the interval with the earliest start point
@@ -274,7 +278,7 @@
             fixed_.pop_front();
         }
 
-        DEBUG(std::cerr << *cur << '\n');
+        DEBUG(std::cerr << "\n*** CURRENT ***: " << *cur << '\n');
 
         processActiveIntervals(cur);
         processInactiveIntervals(cur);
@@ -292,13 +296,15 @@
             assignRegOrStackSlotAtInterval(cur);
         }
 
-        DEBUG(printIntervals("\tactive", active_.begin(), active_.end()));
-        DEBUG(printIntervals("\tinactive", inactive_.begin(), inactive_.end()));    }
+        DEBUG(printIntervals("active", active_.begin(), active_.end()));
+        DEBUG(printIntervals("inactive", inactive_.begin(), inactive_.end()));
+        // DEBUG(verifyAssignment());
+    }
 
     // expire any remaining active intervals
     for (IntervalPtrs::iterator i = active_.begin(); i != active_.end(); ++i) {
         unsigned reg = (*i)->reg;
-        DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n");
+        DEBUG(std::cerr << "\tinterval " << **i << " expired\n");
         if (MRegisterInfo::isVirtualRegister(reg)) {
             reg = v2pMap_[reg];
         }
@@ -306,25 +312,30 @@
     }
 
     DEBUG(printVirtRegAssignment());
-    DEBUG(std::cerr << "finished register allocation\n");
-    // this is a slow operations do not uncomment
-    // DEBUG(verifyAssignment());
 
-    const TargetInstrInfo& tii = tm_->getInstrInfo();
+    DEBUG(std::cerr << "********** REWRITE MACHINE CODE **********\n");
+    DEBUG(std::cerr << "********** Function: "
+          << mf_->getFunction()->getName() << '\n');
 
-    DEBUG(std::cerr << "Rewrite machine code:\n");
     for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end();
          mbbi != mbbe; ++mbbi) {
         instrAdded_ = 0;
 
         for (MachineBasicBlock::iterator mii = mbbi->begin(), mie = mbbi->end();
              mii != mie; ++mii) {
-            DEBUG(std::cerr << '\t'; mii->print(std::cerr, *tm_));
+            DEBUG(
+                std::cerr << '[';
+                unsigned index = li_->getInstructionIndex(mii);
+                if (index == std::numeric_limits<unsigned>::max())
+                    std::cerr << '*';
+                else
+                    std::cerr << index;
+                std::cerr << "]\t";
+                mii->print(std::cerr, *tm_));
 
             // use our current mapping and actually replace every
             // virtual register with its allocated physical registers
-            DEBUG(std::cerr << "\t\treplacing virtual registers with mapped "
-                  "physical registers:\n");
+            DEBUG(std::cerr << "\t");
             for (unsigned i = 0, e = mii->getNumOperands();
                  i != e; ++i) {
                 MachineOperand& op = mii->getOperand(i);
@@ -336,14 +347,30 @@
                            "all virtual registers must be allocated");
                     unsigned physReg = it->second;
                     assert(MRegisterInfo::isPhysicalRegister(physReg));
-                    DEBUG(std::cerr << "\t\t\t%reg" << virtReg
-                          << " -> " << mri_->getName(physReg) << '\n');
+                    DEBUG(std::cerr << "\t[reg" << virtReg
+                          << " -> " << mri_->getName(physReg) << ']');
                     mii->SetMachineOperandReg(i, physReg);
                 }
             }
+            DEBUG(std::cerr << '\n');
         }
     }
 
+    DEBUG(std::cerr << "********** MACHINEINSTRS **********\n");
+    DEBUG(
+        for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end();
+             mbbi != mbbe; ++mbbi) {
+            for (MachineBasicBlock::iterator mii = mbbi->begin(),
+                     mie = mbbi->end(); mii != mie; ++mii) {
+                unsigned index = li_->getInstructionIndex(mii);
+                if (index == std::numeric_limits<unsigned>::max())
+                    std::cerr << "*\t";
+                else
+                    std::cerr << index << '\t';
+                mii->print(std::cerr, *tm_);
+            }
+        });
+
     return true;
 }
 
@@ -379,7 +406,7 @@
         }
         // move inactive intervals to inactive list
         else if (!(*i)->liveAt(cur->start())) {
-            DEBUG(std::cerr << "\t\t\tinterval " << **i << " inactive\n");
+            DEBUG(std::cerr << "\t\tinterval " << **i << " inactive\n");
             if (MRegisterInfo::isVirtualRegister(reg)) {
                 reg = v2pMap_[reg];
             }
@@ -403,13 +430,13 @@
 
         // remove expired intervals
         if ((*i)->expiredAt(cur->start())) {
-            DEBUG(std::cerr << "\t\t\tinterval " << **i << " expired\n");
+            DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n");
             // remove from inactive
             i = inactive_.erase(i);
         }
         // move re-activated intervals in active list
         else if ((*i)->liveAt(cur->start())) {
-            DEBUG(std::cerr << "\t\t\tinterval " << **i << " active\n");
+            DEBUG(std::cerr << "\t\tinterval " << **i << " active\n");
             if (MRegisterInfo::isVirtualRegister(reg)) {
                 reg = v2pMap_[reg];
             }
@@ -434,7 +461,7 @@
 
 void RA::assignRegOrStackSlotAtInterval(IntervalPtrs::value_type cur)
 {
-    DEBUG(std::cerr << "\tallocating current interval:\n");
+    DEBUG(std::cerr << "\tallocating current interval: ");
 
     PhysRegTracker backupPrt = prt_;
 
@@ -480,16 +507,15 @@
     // the free physical register and add this interval to the active
     // list.
     if (physReg) {
+        DEBUG(std::cerr <<  mri_->getName(physReg) << '\n');
         assignVirt2PhysReg(cur->reg, physReg);
         active_.push_back(cur);
         handled_.push_back(cur);
         return;
     }
+    DEBUG(std::cerr << "no free registers\n");
 
-    DEBUG(std::cerr << "\t\tassigning stack slot at interval "<< *cur << ":\n");
-    // push the current interval back to unhandled since we are going
-    // to re-run at least this iteration
-    unhandled_.push_front(cur);
+    DEBUG(std::cerr << "\tassigning stack slot at interval "<< *cur << ":\n");
 
     float minWeight = std::numeric_limits<float>::infinity();
     unsigned minReg = 0;
@@ -502,21 +528,36 @@
             minReg = reg;
         }
     }
-    DEBUG(std::cerr << "\t\t\tregister with min weight: "
+    DEBUG(std::cerr << "\t\tregister with min weight: "
           << mri_->getName(minReg) << " (" << minWeight << ")\n");
 
     // if the current has the minimum weight, we need to modify it,
     // push it back in unhandled and let the linear scan algorithm run
     // again
-    if (cur->weight < minWeight) {
-        DEBUG(std::cerr << "\t\t\t\tspilling(c): " << *cur;);
+    if (cur->weight <= minWeight) {
+        DEBUG(std::cerr << "\t\t\tspilling(c): " << *cur << '\n';);
         int slot = assignVirt2StackSlot(cur->reg);
-        li_->updateSpilledInterval(*cur);
-        addSpillCode(cur, slot);
-        DEBUG(std::cerr << "[ " << *cur << " ]\n");
+        li_->updateSpilledInterval(*cur, slot);
+
+        // if we didn't eliminate the interval find where to add it
+        // back to unhandled. We need to scan since unhandled are
+        // sorted on earliest start point and we may have changed our
+        // start point.
+        if (!cur->empty()) {
+            addSpillCode(cur, slot);
+            IntervalPtrs::iterator it = unhandled_.begin();
+            while (it != unhandled_.end() && (*it)->start() < cur->start())
+                ++it;
+            unhandled_.insert(it, cur);
+        }
         return;
     }
 
+    // push the current interval back to unhandled since we are going
+    // to re-run at least this iteration. Since we didn't modify it it
+    // should go back right in the front of the list
+    unhandled_.push_front(cur);
+
     // otherwise we spill all intervals aliasing the register with
     // minimum weight, rollback to the interval with the earliest
     // start point and let the linear scan algorithm run again
@@ -526,18 +567,16 @@
         toSpill[*as] = true;
     unsigned earliestStart = cur->start();
 
-    for (IntervalPtrs::iterator i = active_.begin();
-         i != active_.end(); ++i) {
+    for (IntervalPtrs::iterator i = active_.begin(); i != active_.end(); ++i) {
         unsigned reg = (*i)->reg;
         if (MRegisterInfo::isVirtualRegister(reg) &&
             toSpill[v2pMap_[reg]] &&
             cur->overlaps(**i)) {
-            DEBUG(std::cerr << "\t\t\t\tspilling(a): " << **i);
+            DEBUG(std::cerr << "\t\t\tspilling(a): " << **i << '\n');
+            earliestStart = std::min(earliestStart, (*i)->start());
             int slot = assignVirt2StackSlot((*i)->reg);
-            li_->updateSpilledInterval(**i);
+            li_->updateSpilledInterval(**i, slot);
             addSpillCode(*i, slot);
-            DEBUG(std::cerr << "[ " << **i << " ]\n");
-            earliestStart = std::min(earliestStart, (*i)->start());
         }
     }
     for (IntervalPtrs::iterator i = inactive_.begin();
@@ -546,24 +585,23 @@
         if (MRegisterInfo::isVirtualRegister(reg) &&
             toSpill[v2pMap_[reg]] &&
             cur->overlaps(**i)) {
-            DEBUG(std::cerr << "\t\t\t\tspilling(i): " << **i << '\n');
+            DEBUG(std::cerr << "\t\t\tspilling(i): " << **i << '\n');
+            earliestStart = std::min(earliestStart, (*i)->start());
             int slot = assignVirt2StackSlot((*i)->reg);
-            li_->updateSpilledInterval(**i);
+            li_->updateSpilledInterval(**i, slot);
             addSpillCode(*i, slot);
-            DEBUG(std::cerr << "[ " << **i << " ]\n");
-            earliestStart = std::min(earliestStart, (*i)->start());
         }
     }
 
-    DEBUG(std::cerr << "\t\t\t\trolling back to: " << earliestStart << '\n');
+    DEBUG(std::cerr << "\t\trolling back to: " << earliestStart << '\n');
     // scan handled in reverse order and undo each one, restoring the
     // state of unhandled and fixed
     while (!handled_.empty()) {
         IntervalPtrs::value_type i = handled_.back();
         // if this interval starts before t we are done
-        if (i->start() < earliestStart)
+        if (!i->empty() && i->start() < earliestStart)
             break;
-        DEBUG(std::cerr << "\t\t\t\t\tundo changes for: " << *i << '\n');
+        DEBUG(std::cerr << "\t\t\tundo changes for: " << *i << '\n');
         handled_.pop_back();
         IntervalPtrs::iterator it;
         if ((it = find(active_.begin(), active_.end(), i)) != active_.end()) {
@@ -575,8 +613,19 @@
             else {
                 Virt2PhysMap::iterator v2pIt = v2pMap_.find(i->reg);
                 clearVirtReg(v2pIt);
-                unhandled_.push_front(i);
                 prt_.delPhysRegUse(v2pIt->second);
+                if (i->spilled()) {
+                    if (!i->empty()) {
+                        IntervalPtrs::iterator it = unhandled_.begin();
+                        while (it != unhandled_.end() &&
+                               (*it)->start() < i->start())
+                            ++it;
+                        unhandled_.insert(it, i);
+                    }
+                }
+                else
+                    unhandled_.push_front(i);
+
             }
         }
         else if ((it = find(inactive_.begin(), inactive_.end(), i)) != inactive_.end()) {
@@ -586,7 +635,17 @@
             else {
                 Virt2PhysMap::iterator v2pIt = v2pMap_.find(i->reg);
                 clearVirtReg(v2pIt);
-                unhandled_.push_front(i);
+                if (i->spilled()) {
+                    if (!i->empty()) {
+                        IntervalPtrs::iterator it = unhandled_.begin();
+                        while (it != unhandled_.end() &&
+                               (*it)->start() < i->start())
+                            ++it;
+                        unhandled_.insert(it, i);
+                    }
+                }
+                else
+                    unhandled_.push_front(i);
             }
         }
         else {
@@ -606,7 +665,7 @@
     IntervalPtrs::iterator i = handled_.begin(), e = handled_.end();
     for (; i != e; ++i) {
         if (!(*i)->expiredAt(earliestStart) && (*i)->expiredAt(cur->start())) {
-            DEBUG(std::cerr << "\t\t\t\t\tundo changes for: " << **i << '\n');
+            DEBUG(std::cerr << "\t\t\tundo changes for: " << **i << '\n');
             active_.push_back(*i);
             if (MRegisterInfo::isPhysicalRegister((*i)->reg))
                 prt_.addPhysRegUse((*i)->reg);
@@ -627,39 +686,26 @@
 
     for (LiveIntervals::Interval::Ranges::iterator i = li->ranges.begin(),
              e = li->ranges.end(); i != e; ++i) {
-        unsigned index = i->first & ~1;
+        unsigned index = i->first;
         unsigned end = i->second;
 
-    entry:
-        bool dirty = false, loaded = false;
+        bool loaded = false;
 
         // skip deleted instructions. getInstructionFromIndex returns
         // null if the instruction was deleted (because of coalescing
         // for example)
-        while (!li_->getInstructionFromIndex(index)) index += 2;
+        while (!li_->getInstructionFromIndex(index))
+            index += LiveIntervals::InstrSlots::NUM;
         MachineBasicBlock::iterator mi = li_->getInstructionFromIndex(index);
         MachineBasicBlock* mbb = mi->getParent();
+        assert(mbb && "machine instruction not bound to basic block");
 
-        for (; index < end; index += 2) {
+        for (; index < end; index += LiveIntervals::InstrSlots::NUM) {
             // ignore deleted instructions
             while (!li_->getInstructionFromIndex(index)) index += 2;
-
-            // if we changed basic block we need to start over
             mi = li_->getInstructionFromIndex(index);
-            if (mbb != mi->getParent()) {
-                if (dirty) {
-                    mi = li_->getInstructionFromIndex(index-2);
-                    assert(mbb == mi->getParent() &&
-                           "rewound to wrong instruction?");
-                    DEBUG(std::cerr << "add store for reg" << li->reg << " to "
-                          "stack slot " << slot << " after: ";
-                          mi->print(std::cerr, *tm_));
-                    ++numStores;
-                    mri_->storeRegToStackSlot(*mi->getParent(),
-                                              next(mi), li->reg, slot, rc);
-                }
-                goto entry;
-            }
+            DEBUG(std::cerr << "\t\t\t\texamining: \t\t\t\t\t" << index << '\t';
+                  mi->print(std::cerr, *tm_));
 
             // if it is used in this instruction load it
             for (unsigned i = 0; i < mi->getNumOperands(); ++i) {
@@ -667,12 +713,12 @@
                 if (mop.isRegister() && mop.getReg() == li->reg &&
                     mop.isUse() && !loaded) {
                     loaded = true;
-                    DEBUG(std::cerr << "add load for reg" << li->reg
-                          << " from stack slot " << slot << " before: ";
-                          mi->print(std::cerr, *tm_));
+                    mri_->loadRegFromStackSlot(*mbb, mi, li->reg, slot, rc);
                     ++numLoads;
-                    mri_->loadRegFromStackSlot(*mi->getParent(),
-                                               mi, li->reg, slot, rc);
+                    DEBUG(std::cerr << "\t\t\t\tadded load for reg" << li->reg
+                          << " from ss#" << slot << " before: \t"
+                          << LiveIntervals::getBaseIndex(index) << '\t';
+                          mi->print(std::cerr, *tm_));
                 }
             }
 
@@ -680,39 +726,31 @@
             for (unsigned i = 0; i < mi->getNumOperands(); ++i) {
                 MachineOperand& mop = mi->getOperand(i);
                 if (mop.isRegister() && mop.getReg() == li->reg &&
-                    mop.isDef())
-                    dirty = loaded = true;
+                    mop.isDef()) {
+                    loaded = true;
+
+                    mri_->storeRegToStackSlot(*mbb, next(mi), li->reg, slot,rc);
+                    ++numStores;
+                    DEBUG(std::cerr << "\t\t\t\tadded store for reg" << li->reg
+                          << " to ss#" << slot << " after: \t\t"
+                          << LiveIntervals::getBaseIndex(index) << " \t";
+                          prior(mi,2)->print(std::cerr, *tm_));
+                }
             }
         }
-        if (dirty) {
-            mi = li_->getInstructionFromIndex(index-2);
-            assert(mbb == mi->getParent() &&
-                   "rewound to wrong instruction?");
-            DEBUG(std::cerr << "add store for reg" << li->reg << " to "
-                  "stack slot " << slot << " after: ";
-                  mi->print(std::cerr, *tm_));
-            ++numStores;
-            mri_->storeRegToStackSlot(*mi->getParent(),
-                                      next(mi), li->reg, slot, rc);
-        }
     }
 }
 
 unsigned RA::getFreePhysReg(IntervalPtrs::value_type cur)
 {
-    DEBUG(std::cerr << "\t\tgetting free physical register: ");
     const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(cur->reg);
 
     for (TargetRegisterClass::iterator i = rc->allocation_order_begin(*mf_);
          i != rc->allocation_order_end(*mf_); ++i) {
         unsigned reg = *i;
-        if (prt_.isPhysRegAvail(reg)) {
-            DEBUG(std::cerr << mri_->getName(reg) << '\n');
+        if (prt_.isPhysRegAvail(reg))
             return reg;
-        }
     }
-
-    DEBUG(std::cerr << "no free register\n");
     return 0;
 }
 


Index: llvm/lib/CodeGen/LiveIntervals.cpp
diff -u llvm/lib/CodeGen/LiveIntervals.cpp:1.54 llvm/lib/CodeGen/LiveIntervals.cpp:1.55
--- llvm/lib/CodeGen/LiveIntervals.cpp:1.54	Tue Feb 17 22:38:37 2004
+++ llvm/lib/CodeGen/LiveIntervals.cpp	Fri Feb 20 00:15:39 2004
@@ -45,7 +45,8 @@
     Statistic<> numJoined   ("liveintervals", "Number of joined intervals");
     Statistic<> numPeep     ("liveintervals", "Number of identity moves "
                              "eliminated after coalescing");
-
+    Statistic<> numFolded   ("liveintervals", "Number of register operands "
+                             "folded");
     cl::opt<bool>
     join("join-liveintervals",
          cl::desc("Join compatible live intervals"),
@@ -77,7 +78,6 @@
 /// runOnMachineFunction - Register allocate the whole function
 ///
 bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) {
-    DEBUG(std::cerr << "MACHINE FUNCTION: "; fn.print(std::cerr));
     mf_ = &fn;
     tm_ = &fn.getTarget();
     mri_ = tm_->getRegisterInfo();
@@ -98,7 +98,7 @@
             inserted = mi2iMap_.insert(std::make_pair(mi, miIndex)).second;
             assert(inserted && "multiple MachineInstr -> index mappings");
             i2miMap_.push_back(mi);
-            miIndex += 2;
+            miIndex += InstrSlots::NUM;
         }
     }
 
@@ -143,7 +143,7 @@
                 // MachineInstr -> index mappings
                 Mi2IndexMap::iterator mi2i = mi2iMap_.find(mii);
                 if (mi2i != mi2iMap_.end()) {
-                    i2miMap_[mi2i->second/2] = 0;
+                    i2miMap_[mi2i->second/InstrSlots::NUM] = 0;
                     mi2iMap_.erase(mi2i);
                 }
                 mii = mbbi->erase(mii);
@@ -155,14 +155,14 @@
     }
 
     intervals_.sort(StartPointComp());
-    DEBUG(std::cerr << "*** INTERVALS ***\n");
+    DEBUG(std::cerr << "********** INTERVALS **********\n");
     DEBUG(std::copy(intervals_.begin(), intervals_.end(),
                     std::ostream_iterator<Interval>(std::cerr, "\n")));
-    DEBUG(std::cerr << "*** MACHINEINSTRS ***\n");
+    DEBUG(std::cerr << "********** MACHINEINSTRS **********\n");
     DEBUG(
         for (unsigned i = 0; i != i2miMap_.size(); ++i) {
             if (const MachineInstr* mi = i2miMap_[i]) {
-                std:: cerr << i*2 << '\t';
+                std:: cerr << i * InstrSlots::NUM << '\t';
                 mi->print(std::cerr, *tm_);
             }
         });
@@ -170,37 +170,52 @@
     return true;
 }
 
-void LiveIntervals::updateSpilledInterval(Interval& li)
+void LiveIntervals::updateSpilledInterval(Interval& li, int slot)
 {
     assert(li.weight != std::numeric_limits<float>::infinity() &&
            "attempt to spill already spilled interval!");
     Interval::Ranges oldRanges;
     swap(oldRanges, li.ranges);
 
+    DEBUG(std::cerr << "\t\t\t\tupdating interval: " << li);
+
     for (Interval::Ranges::iterator i = oldRanges.begin(), e = oldRanges.end();
          i != e; ++i) {
-        unsigned index = i->first & ~1;
-        unsigned end = i->second;
-
-        for (; index < end; index += 2) {
+        unsigned index = getBaseIndex(i->first);
+        unsigned end = getBaseIndex(i->second-1) + InstrSlots::NUM;
+        for (; index < end; index += InstrSlots::NUM) {
             // skip deleted instructions
-            while (!getInstructionFromIndex(index)) index += 2;
-            MachineInstr* mi = getInstructionFromIndex(index);
+            while (!getInstructionFromIndex(index)) index += InstrSlots::NUM;
+            MachineBasicBlock::iterator mi = getInstructionFromIndex(index);
+
             for (unsigned i = 0; i < mi->getNumOperands(); ++i) {
                 MachineOperand& mop = mi->getOperand(i);
-                if (mop.isRegister()) {
-                    unsigned reg = mop.getReg();
-                    if (rep(reg) == li.reg) {
-                        unsigned start = mop.isUse() ? index : index+1;
-                        unsigned end = mop.isDef() ? index+2 : index+1;
-                        li.addRange(start, end);
-                    }
+                if (mop.isRegister() && mop.getReg() == li.reg) {
+                    // This is tricky. We need to add information in
+                    // the interval about the spill code so we have to
+                    // use our extra load/store slots.
+                    //
+                    // If we have a use we are going to have a load so
+                    // we start the interval from the load slot
+                    // onwards. Otherwise we start from the def slot.
+                    unsigned start = (mop.isUse() ?
+                                      getLoadIndex(index) :
+                                      getDefIndex(index));
+                    // If we have a def we are going to have a store
+                    // right after it so we end the interval after the
+                    // use of the next instruction. Otherwise we end
+                    // after the use of this instruction.
+                    unsigned end = 1 + (mop.isDef() ?
+                                        getUseIndex(index+InstrSlots::NUM) :
+                                        getUseIndex(index));
+                    li.addRange(start, end);
                 }
             }
         }
     }
     // the new spill weight is now infinity as it cannot be spilled again
     li.weight = std::numeric_limits<float>::infinity();
+    DEBUG(std::cerr << '\n');
 }
 
 void LiveIntervals::printRegName(unsigned reg) const
@@ -208,15 +223,14 @@
     if (MRegisterInfo::isPhysicalRegister(reg))
         std::cerr << mri_->getName(reg);
     else
-        std::cerr << '%' << reg;
+        std::cerr << "%reg" << reg;
 }
 
 void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock* mbb,
                                              MachineBasicBlock::iterator mi,
                                              unsigned reg)
 {
-    DEBUG(std::cerr << "\t\tregister: ";printRegName(reg); std::cerr << '\n');
-
+    DEBUG(std::cerr << "\t\tregister: "; printRegName(reg));
     LiveVariables::VarInfo& vi = lv_->getVarInfo(reg);
 
     Interval* interval = 0;
@@ -235,8 +249,9 @@
             if (vi.AliveBlocks[i]) {
                 MachineBasicBlock* mbb = lv_->getIndexMachineBasicBlock(i);
                 if (!mbb->empty()) {
-                    interval->addRange(getInstructionIndex(&mbb->front()),
-                                       getInstructionIndex(&mbb->back()) + 1);
+                    interval->addRange(
+                        getInstructionIndex(&mbb->front()),
+                        getInstructionIndex(&mbb->back()) + InstrSlots::NUM);
                 }
             }
         }
@@ -245,20 +260,20 @@
         interval = &*r2iit->second;
     }
 
-    // we consider defs to happen at the second time slot of the
-    // instruction
-    unsigned instrIndex = getInstructionIndex(mi) + 1;
+    unsigned baseIndex = getInstructionIndex(mi);
 
     bool killedInDefiningBasicBlock = false;
     for (int i = 0, e = vi.Kills.size(); i != e; ++i) {
         MachineBasicBlock* killerBlock = vi.Kills[i].first;
         MachineInstr* killerInstr = vi.Kills[i].second;
         unsigned start = (mbb == killerBlock ?
-                          instrIndex :
+                          getDefIndex(baseIndex) :
                           getInstructionIndex(&killerBlock->front()));
         unsigned end = (killerInstr == mi ?
-                        instrIndex + 1 : // dead
-                        getInstructionIndex(killerInstr) + 1); // killed
+                         // dead
+                        start + 1 :
+                        // killed
+                        getUseIndex(getInstructionIndex(killerInstr))+1);
         // we do not want to add invalid ranges. these can happen when
         // a variable has its latest use and is redefined later on in
         // the same basic block (common with variables introduced by
@@ -270,31 +285,30 @@
     }
 
     if (!killedInDefiningBasicBlock) {
-        unsigned end = getInstructionIndex(&mbb->back()) + 1;
-        interval->addRange(instrIndex, end);
+        unsigned end = getInstructionIndex(&mbb->back()) + InstrSlots::NUM;
+        interval->addRange(getDefIndex(baseIndex), end);
     }
+    DEBUG(std::cerr << '\n');
 }
 
 void LiveIntervals::handlePhysicalRegisterDef(MachineBasicBlock* mbb,
                                               MachineBasicBlock::iterator mi,
                                               unsigned reg)
 {
-    typedef LiveVariables::killed_iterator KillIter;
-
     DEBUG(std::cerr << "\t\tregister: "; printRegName(reg));
+    typedef LiveVariables::killed_iterator KillIter;
 
     MachineBasicBlock::iterator e = mbb->end();
-    // we consider defs to happen at the second time slot of the
-    // instruction
-    unsigned start, end;
-    start = end = getInstructionIndex(mi) + 1;
+    unsigned baseIndex = getInstructionIndex(mi);
+    unsigned start = getDefIndex(baseIndex);
+    unsigned end = start;
 
     // a variable can be dead by the instruction defining it
     for (KillIter ki = lv_->dead_begin(mi), ke = lv_->dead_end(mi);
          ki != ke; ++ki) {
         if (reg == ki->second) {
-            DEBUG(std::cerr << " dead\n");
-            ++end;
+            DEBUG(std::cerr << " dead");
+            end = getDefIndex(start) + 1;
             goto exit;
         }
     }
@@ -302,11 +316,12 @@
     // a variable can only be killed by subsequent instructions
     do {
         ++mi;
-        end += 2;
+        baseIndex += InstrSlots::NUM;
         for (KillIter ki = lv_->killed_begin(mi), ke = lv_->killed_end(mi);
              ki != ke; ++ki) {
             if (reg == ki->second) {
-                DEBUG(std::cerr << " killed\n");
+                DEBUG(std::cerr << " killed");
+                end = getUseIndex(baseIndex) + 1;
                 goto exit;
             }
         }
@@ -325,6 +340,7 @@
         r2iMap_.insert(r2iit, std::make_pair(reg, --intervals_.end()));
         intervals_.back().addRange(start, end);
     }
+    DEBUG(std::cerr << '\n');
 }
 
 void LiveIntervals::handleRegisterDef(MachineBasicBlock* mbb,
@@ -346,12 +362,14 @@
 unsigned LiveIntervals::getInstructionIndex(MachineInstr* instr) const
 {
     Mi2IndexMap::const_iterator it = mi2iMap_.find(instr);
-    return it == mi2iMap_.end() ? std::numeric_limits<unsigned>::max() : it->second;
+    return (it == mi2iMap_.end() ?
+            std::numeric_limits<unsigned>::max() :
+            it->second);
 }
 
 MachineInstr* LiveIntervals::getInstructionFromIndex(unsigned index) const
 {
-    index /= 2; // convert index to vector index
+    index /= InstrSlots::NUM; // convert index to vector index
     assert(index < i2miMap_.size() &&
            "index does not correspond to an instruction");
     return i2miMap_[index];
@@ -363,7 +381,9 @@
 /// which a variable is live
 void LiveIntervals::computeIntervals()
 {
-    DEBUG(std::cerr << "*** COMPUTING LIVE INTERVALS ***\n");
+    DEBUG(std::cerr << "********** COMPUTING LIVE INTERVALS **********\n");
+    DEBUG(std::cerr << "********** Function: "
+          << mf_->getFunction()->getName() << '\n');
 
     for (MbbIndex2MbbMap::iterator
              it = mbbi2mbbMap_.begin(), itEnd = mbbi2mbbMap_.end();
@@ -375,8 +395,8 @@
              mi != miEnd; ++mi) {
             const TargetInstrDescriptor& tid =
                 tm_->getInstrInfo().get(mi->getOpcode());
-            DEBUG(std::cerr << "[" << getInstructionIndex(mi) << "]\t";
-                  mi->print(std::cerr, *tm_););
+            DEBUG(std::cerr << getInstructionIndex(mi) << "\t";
+                  mi->print(std::cerr, *tm_));
 
             // handle implicit defs
             for (const unsigned* id = tid.ImplicitDefs; *id; ++id)
@@ -403,7 +423,7 @@
 
 void LiveIntervals::joinIntervals()
 {
-    DEBUG(std::cerr << "** JOINING INTERVALS ***\n");
+    DEBUG(std::cerr << "********** JOINING INTERVALS ***********\n");
 
     const TargetInstrInfo& tii = tm_->getInstrInfo();
 
@@ -416,7 +436,7 @@
              mi != mie; ++mi) {
             const TargetInstrDescriptor& tid =
                 tm_->getInstrInfo().get(mi->getOpcode());
-            DEBUG(std::cerr << "[" << getInstructionIndex(mi) << "]\t";
+            DEBUG(std::cerr << getInstructionIndex(mi) << '\t';
                   mi->print(std::cerr, *tm_););
 
             // we only join virtual registers with allocatable
@@ -513,17 +533,19 @@
 
 }
 
+bool LiveIntervals::Interval::spilled() const
+{
+    return (weight == std::numeric_limits<float>::infinity() &&
+            MRegisterInfo::isVirtualRegister(reg));
+}
+
 // An example for liveAt():
 //
-// this = [1,2), liveAt(0) will return false. The instruction defining
-// this spans slots [0,1]. Since it is a definition we say that it is
-// live in the second slot onwards. By ending the lifetime of this
-// interval at 2 it means that it is not used at all. liveAt(1)
-// returns true which means that this clobbers a register at
-// instruction at 0.
+// this = [1,4), liveAt(0) will return false. The instruction defining
+// this spans slots [0,3]. The interval belongs to an spilled
+// definition of the variable it represents. This is because slot 1 is
+// used (def slot) and spans up to slot 3 (store slot).
 //
-// this = [1,4), liveAt(0) will return false and liveAt(2) will return
-// true.  The variable is defined at instruction 0 and last used at 2.
 bool LiveIntervals::Interval::liveAt(unsigned index) const
 {
     Range dummy(index, index+1);
@@ -540,14 +562,14 @@
 // An example for overlaps():
 //
 // 0: A = ...
-// 2: B = ...
-// 4: C = A + B ;; last use of A
+// 4: B = ...
+// 8: C = A + B ;; last use of A
 //
 // The live intervals should look like:
 //
-// A = [1, 5)
-// B = [3, x)
-// C = [5, y)
+// A = [3, 11)
+// B = [7, x)
+// C = [11, y)
 //
 // A->overlaps(C) should return false since we want to be able to join
 // A and C.
@@ -592,7 +614,7 @@
 void LiveIntervals::Interval::addRange(unsigned start, unsigned end)
 {
     assert(start < end && "Invalid range to add!");
-    DEBUG(std::cerr << "\t\t\tadding range: [" << start <<','<< end << ") -> ");
+    DEBUG(std::cerr << " +[" << start << ',' << end << ")");
     //assert(start < end && "invalid range?");
     Range range = std::make_pair(start, end);
     Ranges::iterator it =
@@ -601,13 +623,11 @@
 
     it = mergeRangesForward(it);
     it = mergeRangesBackward(it);
-    DEBUG(std::cerr << "\t\t\t\tafter merging: " << *this << '\n');
 }
 
 void LiveIntervals::Interval::join(const LiveIntervals::Interval& other)
 {
-    DEBUG(std::cerr << "\t\t\t\tjoining intervals: "
-          << other << " and " << *this << '\n');
+    DEBUG(std::cerr << "\t\tjoining " << *this << " with " << other << '\n');
     Ranges::iterator cur = ranges.begin();
 
     for (Ranges::const_iterator i = other.ranges.begin(),
@@ -618,8 +638,6 @@
     }
     if (MRegisterInfo::isVirtualRegister(reg))
         weight += other.weight;
-
-    DEBUG(std::cerr << "\t\t\t\tafter merging: " << *this << '\n');
 }
 
 LiveIntervals::Interval::Ranges::iterator
@@ -652,6 +670,8 @@
                                const LiveIntervals::Interval& li)
 {
     os << "%reg" << li.reg << ',' << li.weight << " = ";
+    if (li.empty())
+        return os << "EMPTY";
     for (LiveIntervals::Interval::Ranges::const_iterator
              i = li.ranges.begin(), e = li.ranges.end(); i != e; ++i) {
         os << "[" << i->first << "," << i->second << ")";





More information about the llvm-commits mailing list