Create an object for tracking physical register usage. This will look
authorAlkis Evlogimenos <alkis@evlogimenos.com>
Mon, 2 Feb 2004 07:30:36 +0000 (07:30 +0000)
committerAlkis Evlogimenos <alkis@evlogimenos.com>
Mon, 2 Feb 2004 07:30:36 +0000 (07:30 +0000)
much better when I get rid of the reserved registers.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@11066 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/RegAllocLinearScan.cpp

index 37be4b4232b3b2c7a6f872a766febe16fb9223f0..69c3120275e9486190094b44a500643aa96f8ccc 100644 (file)
@@ -35,6 +35,69 @@ namespace {
     Statistic<> numPeep    ("ra-linearscan",
                             "Number of identity moves eliminated");
 
+    class PhysRegTracker {
+    private:
+        const MRegisterInfo* mri_;
+        std::vector<bool> reserved_;
+        std::vector<unsigned> regUse_;
+
+    public:
+        PhysRegTracker(MachineFunction* mf)
+            : mri_(mf ? mf->getTarget().getRegisterInfo() : NULL) {
+            if (mri_) {
+                reserved_.assign(mri_->getNumRegs(), false);
+                regUse_.assign(mri_->getNumRegs(), 0);
+            }
+        }
+
+        PhysRegTracker(const PhysRegTracker& rhs)
+            : mri_(rhs.mri_),
+              reserved_(rhs.reserved_),
+              regUse_(rhs.regUse_) {
+        }
+
+        const PhysRegTracker& operator=(const PhysRegTracker& rhs) {
+            mri_ = rhs.mri_;
+            reserved_ = rhs.reserved_;
+            regUse_ = rhs.regUse_;
+            return *this;
+        }
+
+        void reservePhysReg(unsigned physReg) {
+            reserved_[physReg] = true;
+        }
+
+        void addPhysRegUse(unsigned physReg) {
+            ++regUse_[physReg];
+            for (const unsigned* as = mri_->getAliasSet(physReg); *as; ++as) {
+                physReg = *as;
+                ++regUse_[physReg];
+            }
+        }
+
+        void delPhysRegUse(unsigned physReg) {
+            assert(regUse_[physReg] != 0);
+            --regUse_[physReg];
+            for (const unsigned* as = mri_->getAliasSet(physReg); *as; ++as) {
+                physReg = *as;
+                assert(regUse_[physReg] != 0);
+                --regUse_[physReg];
+            }
+        }
+
+        bool isPhysRegReserved(unsigned physReg) const {
+            return reserved_[physReg];
+        }
+
+        bool isPhysRegAvail(unsigned physReg) const {
+            return regUse_[physReg] == 0 && !isPhysRegReserved(physReg);
+        }
+
+        bool isReservedPhysRegAvail(unsigned physReg) const {
+            return regUse_[physReg] == 0 && isPhysRegReserved(physReg);
+        }
+    };
+
     class RA : public MachineFunctionPass {
     private:
         MachineFunction* mf_;
@@ -50,11 +113,7 @@ namespace {
         Regs tempUseOperands_;
         Regs tempDefOperands_;
 
-        typedef std::vector<bool> RegMask;
-        RegMask reserved_;
-
-        unsigned regUse_[MRegisterInfo::FirstVirtualRegister];
-        unsigned regUseBackup_[MRegisterInfo::FirstVirtualRegister];
+        PhysRegTracker prt_;
 
         typedef std::map<unsigned, unsigned> Virt2PhysMap;
         Virt2PhysMap v2pMap_;
@@ -65,6 +124,11 @@ namespace {
         int instrAdded_;
 
     public:
+        RA()
+            : prt_(NULL) {
+
+        }
+
         virtual const char* getPassName() const {
             return "Linear Scan Register Allocator";
         }
@@ -97,7 +161,8 @@ namespace {
         /// interval. Currently we spill the interval with the last
         /// end point in the active and inactive lists and the current
         /// interval
-        void assignStackSlotAtInterval(IntervalPtrs::value_type cur);
+        void assignStackSlotAtInterval(IntervalPtrs::value_type cur,
+                                       const PhysRegTracker& backupPtr);
 
         ///
         /// register handling helpers
@@ -108,14 +173,6 @@ namespace {
         /// 0
         unsigned getFreePhysReg(IntervalPtrs::value_type cur);
 
-        /// physRegAvailable - returns true if the specifed physical
-        /// register is available
-        bool physRegAvailable(unsigned physReg);
-
-        /// tempPhysRegAvailable - returns true if the specifed
-        /// temporary physical register is available
-        bool tempPhysRegAvailable(unsigned physReg);
-
         /// getFreeTempPhysReg - return a free temprorary physical
         /// register for this virtual register if we have one (should
         /// never return 0)
@@ -146,19 +203,9 @@ namespace {
         /// an assigned stack slot
         void loadVirt2PhysReg(unsigned virtReg, unsigned physReg);
 
-        void markPhysRegFree(unsigned physReg);
-        void markPhysRegNotFree(unsigned physReg);
-
-        void backupRegUse() {
-            memcpy(regUseBackup_, regUse_, sizeof(regUseBackup_));
-        }
-
-        void restoreRegUse() {
-            memcpy(regUse_, regUseBackup_, sizeof(regUseBackup_));
-        }
-
         void printVirtRegAssignment() const {
             std::cerr << "register assignment:\n";
+
             for (Virt2PhysMap::const_iterator
                      i = v2pMap_.begin(), e = v2pMap_.end(); i != e; ++i) {
                 assert(i->second != 0);
@@ -187,20 +234,20 @@ namespace {
             }
         }
 
-        void printFreeRegs(const char* const str,
-                           const TargetRegisterClass* rc) const {
-            if (str) std::cerr << str << ':';
-            for (TargetRegisterClass::iterator i =
-                     rc->allocation_order_begin(*mf_);
-                 i != rc->allocation_order_end(*mf_); ++i) {
-                unsigned reg = *i;
-                if (!regUse_[reg]) {
-                    std::cerr << ' ' << mri_->getName(reg);
-                    if (reserved_[reg]) std::cerr << "*";
-                }
-            }
-            std::cerr << '\n';
-        }
+//         void printFreeRegs(const char* const str,
+//                            const TargetRegisterClass* rc) const {
+//             if (str) std::cerr << str << ':';
+//             for (TargetRegisterClass::iterator i =
+//                      rc->allocation_order_begin(*mf_);
+//                  i != rc->allocation_order_end(*mf_); ++i) {
+//                 unsigned reg = *i;
+//                 if (!regUse_[reg]) {
+//                     std::cerr << ' ' << mri_->getName(reg);
+//                     if (reserved_[reg]) std::cerr << "*";
+//                 }
+//             }
+//             std::cerr << '\n';
+//         }
     };
 }
 
@@ -220,10 +267,9 @@ bool RA::runOnMachineFunction(MachineFunction &fn) {
     tm_ = &fn.getTarget();
     mri_ = tm_->getRegisterInfo();
     li_ = &getAnalysis<LiveIntervals>();
-    initIntervalSets(li_->getIntervals());
+    prt_ = PhysRegTracker(mf_);
 
-    memset(regUse_, 0, sizeof(regUse_));
-    memset(regUseBackup_, 0, sizeof(regUseBackup_));
+    initIntervalSets(li_->getIntervals());
 
     // FIXME: this will work only for the X86 backend. I need to
     // device an algorthm to select the minimal (considering register
@@ -234,15 +280,14 @@ bool RA::runOnMachineFunction(MachineFunction &fn) {
     //         R16:  CX,  DI,
     //         R32: ECX, EDI,
     //         RFP: FP5, FP6
-    reserved_.assign(MRegisterInfo::FirstVirtualRegister, false);
-    reserved_[ 8] = true; /*  CH */
-    reserved_[ 9] = true; /*  CL */
-    reserved_[10] = true; /*  CX */
-    reserved_[12] = true; /*  DI */
-    reserved_[18] = true; /* ECX */
-    reserved_[19] = true; /* EDI */
-    reserved_[28] = true; /* FP5 */
-    reserved_[29] = true; /* FP6 */
+    prt_.reservePhysReg( 8); /*  CH */
+    prt_.reservePhysReg( 9); /*  CL */
+    prt_.reservePhysReg(10); /*  CX */
+    prt_.reservePhysReg(12); /*  DI */
+    prt_.reservePhysReg(18); /* ECX */
+    prt_.reservePhysReg(19); /* EDI */
+    prt_.reservePhysReg(28); /* FP5 */
+    prt_.reservePhysReg(29); /* FP6 */
 
     // linear scan algorithm
     DEBUG(std::cerr << "Machine Function\n");
@@ -279,14 +324,14 @@ bool RA::runOnMachineFunction(MachineFunction &fn) {
 
         // if this register is fixed we are done
         if (MRegisterInfo::isPhysicalRegister(cur->reg)) {
-            markPhysRegNotFree(cur->reg);
+            prt_.addPhysRegUse(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 {
-            backupRegUse();
+            PhysRegTracker backupPrt = prt_;
 
             // for every interval in inactive we overlap with, mark the
             // register as not free
@@ -297,7 +342,7 @@ bool RA::runOnMachineFunction(MachineFunction &fn) {
                     reg = v2pMap_[reg];
 
                 if (cur->overlaps(**i)) {
-                    markPhysRegNotFree(reg);
+                    prt_.addPhysRegUse(reg);
                 }
             }
 
@@ -308,17 +353,17 @@ bool RA::runOnMachineFunction(MachineFunction &fn) {
                 assert(MRegisterInfo::isPhysicalRegister((*i)->reg) &&
                        "virtual register interval in fixed set?");
                 if (cur->overlaps(**i))
-                    markPhysRegNotFree((*i)->reg);
+                    prt_.addPhysRegUse((*i)->reg);
             }
 
             DEBUG(std::cerr << "\tallocating current interval:\n");
 
             unsigned physReg = getFreePhysReg(cur);
             if (!physReg) {
-                assignStackSlotAtInterval(cur);
+                assignStackSlotAtInterval(cur, backupPrt);
             }
             else {
-                restoreRegUse();
+                prt_ = backupPrt;
                 assignVirt2PhysReg(cur->reg, physReg);
                 active_.push_back(cur);
             }
@@ -334,7 +379,7 @@ bool RA::runOnMachineFunction(MachineFunction &fn) {
         if (MRegisterInfo::isVirtualRegister(reg)) {
             reg = v2pMap_[reg];
         }
-        markPhysRegFree(reg);
+        prt_.delPhysRegUse(reg);
     }
 
     typedef LiveIntervals::Reg2RegMap Reg2RegMap;
@@ -514,7 +559,7 @@ void RA::processActiveIntervals(IntervalPtrs::value_type cur)
             if (MRegisterInfo::isVirtualRegister(reg)) {
                 reg = v2pMap_[reg];
             }
-            markPhysRegFree(reg);
+            prt_.delPhysRegUse(reg);
             // remove from active
             i = active_.erase(i);
         }
@@ -524,7 +569,7 @@ void RA::processActiveIntervals(IntervalPtrs::value_type cur)
             if (MRegisterInfo::isVirtualRegister(reg)) {
                 reg = v2pMap_[reg];
             }
-            markPhysRegFree(reg);
+            prt_.delPhysRegUse(reg);
             // add to inactive
             inactive_.push_back(*i);
             // remove from active
@@ -554,7 +599,7 @@ void RA::processInactiveIntervals(IntervalPtrs::value_type cur)
             if (MRegisterInfo::isVirtualRegister(reg)) {
                 reg = v2pMap_[reg];
             }
-            markPhysRegNotFree(reg);
+            prt_.addPhysRegUse(reg);
             // add to active
             active_.push_back(*i);
             // remove from inactive
@@ -578,7 +623,8 @@ namespace {
     }
 }
 
-void RA::assignStackSlotAtInterval(IntervalPtrs::value_type cur)
+void RA::assignStackSlotAtInterval(IntervalPtrs::value_type cur,
+                                   const PhysRegTracker& backupPrt)
 {
     DEBUG(std::cerr << "\t\tassigning stack slot at interval "
           << *cur << ":\n");
@@ -631,7 +677,7 @@ void RA::assignStackSlotAtInterval(IntervalPtrs::value_type cur)
     for (TargetRegisterClass::iterator i = rc->allocation_order_begin(*mf_);
          i != rc->allocation_order_end(*mf_); ++i) {
         unsigned reg = *i;
-        if (!reserved_[reg] && minWeight > regWeight[reg]) {
+        if (!prt_.isPhysRegReserved(reg) && minWeight > regWeight[reg]) {
             minWeight = regWeight[reg];
             minReg = reg;
         }
@@ -640,7 +686,7 @@ void RA::assignStackSlotAtInterval(IntervalPtrs::value_type cur)
           << mri_->getName(minReg) << " (" << minWeight << ")\n");
 
     if (cur->weight < minWeight) {
-        restoreRegUse();
+        prt_ = backupPrt;
         DEBUG(std::cerr << "\t\t\t\tspilling: " << *cur << '\n');
         assignVirt2StackSlot(cur->reg);
     }
@@ -684,23 +730,15 @@ void RA::assignStackSlotAtInterval(IntervalPtrs::value_type cur)
         unsigned physReg = getFreePhysReg(cur);
         assert(physReg && "no free physical register after spill?");
 
-        restoreRegUse();
+        prt_ = backupPrt;
         for (unsigned i = 0; i < spilled.size(); ++i)
-            markPhysRegFree(spilled[i]);
+            prt_.delPhysRegUse(spilled[i]);
 
         assignVirt2PhysReg(cur->reg, physReg);
         active_.push_back(cur);
     }
 }
 
-bool RA::physRegAvailable(unsigned physReg)
-{
-    assert(!reserved_[physReg] &&
-           "cannot call this method with a reserved register");
-
-    return !regUse_[physReg];
-}
-
 unsigned RA::getFreePhysReg(IntervalPtrs::value_type cur)
 {
     DEBUG(std::cerr << "\t\tgetting free physical register: ");
@@ -709,7 +747,7 @@ unsigned RA::getFreePhysReg(IntervalPtrs::value_type cur)
     for (TargetRegisterClass::iterator i = rc->allocation_order_begin(*mf_);
          i != rc->allocation_order_end(*mf_); ++i) {
         unsigned reg = *i;
-        if (!reserved_[reg] && !regUse_[reg]) {
+        if (prt_.isPhysRegAvail(reg)) {
             DEBUG(std::cerr << mri_->getName(reg) << '\n');
             return reg;
         }
@@ -719,14 +757,6 @@ unsigned RA::getFreePhysReg(IntervalPtrs::value_type cur)
     return 0;
 }
 
-bool RA::tempPhysRegAvailable(unsigned physReg)
-{
-    assert(reserved_[physReg] &&
-           "cannot call this method with a not reserved temp register");
-
-    return !regUse_[physReg];
-}
-
 unsigned RA::getFreeTempPhysReg(unsigned virtReg)
 {
     DEBUG(std::cerr << "\t\tgetting free temporary physical register: ");
@@ -738,7 +768,7 @@ unsigned RA::getFreeTempPhysReg(unsigned virtReg)
              i(rc->allocation_order_end(*mf_)),
              e(rc->allocation_order_begin(*mf_)); i != e; ++i) {
         unsigned reg = *i;
-        if (reserved_[reg] && !regUse_[reg]) {
+        if (prt_.isReservedPhysRegAvail(reg)) {
             DEBUG(std::cerr << mri_->getName(reg) << '\n');
             return reg;
         }
@@ -753,7 +783,7 @@ void RA::assignVirt2PhysReg(unsigned virtReg, unsigned physReg)
     bool inserted = v2pMap_.insert(std::make_pair(virtReg, physReg)).second;
     assert(inserted && "attempting to assign a virt->phys mapping to an "
            "already mapped register");
-    markPhysRegNotFree(physReg);
+    prt_.addPhysRegUse(physReg);
 }
 
 void RA::clearVirtReg(unsigned virtReg)
@@ -762,7 +792,7 @@ void RA::clearVirtReg(unsigned virtReg)
     assert(it != v2pMap_.end() &&
            "attempting to clear a not allocated virtual register");
     unsigned physReg = it->second;
-    markPhysRegFree(physReg);
+    prt_.delPhysRegUse(physReg);
     v2pMap_.erase(it);
     DEBUG(std::cerr << "\t\t\tcleared register " << mri_->getName(physReg)
           << "\n");
@@ -817,26 +847,6 @@ void RA::loadVirt2PhysReg(unsigned virtReg, unsigned physReg)
     assignVirt2PhysReg(virtReg, physReg);
 }
 
-void RA::markPhysRegFree(unsigned physReg)
-{
-    assert(regUse_[physReg] != 0);
-    --regUse_[physReg];
-    for (const unsigned* as = mri_->getAliasSet(physReg); *as; ++as) {
-        physReg = *as;
-        assert(regUse_[physReg] != 0);
-        --regUse_[physReg];
-    }
-}
-
-void RA::markPhysRegNotFree(unsigned physReg)
-{
-    ++regUse_[physReg];
-    for (const unsigned* as = mri_->getAliasSet(physReg); *as; ++as) {
-        physReg = *as;
-        ++regUse_[physReg];
-    }
-}
-
 FunctionPass* llvm::createLinearScanRegisterAllocator() {
     return new RA();
 }