[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