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

Alkis Evlogimenos alkis at cs.uiuc.edu
Wed Jan 7 03:22:01 PST 2004


Changes in directory llvm/lib/CodeGen:

RegAllocLinearScan.cpp updated: 1.24 -> 1.25

---
Log message:

Add a separate list of fixed intervals. This improves the running time
of the register allocator as follows:

       before   after
mesa   2.3790  1.5994
vpr    2.6008  1.2078
gcc    1.9840  0.5273
mcf    0.2569  0.0470
eon    1.8468  1.4359
twolf  0.9475  0.2004
burg   1.6807  1.3300
lambda 1.2191  0.3764

Speedups range anyware from 30% to over 400% :-)


---
Diffs of the changes:  (+112 -65)

Index: llvm/lib/CodeGen/RegAllocLinearScan.cpp
diff -u llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.24 llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.25
--- llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.24	Tue Jan  6 23:31:12 2004
+++ llvm/lib/CodeGen/RegAllocLinearScan.cpp	Wed Jan  7 03:20:58 2004
@@ -40,10 +40,8 @@
         const MRegisterInfo* mri_;
         MachineFunction::iterator currentMbb_;
         MachineBasicBlock::iterator currentInstr_;
-        typedef LiveIntervals::Intervals Intervals;
-        const Intervals* li_;
         typedef std::vector<const LiveIntervals::Interval*> IntervalPtrs;
-        IntervalPtrs active_, inactive_;
+        IntervalPtrs unhandled_, fixed_, active_, inactive_;
 
         typedef std::vector<unsigned> Regs;
         Regs tempUseOperands_;
@@ -78,19 +76,23 @@
         /// runOnMachineFunction - register allocate the whole function
         bool runOnMachineFunction(MachineFunction&);
 
+        /// initIntervalSets - initializa the four interval sets:
+        /// unhandled, fixed, active and inactive
+        void initIntervalSets(const LiveIntervals::Intervals& li);
+
         /// processActiveIntervals - expire old intervals and move
         /// non-overlapping ones to the incative list
-        void processActiveIntervals(Intervals::const_iterator cur);
+        void processActiveIntervals(IntervalPtrs::value_type cur);
 
         /// processInactiveIntervals - expire old intervals and move
         /// overlapping ones to the active list
-        void processInactiveIntervals(Intervals::const_iterator cur);
+        void processInactiveIntervals(IntervalPtrs::value_type cur);
 
         /// assignStackSlotAtInterval - choose and spill
         /// interval. Currently we spill the interval with the last
         /// end point in the active and inactive lists and the current
         /// interval
-        void assignStackSlotAtInterval(Intervals::const_iterator cur);
+        void assignStackSlotAtInterval(IntervalPtrs::value_type cur);
 
         ///
         /// register handling helpers
@@ -99,7 +101,7 @@
         /// getFreePhysReg - return a free physical register for this
         /// virtual register interval if we have one, otherwise return
         /// 0
-        unsigned getFreePhysReg(Intervals::const_iterator cur);
+        unsigned getFreePhysReg(IntervalPtrs::value_type cur);
 
         /// physRegAvailable - returns true if the specifed physical
         /// register is available
@@ -195,9 +197,8 @@
     mf_ = &fn;
     tm_ = &fn.getTarget();
     mri_ = tm_->getRegisterInfo();
-    li_ = &getAnalysis<LiveIntervals>().getIntervals();
-    active_.clear();
-    inactive_.clear();
+
+    initIntervalSets(getAnalysis<LiveIntervals>().getIntervals());
 
     v2pMap_.clear();
     v2ssMap_.clear();
@@ -223,61 +224,88 @@
     reserved_[28] = true; /* FP5 */
     reserved_[29] = true; /* FP6 */
 
-    // liner scan algorithm
-    for (Intervals::const_iterator
-             i = li_->begin(), e = li_->end(); i != e; ++i) {
-        DEBUG(std::cerr << "processing current interval: " << *i << '\n');
-
-        DEBUG(printIntervals("\tactive", active_.begin(), active_.end()));
-        DEBUG(printIntervals("\tinactive", inactive_.begin(), inactive_.end()));
-        processActiveIntervals(i);
-        processInactiveIntervals(i);
-        
-        backupRegUse();
-
-        // for every interval in inactive we overlap mark the register
-        // as not free
-        for (IntervalPtrs::iterator j = inactive_.begin();
-             j != inactive_.end(); ++j) {
-            unsigned reg = (*j)->reg;
-            if (reg >= MRegisterInfo::FirstVirtualRegister)
-                reg = v2pMap_[reg];
+    // linear scan algorithm
 
-            if (i->overlaps(**j)) {
-                markPhysRegNotFree(reg);
-            }
+    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()));
+
+    while (!unhandled_.empty() || !fixed_.empty()) {
+        // pick the interval with the earliest start point
+        IntervalPtrs::value_type cur;
+        if (fixed_.empty()) {
+            cur = unhandled_.front();
+            unhandled_.erase(unhandled_.begin());
+        }
+        else if (unhandled_.empty()) {
+            cur = fixed_.front();
+            fixed_.erase(fixed_.begin());
+        }
+        else if (unhandled_.front()->start() < fixed_.front()->start()) {
+            cur = unhandled_.front();
+            unhandled_.erase(unhandled_.begin());
         }
-
-        // for every pre-allocated interval in unhandled we overlap
-        // mark the register as not free
-        for (Intervals::const_iterator j = i + 1; j != e; ++j) {
-            if (j->reg < MRegisterInfo::FirstVirtualRegister &&
-                i->overlaps(*j))
-                markPhysRegNotFree(j->reg);
+        else {
+            cur = fixed_.front();
+            fixed_.erase(fixed_.begin());
         }
 
-        DEBUG(std::cerr << "\tallocating current interval:\n");
-        // if this register is preallocated reserve it
-        if (i->reg < MRegisterInfo::FirstVirtualRegister) {
-            restoreRegUse();
-            markPhysRegNotFree(i->reg);
-            active_.push_back(&*i);
+        DEBUG(std::cerr << "processing current interval: " << *cur << '\n');
+
+        processActiveIntervals(cur);
+        processInactiveIntervals(cur);
+        
+        // if this register is fixed we are done
+        if (cur->reg < MRegisterInfo::FirstVirtualRegister) {
+            markPhysRegNotFree(cur->reg);
+            active_.push_back(cur);
         }
         // otherwise we are allocating a virtual register. try to find
         // a free physical register or spill an interval in order to
         // assign it one (we could spill the current though).
         else {
-            unsigned physReg = getFreePhysReg(i); 
+            backupRegUse();
+
+            // for every interval in inactive we overlap with, mark the
+            // register as not free
+            for (IntervalPtrs::const_iterator i = inactive_.begin(),
+                     e = inactive_.end(); i != e; ++i) {
+                unsigned reg = (*i)->reg;
+                if (reg >= MRegisterInfo::FirstVirtualRegister)
+                    reg = v2pMap_[reg];
+
+                if (cur->overlaps(**i)) {
+                    markPhysRegNotFree(reg);
+                }
+            }
+
+            // for every interval in fixed we overlap with,
+            // mark the register as not free
+            for (IntervalPtrs::const_iterator i = fixed_.begin(),
+                     e = fixed_.end(); i != e; ++i) {
+                assert((*i)->reg < MRegisterInfo::FirstVirtualRegister &&
+                       "virtual register interval in fixed set?");
+                if (cur->overlaps(**i))
+                    markPhysRegNotFree((*i)->reg);
+            }
+
+            DEBUG(std::cerr << "\tallocating current interval:\n");
+
+            unsigned physReg = getFreePhysReg(cur);
             if (!physReg) {
-                assignStackSlotAtInterval(i);
+                assignStackSlotAtInterval(cur);
             }
             else {
                 restoreRegUse();
-                assignVirt2PhysReg(i->reg, physReg);
-                active_.push_back(&*i);
+                assignVirt2PhysReg(cur->reg, physReg);
+                active_.push_back(cur);
             }
         }
-    }
+
+        DEBUG(printIntervals("\tactive", active_.begin(), active_.end()));
+        DEBUG(printIntervals("\tinactive", inactive_.begin(), inactive_.end()));    }
+
     // expire any remaining active intervals
     for (IntervalPtrs::iterator i = active_.begin(); i != active_.end(); ++i) {
         unsigned reg = (*i)->reg;
@@ -287,6 +315,8 @@
         }
         markPhysRegFree(reg);
     }
+    active_.clear();
+    inactive_.clear();
 
     DEBUG(std::cerr << "finished register allocation\n");
     DEBUG(printVirt2PhysMap());
@@ -378,7 +408,22 @@
     return true;
 }
 
-void RA::processActiveIntervals(Intervals::const_iterator cur)
+void RA::initIntervalSets(const LiveIntervals::Intervals& li)
+{
+    assert(unhandled_.empty() && fixed_.empty() &&
+           active_.empty() && inactive_.empty() &&
+           "interval sets should be empty on initialization");
+
+    for (LiveIntervals::Intervals::const_iterator i = li.begin(), e = li.end();
+         i != e; ++i) {
+        if (i->reg < MRegisterInfo::FirstVirtualRegister)
+            fixed_.push_back(&*i);
+        else
+            unhandled_.push_back(&*i);
+    }
+}
+
+void RA::processActiveIntervals(IntervalPtrs::value_type cur)
 {
     DEBUG(std::cerr << "\tprocessing active intervals:\n");
     for (IntervalPtrs::iterator i = active_.begin(); i != active_.end();) {
@@ -414,7 +459,7 @@
     }
 }
 
-void RA::processInactiveIntervals(Intervals::const_iterator cur)
+void RA::processInactiveIntervals(IntervalPtrs::value_type cur)
 {
     DEBUG(std::cerr << "\tprocessing inactive intervals:\n");
     for (IntervalPtrs::iterator i = inactive_.begin(); i != inactive_.end();) {
@@ -459,7 +504,7 @@
     }
 }
 
-void RA::assignStackSlotAtInterval(Intervals::const_iterator cur)
+void RA::assignStackSlotAtInterval(IntervalPtrs::value_type cur)
 {
     DEBUG(std::cerr << "\t\tassigning stack slot at interval "
           << *cur << ":\n");
@@ -470,7 +515,8 @@
         regWeight[i] = 0.0F;
 
     // for each interval in active that overlaps
-    for (IntervalPtrs::iterator i = active_.begin(); i != active_.end(); ++i) {
+    for (IntervalPtrs::const_iterator i = active_.begin(), e = active_.end();
+         i != e; ++i) {
          if (!cur->overlaps(**i))
              continue;
 
@@ -484,8 +530,8 @@
     }
 
     // for each interval in inactive that overlaps
-    for (IntervalPtrs::iterator i = inactive_.begin();
-         i != inactive_.end(); ++i) {
+    for (IntervalPtrs::const_iterator i = inactive_.begin(),
+             e = inactive_.end(); i != e; ++i) {
          if (!cur->overlaps(**i))
              continue;
 
@@ -498,13 +544,14 @@
             updateWeight(regWeight, *as, (*i)->weight);
     }
 
-    // for each fixed interval in unhandled that overlaps
-    for (Intervals::const_iterator j = cur + 1; j != li_->end(); ++j) {
-        if (j->reg >= MRegisterInfo::FirstVirtualRegister)
-            continue;
-        updateWeight(regWeight, j->reg, j->weight);
-        for (const unsigned* as = mri_->getAliasSet(j->reg); *as; ++as)
-            updateWeight(regWeight, *as, j->weight);
+    // for each fixed interval that overlaps
+    for (IntervalPtrs::const_iterator i = fixed_.begin(), e = fixed_.end();
+         i != e; ++i) {
+        assert((*i)->reg < MRegisterInfo::FirstVirtualRegister &&
+               "virtual register interval in fixed set?");
+        updateWeight(regWeight, (*i)->reg, (*i)->weight);
+        for (const unsigned* as = mri_->getAliasSet((*i)->reg); *as; ++as)
+            updateWeight(regWeight, *as, (*i)->weight);
     }
 
     float minWeight = std::numeric_limits<float>::max();
@@ -569,7 +616,7 @@
             markPhysRegFree(spilled[i]);
 
         assignVirt2PhysReg(cur->reg, physReg);
-        active_.push_back(&*cur);
+        active_.push_back(cur);
     }
 }
 
@@ -581,7 +628,7 @@
     return !regUse_[physReg];
 }
 
-unsigned RA::getFreePhysReg(Intervals::const_iterator cur)
+unsigned RA::getFreePhysReg(IntervalPtrs::value_type cur)
 {
     DEBUG(std::cerr << "\t\tgetting free physical register: ");
     const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(cur->reg);





More information about the llvm-commits mailing list