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

Alkis Evlogimenos alkis at cs.uiuc.edu
Fri Oct 24 01:08:19 PDT 2003


Changes in directory llvm/lib/CodeGen:

LiveIntervals.cpp added (r1.1.2.1)
Passes.cpp updated: 1.1.2.1 -> 1.1.2.2
RegAllocLinearScan.cpp updated: 1.1.2.3 -> 1.1.2.4

---
Log message:

Add live interval analysis pass

---
Diffs of the changes:  (+575 -48)

Index: llvm/lib/CodeGen/LiveIntervals.cpp
diff -c /dev/null llvm/lib/CodeGen/LiveIntervals.cpp:1.1.2.1
*** /dev/null	Fri Oct 24 01:06:57 2003
--- llvm/lib/CodeGen/LiveIntervals.cpp	Fri Oct 24 01:06:47 2003
***************
*** 0 ****
--- 1,208 ----
+ //===-- LiveIntervals.cpp - Linear Scan register allocator --------------===//
+ // 
+ //                     The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ // 
+ //===--------------------------------------------------------------------===//
+ //
+ // This file implements the LiveInterval analysis pass which is used
+ // by the Linear Scan Register allocator. This pass linearizes the
+ // basic blocks of the function in DFS order and uses the
+ // LiveVariables pass to conservatively compute live intervals for
+ // each virtual and physical register.
+ //
+ //===--------------------------------------------------------------------===//
+ 
+ #define DEBUG_TYPE "liveintervals"
+ #include "llvm/CodeGen/LiveIntervals.h"
+ #include "llvm/Function.h"
+ #include "llvm/CodeGen/LiveVariables.h"
+ #include "llvm/CodeGen/MachineFrameInfo.h"
+ #include "llvm/CodeGen/MachineFunctionPass.h"
+ #include "llvm/CodeGen/MachineInstr.h"
+ #include "llvm/CodeGen/Passes.h"
+ #include "llvm/CodeGen/SSARegMap.h"
+ #include "llvm/Target/MRegisterInfo.h"
+ #include "llvm/Target/TargetInstrInfo.h"
+ #include "llvm/Target/TargetMachine.h"
+ #include "llvm/Target/TargetRegInfo.h"
+ #include "llvm/Support/CFG.h"
+ #include "Support/Debug.h"
+ #include "Support/DepthFirstIterator.h"
+ #include "Support/Statistic.h"
+ #include <iostream>
+ 
+ namespace {
+     RegisterAnalysis<LiveIntervals> X("liveintervals",
+                                       "Live Interval Analysis");
+ 
+     Statistic<> numIntervals("liveintervals", "Number of intervals");
+ };
+ 
+ void LiveIntervals::getAnalysisUsage(AnalysisUsage &AU) const
+ {
+     AU.setPreservesAll();
+     AU.addRequired<LiveVariables>();
+     MachineFunctionPass::getAnalysisUsage(AU);
+ }
+ 
+ /// runOnMachineFunction - Register allocate the whole function
+ ///
+ bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) {
+     DEBUG(std::cerr << "Machine Function\n");
+     _mf = &fn;
+     _tm = &fn.getTarget();
+     _mri = _tm->getRegisterInfo();
+     _lv = &getAnalysis<LiveVariables>();
+ 
+     // create a mapping from BasicBlock* to MachineBasicBlock*
+     typedef std::map<const BasicBlock*, MachineBasicBlock*> BB2MBBMap;
+     BB2MBBMap bb2mbbMap;
+     for (MachineFunction::iterator mbb = _mf->begin(), mbbEnd = _mf->end();
+          mbb != mbbEnd; ++mbb) {
+         bool inserted = bb2mbbMap.insert(
+             std::make_pair(mbb->getBasicBlock(), &*mbb)).second;
+         assert(inserted && "multiple BasicBlock -> MachineBasicBlock mappings");
+     }
+ 
+     // add MachineBasicBlocks in depth first order
+     _mbbOrder.clear();
+     _mbbOrder.reserve(bb2mbbMap.size());
+     const BasicBlock* entry = _mf->getFunction()->begin();
+     for (df_iterator<const BasicBlock*>
+              bb = df_begin(entry), bbEnd = df_end(entry);
+          bb != bbEnd; ++bb) {
+         MachineBasicBlock* mbb = bb2mbbMap.find(*bb)->second;
+         _mbbOrder.push_back(mbb);
+         assert(mbb && "MachineBasicBlock for BasicBlock cannot be null");
+     }
+     
+     _i2iMap.clear();
+ 
+     computeIntervals();
+ 
+     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::handleRegisterDef(Reg2IntervalMap& r2iMap,
+                                       unsigned i,
+                                       unsigned reg)
+ {
+     DEBUG(std::cerr << "\t\t\t\tregister: "; printRegName(_mri, reg));
+ 
+     assert((reg < MRegisterInfo::FirstVirtualRegister ||
+             r2iMap.find(reg) == r2iMap.end()) &&
+            "multiple definitions of virtual register");
+     // initialize intervals to [index, inf] - be conservative!
+     _intervals.push_back(
+         Interval(reg, i, std::numeric_limits<unsigned>::max()));
+     // update last live interval for this register
+     r2iMap[reg] = _intervals.size() - 1;
+ 
+     DEBUG(std::cerr << " -> ADD interval " << _intervals.back() << '\n');
+ }
+ 
+ void LiveIntervals::handleRegisterKill(Reg2IntervalMap& r2iMap,
+                                        unsigned i,
+                                        unsigned reg)
+ {
+     DEBUG(std::cerr << "\t\t\t\tregister: "; printRegName(_mri, reg));
+ 
+     Reg2IntervalMap::iterator ri = r2iMap.find(reg);
+     assert(ri != r2iMap.end()
+            && "did not find live interval for killed register");
+     Interval& interval = _intervals[ri->second];
+     // if this is a later kill remark the end here - be conservative!
+     interval.end = i;
+ 
+     DEBUG(std::cerr << " -> END interval " << interval << '\n');
+ }
+ 
+ /// computeIntervals - computes the live intervals for virtual
+ /// registers. for some ordering of the machine instructions [1,N] a
+ /// live interval is an interval [i, j] where 1 <= i <= j <= N for
+ /// which a variable is live
+ void LiveIntervals::computeIntervals()
+ {
+     DEBUG(std::cerr << "computing live intervals:\n");
+ 
+     // register -> last live interval index
+     Reg2IntervalMap r2iMap;
+ 
+     unsigned index = 0;
+     for (MBBPtrs::iterator it = _mbbOrder.begin(), itEnd = _mbbOrder.end();
+          it != itEnd; ++it) {
+         MachineBasicBlock* mbb = *it;
+         DEBUG(std::cerr << "machine basic block: " << mbb);
+         for (MachineBasicBlock::iterator mi = mbb->begin(), miEnd = mbb->end();
+              mi != miEnd; ++index, ++mi) {
+             MachineInstr* instr = *mi;
+             const TargetInstrDescriptor& tid =
+                 _tm->getInstrInfo().get(instr->getOpcode());
+             _i2iMap.insert(std::make_pair(instr, index));
+             DEBUG(std::cerr << "\t\tinstruction[" << index << "]: "
+                             << *instr << '\n');
+ 
+             DEBUG(std::cerr << "\t\t\thandling implicit definitions:\n");
+             for (const unsigned* id = tid.ImplicitDefs; *id; ++id) {
+                 unsigned reg = *id;
+                 handleRegisterDef(r2iMap, index, reg);
+             }
+ 
+             DEBUG(std::cerr << "\t\t\thandling kills:\n");
+             for (LiveVariables::killed_iterator
+                      ki = _lv->killed_begin(instr),
+                      kiEnd = _lv->killed_end(instr);
+                  ki != kiEnd; ++ki) {
+                 unsigned reg = ki->second;
+                 handleRegisterKill(r2iMap, index, reg);
+             }
+ 
+             DEBUG(std::cerr << "\t\t\thandling definitions:\n");
+             for (int i = instr->getNumOperands() - 1; i >= 0; --i) {
+                 MachineOperand& mop = instr->getOperand(i);
+ 
+                 if (!mop.isRegister())
+                     continue;
+ 
+                 // mark start and end points
+                 unsigned reg = mop.getAllocatedRegNum();
+                 if (mop.opIsDefOnly() || mop.opIsDefAndUse()) {
+                     handleRegisterDef(r2iMap, index, reg);
+                 }
+             }
+         }
+ 
+         // kill all physical registers in the end of each basic block
+         for (Intervals::iterator it =
+                  _intervals.begin(), itEnd = _intervals.end();
+              it != itEnd; ++it) {
+             unsigned reg = it->reg;
+             if (reg < MRegisterInfo::FirstVirtualRegister) {
+                 handleRegisterKill(r2iMap, index, reg);
+             }
+         }
+     }
+ 
+     // sort the live intervals in increasing start point
+     sort(_intervals.begin(), _intervals.end(), StartPointComp());
+ 
+     DEBUG(
+         for(Intervals::iterator
+                 it = _intervals.begin(), itEnd = _intervals.end();
+             it != itEnd; ++it) {
+             std::cerr << *it << '\n';
+         });
+ }


Index: llvm/lib/CodeGen/Passes.cpp
diff -u llvm/lib/CodeGen/Passes.cpp:1.1.2.1 llvm/lib/CodeGen/Passes.cpp:1.1.2.2
--- llvm/lib/CodeGen/Passes.cpp:1.1.2.1	Thu Oct  2 12:17:02 2003
+++ llvm/lib/CodeGen/Passes.cpp	Fri Oct 24 01:06:47 2003
@@ -15,9 +15,9 @@
   RegAlloc("regalloc",
            cl::desc("Register allocator to use: (default = simple)"),
            cl::Prefix,
-           cl::values(clEnumVal(simple, "  simple register allocator"),
-                      clEnumVal(local,  "  local register allocator"),
-                      clEnumVal(local,  "  linear-scan global register allocator"),
+           cl::values(clEnumVal(simple,      "  simple register allocator"),
+                      clEnumVal(local,       "  local register allocator"),
+                      clEnumVal(linearscan,  "  linear-scan global register allocator"),
                       0),
            cl::init(local));
 }


Index: llvm/lib/CodeGen/RegAllocLinearScan.cpp
diff -u llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.3 llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.4
--- llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.3	Thu Oct  2 02:26:01 2003
+++ llvm/lib/CodeGen/RegAllocLinearScan.cpp	Fri Oct 24 01:06:47 2003
@@ -1,71 +1,390 @@
 //===-- RegAllocLinearScan.cpp - Linear Scan register allocator ---------===//
 //
-// This file implements a linear scan register allocator..
+// This file implements a linear scan register allocator.
 //
 //===--------------------------------------------------------------------===//
 
 #define DEBUG_TYPE "regalloc"
-#include "llvm/CodeGen/Passes.h"
+#include "llvm/Function.h"
+#include "llvm/CodeGen/LiveIntervals.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/SSARegMap.h"
 #include "llvm/Target/MRegisterInfo.h"
+#include "llvm/Target/TargetInstrInfo.h"
 #include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetRegInfo.h"
+#include "llvm/Support/CFG.h"
 #include "Support/Debug.h"
+#include "Support/DepthFirstIterator.h"
 #include "Support/Statistic.h"
 #include <iostream>
 
 namespace {
-  Statistic<> NumSpilled ("ra-linearscan", "Number of registers spilled");
-  Statistic<> NumReloaded("ra-linearscan", "Number of registers reloaded");
+    Statistic<> numSpilled ("ra-linearscan", "Number of registers spilled");
+    Statistic<> numReloaded("ra-linearscan", "Number of registers reloaded");
+
+    class RA : public MachineFunctionPass {
+    private:
+        MachineFunction* _mf;
+        const TargetMachine* _tm;
+        const TargetRegInfo* _tri;
+        const MRegisterInfo* _mri;
+        MachineBasicBlock* _currentMbb;
+        MachineBasicBlock::iterator _currentInstr;
+
+        LiveIntervals* _li;
+
+        typedef std::map<MachineInstr*, unsigned> Instr2IndexMap;
+        Instr2IndexMap _i2iMap;
+
+        typedef std::vector<unsigned> Phys2VirtMap;
+        Phys2VirtMap _p2vMap;
+
+        typedef std::map<unsigned, unsigned> Virt2PhysMap;
+        Virt2PhysMap _v2pMap;
+
+        typedef std::map<unsigned, int> Virt2StackSlotMap;
+        Virt2StackSlotMap _v2ssMap;
+
+    public:
+        virtual const char* getPassName() const {
+            return "Linear Scan Register Allocator";
+        }
+
+        virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+            AU.addRequiredID(PHIEliminationID);
+            AU.addRequired<LiveIntervals>();
+            MachineFunctionPass::getAnalysisUsage(AU);
+        }
+
+    private:
+        /// runOnMachineFunction - Register allocate the whole function
+        bool runOnMachineFunction(MachineFunction&);
+
+        /// expireOldIntervals - in each iteration of the linear scan
+        /// loop, expire the old intervals; that is the registers that
+        /// are killed
+//         void expireOldIntervals(Intervals::iterator li);
+
+        /// spillAtInterval - choose and spill at the specified
+        /// interval. Currently we spill using a heuristic: the active
+        /// interval that ends last
+//         void spillAtInterval(Intervals::iterator li);
+
+        /// computeIntervals - computes the live intervals for
+        /// virtual registers
+        void computeIntervals();
+
+        /// getFreeReg - return a free register for this virtual
+        /// register if we have one, otherwise return 0
+        unsigned getFreeReg(unsigned virtReg);
+
+        /// physRegAvailable - returns true if the specifed physical
+        /// register is available
+        bool physRegAvailable(unsigned physReg);
+
+        /// findOrCreateStackSlot - returns the offset of the
+        /// specified register on the stack allocating space if
+        /// necessary
+        int findOrCreateStackSlot(unsigned virtReg);
+
+        /// spillVirtReg - spills the virtual register
+        void spillVirtReg(unsigned virtReg, unsigned physReg);
+
+        /// loadPhysReg - loads to the physical register the value of
+        /// the virtual register specifed
+        void loadPhysReg(unsigned physReg, unsigned virtReg);
+    };
+}
+
+/// runOnMachineFunction - Register allocate the whole function
+///
+bool RA::runOnMachineFunction(MachineFunction &fn) {
+    DEBUG(std::cerr << "Machine Function\n");
+    _mf = &fn;
+    _tm = &fn.getTarget();
+    _tri = &_tm->getRegInfo();
+    _mri = _tm->getRegisterInfo();
+    _li = &getAnalysis<LiveIntervals>();
+    _p2vMap.resize(_mri->getNumRegs());
+    _p2vMap.clear();
+    _v2pMap.clear();
+    _v2ssMap.clear();
+
+//    computeIntervals();
+
+//     // liner scan algorithm
+//     for (Intervals::iterator li = _intervals.begin(), liEnd = _intervals.end();
+//          li != liEnd; ++li) {
+//         // FIXME: find a more efficient way to keep track of the
+//         // iterator on the current instruction
+//         MachineInstr* mi = _instrOrdering[li->start].first;
+//         _currentMbb = _instrOrdering[li->start].second;
+//         _currentInstr = find(_currentMbb->begin(), _currentMbb->end(), mi);
+//         assert(_currentInstr != _currentMbb->end() &&
+//                "Cannot find instruction in basic block");
+//         // check if this interval is for a physical or a virtual register
+//         if (li->mop->isVirtualRegister()) {
+//             expireOldIntervals(li);
+//             if (unsigned physReg = getFreeReg(li->mop->getAllocatedRegNum())) {
+//                 loadPhysReg(physReg, li->mop->getAllocatedRegNum());
+//             }
+//             else {
+//                 spillAtInterval(li);
+//             }
+//         }
+//         else {
+//             // spill register if it is used
+//             // mark register as used
+//         }
+//     }
 
-  class RA : public MachineFunctionPass {
-  private:
-    MachineFunction *MF;
-    const TargetMachine *TM;
-    const MRegisterInfo *RegInfo;
-
-    // StackSlotForVirtReg - Maps virtual regs to the frame index where these
-    // values are spilled.
-    std::map<unsigned, int> StackSlotForVirtReg;
-
-    // Virt2PhysRegMap - This map contains entries for each virtual register
-    // that is currently available in a physical register.
-    //
-    std::map<unsigned, unsigned> Virt2PhysRegMap;
-
-    // Phys2VirtRegMap - This map contains entries for each physical register
-    // that currently maps a virtual register..
-    //
-    std::map<unsigned, unsigned> Phys2VirtRegMap;
-
-  public:
-    virtual const char* getPassName() const {
-      return "Linear Scan Register Allocator";
+    return true;
+}
+
+/// computeIntervals - computes the live intervals for virtual
+/// registers. for some ordering of the machine instructions [1,N] a
+/// live interval is an interval [i, j] where 1 <= i <= j <= N for
+/// which a variable is live
+void RA::computeIntervals()
+{
+    DEBUG(std::cerr << "\tcomputing live intervals:\n");
+
+    // create a mapping from BasicBlock* to MachineBasicBlock*
+    typedef std::map<const BasicBlock*, MachineBasicBlock*> BB2MBBMap;
+    BB2MBBMap bb2mbbMap;
+    for (MachineFunction::iterator mbb = _mf->begin(), mbbEnd = _mf->end();
+         mbb != mbbEnd; ++mbb) {
+        bool inserted = bb2mbbMap.insert(
+            std::make_pair(mbb->getBasicBlock(), &*mbb)).second;
+        assert(inserted && "multiple BasicBlock -> MachineBasicBlock mappings");
     }
-    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
-      AU.addRequiredID(PHIEliminationID);
-      MachineFunctionPass::getAnalysisUsage(AU);
+
+    // depth first ordering for the instructions (use depth first
+    // ordering of BasicBlocks, map to MachineBasicBlocks and
+    // sequentially order the instructions in each block
+    const BasicBlock* entry = _mf->getFunction()->begin();
+
+    // register -> live interval index
+    typedef std::map<unsigned, unsigned> Reg2IntervalMap;
+    Reg2IntervalMap r2iMap;
+
+    unsigned index = 0;
+//     for (df_iterator<const BasicBlock*>
+//              bb = df_begin(entry), bbEnd = df_end(entry);
+//          bb != bbEnd; ++bb) {
+//         MachineBasicBlock* mbb = bb2mbbMap.find(*bb)->second;
+//         assert(mbb && "MachineBasicBlock for BasicBlock cannot be null");
+
+//         for (MachineBasicBlock::iterator mi = mbb->begin(), miEnd = mbb->end();
+//              mi != miEnd; ++index, ++mi) {
+//             MachineInstr* instr = *mi;
+//             const TargetInstrDescriptor& tid =
+//                 _tm->getInstrInfo().get(instr->getOpcode());
+//             _i2iMap.insert(std::make_pair(instr, index));
+//             DEBUG(std::cerr << "\t\tinstruction[" << index << "]: " << *instr << '\n');
+//             for (const unsigned* id =tid.ImplicitDefs; *id; ++id) {
+//                 unsigned reg = *id;
+//                 assert(r2iMap.find(reg) == r2iMap.end() &&
+//                        "multiple definitions of virtual register");
+//                 // initialize intervals to [index, inf]
+//                 _intervals.push_back(
+//                     Interval(reg,
+//                              index,
+//                              std::numeric_limits<unsigned>::max()));
+//                 r2iMap.insert(std::make_pair(reg, _intervals.size() - 1));
+//                 DEBUG(std::cerr << "\t\t\tadded interval for register "
+//                       << _tri->getUnifiedRegName(reg)
+//                       << ": " << _intervals.back() << '\n');
+//             }
+
+//             for (int i = instr->getNumOperands() - 1; i >= 0; --i) {
+//                 MachineOperand& mop = instr->getOperand(i);
+
+//                 if (!mop.isRegister())
+//                     continue;
+
+//                 // mark start and end points
+//                 if (mop.opIsDefOnly() || mop.opIsDefAndUse()) {
+//                     Intervals::iterator li;
+//                     unsigned reg = mop.getAllocatedRegNum();
+//                     assert(r2iMap.find(reg) == r2iMap.end() &&
+//                            "multiple definitions of virtual register");
+//                     // initialize intervals to [index, inf]
+//                     _intervals.push_back(
+//                         Interval(reg,
+//                                  index,
+//                                  std::numeric_limits<unsigned>::max()));
+//                     r2iMap.insert(std::make_pair(reg, _intervals.size() - 1));
+//                     DEBUG(std::cerr << "\t\t\tadded interval for register "
+//                           << _tri->getUnifiedRegName(reg)
+//                           << ": " << _intervals.back() << '\n');
+//                 }
+//             }
+
+//             for (LiveVariables::killed_iterator
+//                      ki = _lv->killed_begin(instr),
+//                      kiEnd = _lv->killed_end(instr);
+//                  ki != kiEnd; ++ki) {
+//                 unsigned reg = ki->second;
+//                 DEBUG(std::cerr << "\t\t\tmarking end of interval for register " << _tri->getUnifiedRegName(reg) << '\n');
+//                 Reg2IntervalMap::iterator ri = r2iMap.find(reg);
+//                 assert(ri != r2iMap.end()
+//                        && "did not find interval for killed register");
+//                 Interval& interval = _intervals[ri->second];
+//                 assert(interval.end > index
+//                        && "attempt to mark killed an already killed variable");
+//                 interval.end = index;
+//             }
+//         }
+
+//         // kill all physical registers in the end of each basic block
+//         for (Intervals::iterator it =
+//                  _intervals.begin(), itEnd = _intervals.end();
+//              it != itEnd; ++it) {
+//             if (it->reg < MRegisterInfo::FirstVirtualRegister) {
+//                 Reg2IntervalMap::iterator ri = r2iMap.find(it->reg);
+//                 assert(ri != r2iMap.end()
+//                        && "did not find interval for killed register");
+//                 Interval& interval = _intervals[ri->second];
+//                 assert(interval.end > index
+//                        && "attempt to mark killed an already killed variable");
+//                 interval.end = index;
+//             }
+//         }
+//     }
+
+//     // sort the live intervals in increasing start point
+//     sort(_intervals.begin(), _intervals.end(), StartPointComp());
+
+//     DEBUG(
+//         for(Intervals::iterator
+//                 it = _intervals.begin(), itEnd = _intervals.end();
+//             it != itEnd; ++it) {
+//             std::cerr << *it << '\n';
+//         });
+}
+
+//// expireOldIntervals - expire the old intervals
+////
+// void RA::expireOldIntervals(Intervals::iterator li)
+// {
+//     // the active list is sorted on increasing end point
+//     IntervalPtrs::iterator lip = _active.begin();
+//     for (IntervalPtrs::iterator lipEnd = _active.end();
+//          lip != lipEnd && (*lip)->end < li->start;
+//          ++lip) {
+//         unsigned reg = li->reg;
+//         // if it is a virtual register
+//         if (reg >= MRegisterInfo::FirstVirtualRegister) {
+//             Virt2PhysMap::iterator it = _v2pMap.find(reg);
+//             assert(it != _v2pMap.end());
+//             reg = it->second;
+//             _v2pMap.erase(it);
+//         }
+//         assert(_p2vMap[reg] != 0);
+//         _p2vMap[reg] = 0;
+//     }
+//     _active.erase(_active.begin(), lip);
+// }
+
+//// spillAtInterval - chooses and spills a register for this
+//// interval. The heuristic here is the register with the last end
+//// point thus it can be either the last of the active list or the
+//// current one
+////
+// void RA::spillAtInterval(Intervals::iterator li)
+// {
+//     assert(!_active.empty() && "active set cannot be empty when choosing a register to spill");
+//     Interval* toSpill = _active.back();
+//     // if last in active is ending after the current spill it and add
+//     // current to active
+//     if (toSpill->end > li->end) {
+//         // spill register toSpill->mop->getAllocatedRegNum();
+//         _active.pop_back();
+//         for(IntervalPtrs::iterator it = _active.begin(), itEnd = _active.end();
+//             it != itEnd; ++it) {
+//             if ((*it)->end > li->end) {
+//                 _active.insert(it, &*li);
+//             }
+//         }
+//     }
+//     // spill the current
+//     else {
+//         // spill register li->mop->getAllocatedRegNum()
+//     }
+// }
+
+bool RA::physRegAvailable(unsigned physReg)
+{
+    if (_p2vMap[physReg]) {
+        return false;
     }
 
-  private:
-    /// runOnMachineFunction - Register allocate the whole function
-    bool runOnMachineFunction(MachineFunction &Fn);
-  };
+    // if it aliases other registers it is still not free
+    for (const unsigned* as = _mri->getAliasSet(physReg); *as; ++as) {
+        if (_p2vMap[*as]) {
+            return false;
+        }
+    }
+
+    return true;
 }
 
-/// runOnMachineFunction - Register allocate the whole function
-///
-bool RA::runOnMachineFunction(MachineFunction &Fn) {
-  DEBUG(std::cerr << "Machine Function " << "\n");
-  MF = &Fn;
-  TM = &Fn.getTarget();
-  RegInfo = TM->getRegisterInfo();
+unsigned RA::getFreeReg(unsigned virtReg)
+{
+    const TargetRegisterClass* rc = _mf->getSSARegMap()->getRegClass(virtReg);
+    TargetRegisterClass::iterator reg = rc->allocation_order_begin(*_mf);
+    TargetRegisterClass::iterator regEnd = rc->allocation_order_end(*_mf);
+
+    for (; reg != regEnd; ++reg) {
+        if (physRegAvailable(*reg)) {
+            assert(*reg != 0 && "Cannot use register!");
+            return *reg; // Found an unused register!
+        }
+    }
+
+    return 0;
+}
 
-  // compute live intervals
-  // liner scan algorithm
+int RA::findOrCreateStackSlot(unsigned virtReg)
+{
+    // use lower_bound so that we can do a O(1) insert later if necessary
+    Virt2StackSlotMap::iterator it = _v2ssMap.lower_bound(virtReg);
+    if (it != _v2ssMap.end() && it->first == virtReg) {
+        return it->second;
+    }
+    const TargetRegisterClass* rc = _mf->getSSARegMap()->getRegClass(virtReg);
+    int frameIndex = _mf->getFrameInfo()->CreateStackObject(rc);
+
+    _v2ssMap.insert(it, std::make_pair(virtReg, frameIndex));
+
+    return frameIndex;
+}
+
+void RA::spillVirtReg(unsigned virtReg, unsigned physReg)
+{
+    const TargetRegisterClass* rc = _mf->getSSARegMap()->getRegClass(virtReg);
+    int frameIndex = findOrCreateStackSlot(virtReg);
+    ++numSpilled;
+    _mri->storeRegToStackSlot(*_currentMbb, _currentInstr,
+                              physReg, frameIndex, rc);
+}
 
-  return true;
+void RA::loadPhysReg(unsigned physReg, unsigned virtReg)
+{
+    const TargetRegisterClass* rc = _mf->getSSARegMap()->getRegClass(virtReg);
+    int frameIndex = findOrCreateStackSlot(virtReg);
+    ++numReloaded;
+    _mri->loadRegFromStackSlot(*_currentMbb, _currentInstr,
+                               physReg, frameIndex, rc);
+    _v2pMap[virtReg] = physReg;
+    _p2vMap[physReg] = virtReg;
 }
 
 FunctionPass *createLinearScanRegisterAllocator() {
-  return new RA();
+    return new RA();
 }





More information about the llvm-commits mailing list