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

Alkis Evlogimenos alkis at cs.uiuc.edu
Fri Nov 7 18:24:02 PST 2003


Changes in directory llvm/lib/CodeGen:

RegAllocLinearScan.cpp updated: 1.1.2.9 -> 1.1.2.10
LiveIntervals.cpp updated: 1.1.2.7 -> 1.1.2.8

---
Log message:

LiveIntervals:
   - be a little stricter in terms of constness
   - make runOnMachineFunction reentrant
   - make debugging output prettier
   - fix wrong interval computation of variables that get killed in
     their defining basic block
RegAlloc:
   - disable inactive interval processing, handle the simple case for
     now (ignore holes)
   - improve debugging output
   - succeed in register allocating a simple hello world llvm assembly file


---
Diffs of the changes:  (+214 -96)

Index: llvm/lib/CodeGen/RegAllocLinearScan.cpp
diff -u llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.9 llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.10
--- llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.9	Thu Nov  6 03:59:26 2003
+++ llvm/lib/CodeGen/RegAllocLinearScan.cpp	Fri Nov  7 18:23:03 2003
@@ -35,7 +35,7 @@
 
     class RA : public MachineFunctionPass {
     public:
-        typedef std::vector<LiveIntervals::Interval*> IntervalPtrs;
+        typedef std::vector<const LiveIntervals::Interval*> IntervalPtrs;
 
     private:
         MachineFunction* mf_;
@@ -45,8 +45,8 @@
         MachineBasicBlock::iterator currentInstr_;
 
         typedef LiveIntervals::Intervals Intervals;
-        Intervals* li_;
-
+        const Intervals* li_;
+        Intervals::const_iterator currentInterval_;
         IntervalPtrs active_, inactive_;
 
         typedef LiveIntervals::MiIndex2MbbMap MiIndex2MbbMap;
@@ -55,6 +55,9 @@
         typedef LiveIntervals::Mbb2MiIndexMap Mbb2MiIndexMap;
         Mbb2MiIndexMap* mbb2miiMap_;
 
+        typedef LiveIntervals::MachineBasicBlockPtrs MachineBasicBlockPtrs;
+        MachineBasicBlockPtrs mbbs_;
+
         typedef std::map<MachineInstr*, unsigned> Instr2IndexMap;
         Instr2IndexMap i2iMap_;
 
@@ -83,18 +86,22 @@
         /// runOnMachineFunction - register allocate the whole function
         bool runOnMachineFunction(MachineFunction&);
 
+        /// processInterval - entry to the linear scan register
+        /// allocator. this happens one every instruction we look at
+        void processInterval(unsigned curIndex);
+
         /// processActiveIntervals - expire old intervals and move
         /// non-overlapping ones to the incative list
-        void processActiveIntervals(Intervals::iterator cur);
+        void processActiveIntervals(unsigned curIndex);
 
         /// expireOldInterval - expire old intervals and move
         /// overlapping ones to the active list
-        void processInactiveIntervals(Intervals::iterator cur);
+        void processInactiveIntervals(unsigned curIndex);
 
-        /// spillAtInterval - choose and spill at the specified
+        /// spill - choose and spill at the current
         /// interval. Currently we spill the interval with the last
         /// end point in the active and inactive lists
-        void spillAtInterval(Intervals::iterator cur);
+        void spill();
 
         /// getFreeReg - return a free register for this virtual
         /// register if we have one, otherwise return 0
@@ -129,23 +136,29 @@
         /// the virtual register specifed
         void loadPhysReg(unsigned physReg, unsigned virtReg);
 
-        /// getMbbMbbIteratorPair - returns a pair of the
-        /// MachineBasicBlock this instruction is on and the iterator
-        /// pointing to the instruction
-        std::pair<MachineBasicBlock*, MachineBasicBlock::iterator>
-        getMbbMbbIteratorPair(unsigned miIndex) const;
-    };
-}
-
-namespace {
-    void printIntervals(const char* const str,
-                        RA::IntervalPtrs::const_iterator i,
-                        RA::IntervalPtrs::const_iterator e) {
-        if (str) std::cerr << str << " intervals:\n";
-        for (; i != e; ++i) {
-            std::cerr << "\t\t" << **i << '\n';
+        /// getInstructionIndex() - returns the instruction index as
+        /// it was computed by the live interval analysis (adjusts for
+        /// inserted instructions.
+        unsigned getInstructionIndex() const;
+
+        void printVirt2PhysMap() const {
+            std::cerr << "\tallocated registers: ";
+            for (Virt2PhysMap::const_iterator
+                     i = v2pMap_.begin(), e = v2pMap_.end(); i != e; ++i) {
+                std::cerr << '[' << i->first << ','
+                          << mri_->getName(i->second) << "] ";
+            }
+            std::cerr << '\n';
+        }
+        void printIntervals(const char* const str,
+                            RA::IntervalPtrs::const_iterator i,
+                            RA::IntervalPtrs::const_iterator e) const {
+            if (str) std::cerr << str << " intervals:\n";
+            for (; i != e; ++i) {
+                std::cerr << "\t\t" << **i << '\n';
+            }
         }
-    }
+    };
 }
 
 bool RA::runOnMachineFunction(MachineFunction &fn) {
@@ -153,83 +166,165 @@
     tm_ = &fn.getTarget();
     mri_ = tm_->getRegisterInfo();
     li_ = &getAnalysis<LiveIntervals>().getIntervals();
+    currentInterval_ = li_->begin();
     active_.clear();
     inactive_.clear();
     mii2mbbMap_ = &getAnalysis<LiveIntervals>().getMiIndex2MbbMap();
     mbb2miiMap_ = &getAnalysis<LiveIntervals>().getMbb2MiIndexMap();
+    mbbs_ = getAnalysis<LiveIntervals>().getOrderedMachineBasicBlockPtrs();
     p2vMap_.resize(MRegisterInfo::FirstVirtualRegister-1);
     p2vMap_.clear();
     v2pMap_.clear();
     v2ssMap_.clear();
-    instrAdded_ = 0;
-
-    // liner scan algorithm
-    DEBUG(std::cerr << "Processing " << li_->size() << " instervals\n");
-    for (Intervals::iterator i = li_->begin(), e = li_->end(); i != e; ++i) {
-        tie(currentMbb_, currentInstr_) = getMbbMbbIteratorPair(i->start());
-        DEBUG(std::cerr << "instruction[" << i->start() << "]: "
-                        << **currentInstr_);
-        assert(currentInstr_ >= currentMbb_->begin() &&
-               currentInstr_ < currentMbb_->end() &&
-               "current instruction/machine basic block mismatch");
-        DEBUG(printIntervals("\tactive", active_.begin(), active_.end()));
-        DEBUG(printIntervals("\tinactive", inactive_.begin(), inactive_.end()));
 
-        processActiveIntervals(i);
-        processInactiveIntervals(i);
+    for (MachineBasicBlockPtrs::iterator
+             mbbi = mbbs_.begin(), mbbe = mbbs_.end(); mbbi != mbbe; ++mbbi) {
+        instrAdded_ = 0;
+        currentMbb_ = *mbbi;
+        for (currentInstr_ = currentMbb_->begin();
+             currentInstr_ != currentMbb_->end(); ++currentInstr_) {
+
+            assert(currentInstr_ >= currentMbb_->begin() &&
+                   currentInstr_ < currentMbb_->end() &&
+                   "current instruction/machine basic block mismatch");
+            unsigned curIndex = getInstructionIndex();
+            DEBUG(std::cerr << "instruction[" << curIndex << "]: ";
+                  (*currentInstr_)->print(std::cerr, *tm_));
+            DEBUG(std::cerr << "\tcurrent interval: ";
+                  if (currentInterval_ == li_->end()) std::cerr << "NONE\n";
+                  else std::cerr << *currentInterval_ << '\n');
+            DEBUG(printIntervals("\tactive", active_.begin(), active_.end()));
+            DEBUG(printIntervals("\tinactive",
+                                 inactive_.begin(),
+                                 inactive_.end()));
+            DEBUG(printVirt2PhysMap());
+
+            // process the active intervals (this will potentially
+            // free physical registers)
+            processActiveIntervals(curIndex);
+            // processInactiveIntervals(curIndex);
+
+
+            // get used operands into registers
+            DEBUG(std::cerr << "\t\tprocessing operands:\n");
+            for (unsigned i = 0, e = (*currentInstr_)->getNumOperands();
+                 i != e; ++i) {
+                MachineOperand& op = (*currentInstr_)->getOperand(i);
+                if (op.opIsUse() && op.isVirtualRegister()) {
+                    unsigned virtReg = op.getAllocatedRegNum();
+                    Virt2PhysMap::iterator it = v2pMap_.find(virtReg);
+                    if (it == v2pMap_.end()) {
+                        unsigned physReg = it->second;
+                        loadPhysReg(physReg, virtReg);
+                    }
+                }
+            }
+
+            // loop over implicit defs spilling them
+            DEBUG(std::cerr << "\t\tprocessing implicit defs:\n");
+            const TargetInstrDescriptor& tid =
+                tm_->getInstrInfo().get((*currentInstr_)->getOpcode());
+            for (const unsigned* id = tid.ImplicitDefs; *id; ++id) {
+            DEBUG(printVirt2PhysMap());
+                unsigned virtReg = p2vMap_[*id];
+                if (virtReg) {
+                    spillVirtReg(virtReg);
+                    for (IntervalPtrs::iterator
+                             i = active_.begin(); i != active_.end(); ) {
+                        if ((*i)->reg == virtReg) {
+                            i = active_.erase(i);
+                            break;
+                        }
+                        else {
+                            ++i;
+                        }
+                    }
+                }
+            }
+
+            processInterval(curIndex);
+
+            for (unsigned i = 0, e = (*currentInstr_)->getNumOperands();
+                 i != e; ++i) {
+                MachineOperand& op = (*currentInstr_)->getOperand(i);
+                if (op.isVirtualRegister()) {
+                    unsigned virtReg = op.getAllocatedRegNum();
+                    unsigned physReg = v2pMap_[virtReg];
+                    assert(physReg && "should not have virtual registers here");
+                    (*currentInstr_)->SetMachineOperandReg(i, physReg);
+                }
+            }
 
-        unsigned physReg = getFreeReg(i->reg);
-        if (!physReg) {
-            spillAtInterval(i);
-            physReg = getFreeReg(i->reg);
+            DEBUG(std::cerr << "instruction[" << curIndex << "]: ";
+                  (*currentInstr_)->print(std::cerr, *tm_));
         }
-        loadPhysReg(physReg, i->reg);
-        active_.push_back(&*i);
     }
 
     return true;
 }
 
-void RA::processActiveIntervals(Intervals::iterator cur)
+void RA::processInterval(unsigned curIndex)
+{
+    // liner scan algorithm
+    assert((currentInterval_ == li_->end() ||
+            currentInterval_->start() >= curIndex)
+           && "skipping intervals?");
+
+    if (currentInterval_ != li_->end() &&
+        currentInterval_->start() == curIndex) {
+        DEBUG(std::cerr << "\t\tprocessing current interval:\n");
+        unsigned virtReg = currentInterval_->reg;
+        unsigned physReg = getFreeReg(virtReg);
+        if (!physReg) {
+            spill();
+            physReg = getFreeReg(virtReg);
+        }
+        bool inserted = v2pMap_.insert(std::make_pair(virtReg, physReg)).second;
+        assert (inserted && "attempt to allocate already allocated register");
+        markReg(virtReg);
+        active_.push_back(&*currentInterval_);
+        ++currentInterval_;
+    }
+}
+
+void RA::processActiveIntervals(unsigned curIndex)
 {
     DEBUG(std::cerr << "\t\tprocessing active intervals:\n");
-    unsigned curInstrIndex = cur->start();
     for (IntervalPtrs::iterator i = active_.begin(); i != active_.end();) {
         unsigned virtReg = (*i)->reg;
         // remove expired intervals
-        if ((*i)->expired(curInstrIndex)) {
+        if ((*i)->expired(curIndex)) {
             DEBUG(std::cerr << "\t\t\tinterval " << **i << " expired\n");
             freeReg(virtReg);
             // remove interval from active
             i = active_.erase(i);
         }
-        else if (!(*i)->overlaps(curInstrIndex)) {
-            DEBUG(std::cerr << "\t\t\tinterval " << **i << " inactive\n");
-            unmarkReg(virtReg);
-            // add interval to inactive
-            inactive_.push_back(*i);
-            // remove interval from active
-            i = active_.erase(i);
-        }
+//         else if (!(*i)->overlaps(curIndex)) {
+//             DEBUG(std::cerr << "\t\t\tinterval " << **i << " inactive\n");
+//             unmarkReg(virtReg);
+//             // add interval to inactive
+//             inactive_.push_back(*i);
+//             // remove interval from active
+//             i = active_.erase(i);
+//         }
         else {
             ++i;
         }
     }
 }
 
-void RA::processInactiveIntervals(Intervals::iterator cur)
+void RA::processInactiveIntervals(unsigned curIndex)
 {
     DEBUG(std::cerr << "\t\tprocessing inactive intervals:\n");
-    unsigned curInstrIndex = cur->start();
     for (IntervalPtrs::iterator i = inactive_.begin(); i != inactive_.end();) {
         unsigned virtReg = (*i)->reg;
-        if ((*i)->expired(curInstrIndex)) {
+        if ((*i)->expired(curIndex)) {
             DEBUG(std::cerr << "\t\t\tinterval " << **i << " expired\n");
             freeReg(virtReg);
             // remove from inactive
             i = inactive_.erase(i);
         }
-        else if ((*i)->overlaps(curInstrIndex)) {
+        else if ((*i)->overlaps(curIndex)) {
             DEBUG(std::cerr << "\t\t\tinterval " << **i << " active\n");
             markReg(virtReg);
             // add to active
@@ -243,9 +338,9 @@
     }
 }
 
-void RA::spillAtInterval(Intervals::iterator cur)
+void RA::spill()
 {
-    DEBUG(std::cerr << "\t\tspilling at interval " << *cur << ":\n");
+    DEBUG(std::cerr << "\t\tspilling at interval "<< *currentInterval_<< ":\n");
     assert(!active_.empty() &&
            "active set cannot be empty when choosing a register to spill");
     IntervalPtrs::iterator lastEnd = active_.begin();
@@ -294,7 +389,7 @@
 
 unsigned RA::getFreeReg(unsigned virtReg)
 {
-    DEBUG(std::cerr << "\t\tgetting free register: ");
+    DEBUG(std::cerr << "\t\t\tgetting free register: ");
     const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(virtReg);
     TargetRegisterClass::iterator reg = rc->allocation_order_begin(*mf_);
     TargetRegisterClass::iterator regEnd = rc->allocation_order_end(*mf_);
@@ -314,7 +409,6 @@
 void RA::freeReg(unsigned virtReg)
 {
     unmarkReg(virtReg);
-    v2pMap_.erase(v2pMap_.find(virtReg));
 }
 
 void RA::markReg(unsigned virtReg)
@@ -323,6 +417,8 @@
     assert(it != v2pMap_.end() &&
            "attempting to mark an already disassociated register");
     unsigned physReg = it->second;
+    DEBUG(std::cerr << "\t\t\t\tmarked registster " << mri_->getName(physReg)
+          << " used by " << virtReg << '\n');
     p2vMap_[physReg] = virtReg;
 }
 
@@ -330,9 +426,12 @@
 {
     Virt2PhysMap::iterator it = v2pMap_.find(virtReg);
     assert(it != v2pMap_.end() &&
-           "attempting to mark an already disassociated register");
+           "attempting to unmark an already disassociated register");
     unsigned physReg = it->second;
+    DEBUG(std::cerr << "\t\t\t\tmarked registster " << mri_->getName(physReg)
+          << " free\n");
     p2vMap_[physReg] = 0;
+    v2pMap_.erase(it);
 }
 
 int RA::findOrCreateStackSlot(unsigned virtReg)
@@ -352,11 +451,13 @@
 
 void RA::spillVirtReg(unsigned virtReg)
 {
+    DEBUG(std::cerr << "\t\t\tspilling register: " << virtReg << '\n');
     const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(virtReg);
     int frameIndex = findOrCreateStackSlot(virtReg);
     ++numSpilled;
     instrAdded_ += mri_->storeRegToStackSlot(*currentMbb_, currentInstr_,
                                              v2pMap_[virtReg], frameIndex, rc);
+    unmarkReg(virtReg);
 }
 
 void RA::loadPhysReg(unsigned physReg, unsigned virtReg)
@@ -366,17 +467,17 @@
     ++numReloaded;
     instrAdded_ += mri_->loadRegFromStackSlot(*currentMbb_, currentInstr_,
                                               physReg, frameIndex, rc);
-    v2pMap_[virtReg] = physReg;
-    p2vMap_[physReg] = virtReg;
+    bool inserted = v2pMap_.insert(std::make_pair(virtReg, physReg)).second;
+    assert (inserted && "attempt to allocate already allocated register");
+    markReg(virtReg);
 }
 
-std::pair<MachineBasicBlock*, MachineBasicBlock::iterator>
-RA::getMbbMbbIteratorPair(unsigned miIndex) const
+unsigned RA::getInstructionIndex() const
 {
-    MachineBasicBlock* mbb = (*mii2mbbMap_)[miIndex];
-    MachineBasicBlock::iterator instr =
-        mbb->begin() + instrAdded_ + miIndex - (*mbb2miiMap_)[mbb];
-    return std::make_pair(mbb, instr);
+    Mbb2MiIndexMap::const_iterator it = mbb2miiMap_->find(currentMbb_);
+    assert(it != mbb2miiMap_->end() &&
+           "no MachineInstruction index for basic block?");
+    return it->second + (currentInstr_ - currentMbb_->begin()) - instrAdded_;
 }
 
 FunctionPass *createLinearScanRegisterAllocator() {


Index: llvm/lib/CodeGen/LiveIntervals.cpp
diff -u llvm/lib/CodeGen/LiveIntervals.cpp:1.1.2.7 llvm/lib/CodeGen/LiveIntervals.cpp:1.1.2.8
--- llvm/lib/CodeGen/LiveIntervals.cpp:1.1.2.7	Wed Nov  5 20:58:12 2003
+++ llvm/lib/CodeGen/LiveIntervals.cpp	Fri Nov  7 18:23:03 2003
@@ -57,6 +57,13 @@
     tm_ = &fn.getTarget();
     mri_ = tm_->getRegisterInfo();
     lv_ = &getAnalysis<LiveVariables>();
+    mbbi2mbbMap_.clear();
+    mi2iMap_.clear();
+    r2iMap_.clear();
+    r2iMap_.clear();
+    intervals_.clear();
+    mii2mbbMap_.clear();
+    mbb2miiMap_.clear();
 
     // number MachineInstrs
     unsigned miIndex = 0;
@@ -86,21 +93,19 @@
     return true;
 }
 
-namespace {
-    void printRegName(const MRegisterInfo* mri, int reg) {
-        DEBUG(
-            if (reg < MRegisterInfo::FirstVirtualRegister)
-            std::cerr << mri->getName(reg);
-            else
-            std::cerr << '%' << reg);
-    }
+void LiveIntervals::printRegName(unsigned reg) const
+{
+    if (reg < MRegisterInfo::FirstVirtualRegister)
+        std::cerr << mri_->getName(reg);
+    else
+        std::cerr << '%' << reg;
 }
 
 void LiveIntervals::handleRegisterDef(MachineBasicBlock* mbb,
                                       MachineInstr* instr,
                                       unsigned reg)
 {
-    DEBUG(std::cerr << "\t\t\tregister: "; printRegName(mri_, reg));
+    DEBUG(std::cerr << "\t\t\tregister: ";printRegName(reg); std::cerr << '\n');
 
     unsigned instrIndex = getInstructionIndex(instr);
 
@@ -113,8 +118,10 @@
         unsigned ii = r2iit->second;
         Interval& interval = intervals_[ii];
         unsigned end = getInstructionIndex(mbb->back()) + 1;
+        DEBUG(std::cerr << "\t\t\t\tadding range: ["
+              << instrIndex << ',' << end << "]\n");
         interval.addRange(instrIndex, end);
-        DEBUG(std::cerr << " -> " << interval << '\n');
+        DEBUG(std::cerr << "\t\t\t\t" << interval << '\n');
     }
     else {
         // add new interval
@@ -130,28 +137,38 @@
             MachineBasicBlock* liveBlock = it->second;
             if (liveBlockIndex < vi.AliveBlocks.size() &&
                 vi.AliveBlocks[liveBlockIndex]) {
-                unsigned start = mbb == liveBlock ?
-                    instrIndex :
-                    getInstructionIndex(liveBlock->front());
-                interval.addRange(start,
-                                  getInstructionIndex(liveBlock->back()) + 1);
+                unsigned start =  getInstructionIndex(liveBlock->front());
+                unsigned end = getInstructionIndex(liveBlock->back()) + 1;
+                DEBUG(std::cerr << "\t\t\t\tadding range: ["
+                      << start << ',' << end << "]\n");
+                interval.addRange(start, end);
             }
         }
 
+        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 :
-                getInstructionIndex(killerBlock->front());
-            interval.addRange(start,
-                              getInstructionIndex(killerInstr) + 1);
+            killedInDefiningBasicBlock |= mbb == killerBlock;
+            unsigned start = (mbb == killerBlock ?
+                              instrIndex :
+                              getInstructionIndex(killerBlock->front()));
+                unsigned end = getInstructionIndex(killerInstr) + 1;
+                DEBUG(std::cerr << "\t\t\t\tadding range: ["
+                      << start << ',' << end << "]\n");
+                interval.addRange(start, end);
         }
-        DEBUG(std::cerr << " -> " << interval << '\n');
+
+        if (!killedInDefiningBasicBlock) {
+            unsigned end = getInstructionIndex(mbb->back()) + 1;
+            interval.addRange(instrIndex, end);
+        }
+
+        DEBUG(std::cerr << "\t\t\t\t" << interval << '\n');
     }
 }
 
-unsigned LiveIntervals::getInstructionIndex(MachineInstr* instr)
+unsigned LiveIntervals::getInstructionIndex(MachineInstr* instr) const
 {
     assert(mi2iMap_.find(instr) != mi2iMap_.end() &&
            "instruction not assigned a number");
@@ -178,8 +195,8 @@
             const TargetInstrDescriptor& tid =
                 tm_->getInstrInfo().get(instr->getOpcode());
             DEBUG(std::cerr << "\t\tinstruction["
-                  << mi2iMap_.find(instr)->second << "]: "
-                  << *instr << '\n');
+                  << getInstructionIndex(instr) << "]: ";
+                  instr->print(std::cerr, *tm_););
 
             for (int i = instr->getNumOperands() - 1; i >= 0; --i) {
                 MachineOperand& mop = instr->getOperand(i);





More information about the llvm-commits mailing list