aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlkis Evlogimenos <alkis@evlogimenos.com>2004-03-01 23:18:15 +0000
committerAlkis Evlogimenos <alkis@evlogimenos.com>2004-03-01 23:18:15 +0000
commitdd420e060accd1d773c731e77335cff65ca34013 (patch)
treee6867745c018e3492508920468b993ec30c5ac99
parent5f37502bfbadfa65de087627bd67fd58bb03725c (diff)
downloadexternal_llvm-dd420e060accd1d773c731e77335cff65ca34013.zip
external_llvm-dd420e060accd1d773c731e77335cff65ca34013.tar.gz
external_llvm-dd420e060accd1d773c731e77335cff65ca34013.tar.bz2
Add a spiller option to llc. A simple spiller will come soon. When we get CFG in the machine code represenation a global spiller will also be possible. Also document the linear scan register allocator but mark it as experimental for now.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@12062 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--docs/CommandGuide/llc.html13
-rw-r--r--lib/CodeGen/Passes.cpp2
-rw-r--r--lib/CodeGen/RegAllocLinearScan.cpp4
-rw-r--r--lib/CodeGen/VirtRegMap.cpp105
-rw-r--r--lib/CodeGen/VirtRegMap.h9
5 files changed, 87 insertions, 46 deletions
diff --git a/docs/CommandGuide/llc.html b/docs/CommandGuide/llc.html
index 3671042..4583b11 100644
--- a/docs/CommandGuide/llc.html
+++ b/docs/CommandGuide/llc.html
@@ -150,6 +150,19 @@ OPTIONS
<di> local
<dd>Local register allocator</dd>
+
+ <di> linearscan
+ <dd>Linear scan global register allocator (experimental)</dd>
+
+ <li>-spiller=&lt;sp&gt;
+ <br>
+ Specify the spiller to use for register allocators that support it.
+ Currently this option is used by the linear scan register
+ allocator. The default is <i>local</i>.
+ Valid spillers are:
+ <dl compact>
+ <di> local
+ <dd>Local spiller</dd>
</dl>
<p>
diff --git a/lib/CodeGen/Passes.cpp b/lib/CodeGen/Passes.cpp
index bdcac4c..2fb6cb4 100644
--- a/lib/CodeGen/Passes.cpp
+++ b/lib/CodeGen/Passes.cpp
@@ -26,7 +26,7 @@ namespace {
cl::Prefix,
cl::values(clEnumVal(simple, " simple register allocator"),
clEnumVal(local, " local register allocator"),
- clEnumVal(linearscan, " linear-scan global register allocator"),
+ clEnumVal(linearscan, " linear scan register allocator (experimental)"),
0),
cl::init(local));
}
diff --git a/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp
index d6c53cd..e92abe1 100644
--- a/lib/CodeGen/RegAllocLinearScan.cpp
+++ b/lib/CodeGen/RegAllocLinearScan.cpp
@@ -41,6 +41,7 @@ namespace {
std::auto_ptr<PhysRegTracker> prt_;
std::auto_ptr<VirtRegMap> vrm_;
+ std::auto_ptr<Spiller> spiller_;
typedef std::vector<float> SpillWeights;
SpillWeights spillWeights_;
@@ -147,12 +148,13 @@ bool RA::runOnMachineFunction(MachineFunction &fn) {
li_ = &getAnalysis<LiveIntervals>();
if (!prt_.get()) prt_.reset(new PhysRegTracker(*mri_));
vrm_.reset(new VirtRegMap(*mf_));
+ if (!spiller_.get()) spiller_.reset(createSpiller());
initIntervalSets(li_->getIntervals());
linearScan();
- eliminateVirtRegs(*mf_, *vrm_);
+ spiller_->runOnMachineFunction(*mf_, *vrm_);
return true;
}
diff --git a/lib/CodeGen/VirtRegMap.cpp b/lib/CodeGen/VirtRegMap.cpp
index 1238a2c..1187fc2 100644
--- a/lib/CodeGen/VirtRegMap.cpp
+++ b/lib/CodeGen/VirtRegMap.cpp
@@ -22,9 +22,10 @@
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetInstrInfo.h"
-#include "Support/Statistic.h"
+#include "Support/CommandLine.h"
#include "Support/Debug.h"
#include "Support/DenseMap.h"
+#include "Support/Statistic.h"
#include "Support/STLExtras.h"
#include <iostream>
@@ -35,6 +36,15 @@ namespace {
Statistic<> numStores("spiller", "Number of stores added");
Statistic<> numLoads ("spiller", "Number of loads added");
+ enum SpillerName { local };
+
+ cl::opt<SpillerName>
+ SpillerOpt("spiller",
+ cl::desc("Spiller to use: (default: local)"),
+ cl::Prefix,
+ cl::values(clEnumVal(local, " local spiller"),
+ 0),
+ cl::init(local));
}
int VirtRegMap::assignVirt2StackSlot(unsigned virtReg)
@@ -88,41 +98,44 @@ std::ostream& llvm::operator<<(std::ostream& os, const VirtRegMap& vrm)
return std::cerr << '\n';
}
+Spiller::~Spiller()
+{
+
+}
+
namespace {
- class Spiller {
+ class LocalSpiller : public Spiller {
typedef std::vector<unsigned> Phys2VirtMap;
typedef std::vector<bool> PhysFlag;
typedef DenseMap<MachineInstr*, VirtReg2IndexFunctor> Virt2MI;
- MachineFunction& mf_;
- const TargetMachine& tm_;
- const TargetInstrInfo& tii_;
- const MRegisterInfo& mri_;
- const VirtRegMap& vrm_;
+ MachineFunction* mf_;
+ const TargetMachine* tm_;
+ const TargetInstrInfo* tii_;
+ const MRegisterInfo* mri_;
+ const VirtRegMap* vrm_;
Phys2VirtMap p2vMap_;
PhysFlag dirty_;
Virt2MI lastDef_;
public:
- Spiller(MachineFunction& mf, const VirtRegMap& vrm)
- : mf_(mf),
- tm_(mf_.getTarget()),
- tii_(tm_.getInstrInfo()),
- mri_(*tm_.getRegisterInfo()),
- vrm_(vrm),
- p2vMap_(mri_.getNumRegs(), 0),
- dirty_(mri_.getNumRegs(), false),
- lastDef_() {
+ bool runOnMachineFunction(MachineFunction& mf, const VirtRegMap& vrm) {
+ mf_ = &mf;
+ tm_ = &mf_->getTarget();
+ tii_ = &tm_->getInstrInfo();
+ mri_ = tm_->getRegisterInfo();
+ vrm_ = &vrm;
+ p2vMap_.assign(mri_->getNumRegs(), 0);
+ dirty_.assign(mri_->getNumRegs(), false);
+
DEBUG(std::cerr << "********** REWRITE MACHINE CODE **********\n");
DEBUG(std::cerr << "********** Function: "
- << mf_.getFunction()->getName() << '\n');
- }
+ << mf_->getFunction()->getName() << '\n');
- void eliminateVirtRegs() {
- for (MachineFunction::iterator mbbi = mf_.begin(),
- mbbe = mf_.end(); mbbi != mbbe; ++mbbi) {
- lastDef_.grow(mf_.getSSARegMap()->getLastVirtReg());
+ for (MachineFunction::iterator mbbi = mf_->begin(),
+ mbbe = mf_->end(); mbbi != mbbe; ++mbbi) {
+ lastDef_.grow(mf_->getSSARegMap()->getLastVirtReg());
DEBUG(std::cerr << mbbi->getBasicBlock()->getName() << ":\n");
eliminateVirtRegsInMbb(*mbbi);
// clear map, dirty flag and last ref
@@ -130,6 +143,7 @@ namespace {
dirty_.assign(dirty_.size(), false);
lastDef_.clear();
}
+ return true;
}
private:
@@ -137,21 +151,21 @@ namespace {
MachineBasicBlock::iterator mii,
unsigned physReg) {
unsigned virtReg = p2vMap_[physReg];
- if (dirty_[physReg] && vrm_.hasStackSlot(virtReg)) {
+ if (dirty_[physReg] && vrm_->hasStackSlot(virtReg)) {
assert(lastDef_[virtReg] && "virtual register is mapped "
"to a register and but was not defined!");
MachineBasicBlock::iterator lastDef = lastDef_[virtReg];
MachineBasicBlock::iterator nextLastRef = next(lastDef);
- mri_.storeRegToStackSlot(*lastDef->getParent(),
+ mri_->storeRegToStackSlot(*lastDef->getParent(),
nextLastRef,
physReg,
- vrm_.getStackSlot(virtReg),
- mri_.getRegClass(physReg));
+ vrm_->getStackSlot(virtReg),
+ mri_->getRegClass(physReg));
++numStores;
DEBUG(std::cerr << "added: ";
- prior(nextLastRef)->print(std::cerr, tm_);
+ prior(nextLastRef)->print(std::cerr, *tm_);
std::cerr << "after: ";
- lastDef->print(std::cerr, tm_));
+ lastDef->print(std::cerr, *tm_));
lastDef_[virtReg] = 0;
}
p2vMap_[physReg] = 0;
@@ -162,7 +176,7 @@ namespace {
MachineBasicBlock::iterator mii,
unsigned physReg) {
vacateJustPhysReg(mbb, mii, physReg);
- for (const unsigned* as = mri_.getAliasSet(physReg); *as; ++as)
+ for (const unsigned* as = mri_->getAliasSet(physReg); *as; ++as)
vacateJustPhysReg(mbb, mii, *as);
}
@@ -175,13 +189,13 @@ namespace {
vacatePhysReg(mbb, mii, physReg);
p2vMap_[physReg] = virtReg;
// load if necessary
- if (vrm_.hasStackSlot(virtReg)) {
- mri_.loadRegFromStackSlot(mbb, mii, physReg,
- vrm_.getStackSlot(virtReg),
- mri_.getRegClass(physReg));
+ if (vrm_->hasStackSlot(virtReg)) {
+ mri_->loadRegFromStackSlot(mbb, mii, physReg,
+ vrm_->getStackSlot(virtReg),
+ mri_->getRegClass(physReg));
++numLoads;
DEBUG(std::cerr << "added: ";
- prior(mii)->print(std::cerr,tm_));
+ prior(mii)->print(std::cerr, *tm_));
lastDef_[virtReg] = mii;
}
}
@@ -208,8 +222,8 @@ namespace {
// we clear all physical registers that may contain
// the value of the spilled virtual register
VirtRegMap::MI2VirtMap::const_iterator i, e;
- for (tie(i, e) = vrm_.getFoldedVirts(mii); i != e; ++i) {
- unsigned physReg = vrm_.getPhys(i->second);
+ for (tie(i, e) = vrm_->getFoldedVirts(mii); i != e; ++i) {
+ unsigned physReg = vrm_->getPhys(i->second);
if (physReg) vacateJustPhysReg(mbb, mii, physReg);
}
@@ -219,7 +233,7 @@ namespace {
if (op.isRegister() && op.getReg() && op.isUse() &&
MRegisterInfo::isVirtualRegister(op.getReg())) {
unsigned virtReg = op.getReg();
- unsigned physReg = vrm_.getPhys(virtReg);
+ unsigned physReg = vrm_->getPhys(virtReg);
handleUse(mbb, mii, virtReg, physReg);
mii->SetMachineOperandReg(i, physReg);
// mark as dirty if this is def&use
@@ -231,7 +245,7 @@ namespace {
}
// spill implicit defs
- const TargetInstrDescriptor& tid =tii_.get(mii->getOpcode());
+ const TargetInstrDescriptor& tid = tii_->get(mii->getOpcode());
for (const unsigned* id = tid.ImplicitDefs; *id; ++id)
vacatePhysReg(mbb, mii, *id);
@@ -243,13 +257,13 @@ namespace {
if (MRegisterInfo::isPhysicalRegister(op.getReg()))
vacatePhysReg(mbb, mii, op.getReg());
else {
- unsigned physReg = vrm_.getPhys(op.getReg());
+ unsigned physReg = vrm_->getPhys(op.getReg());
handleDef(mbb, mii, op.getReg(), physReg);
mii->SetMachineOperandReg(i, physReg);
}
}
- DEBUG(std::cerr << '\t'; mii->print(std::cerr, tm_));
+ DEBUG(std::cerr << '\t'; mii->print(std::cerr, *tm_));
}
for (unsigned i = 1, e = p2vMap_.size(); i != e; ++i)
@@ -259,8 +273,13 @@ namespace {
};
}
-
-void llvm::eliminateVirtRegs(MachineFunction& mf, const VirtRegMap& vrm)
+llvm::Spiller* llvm::createSpiller()
{
- Spiller(mf, vrm).eliminateVirtRegs();
+ switch (SpillerOpt) {
+ default:
+ std::cerr << "no spiller selected";
+ abort();
+ case local:
+ return new LocalSpiller();
+ }
}
diff --git a/lib/CodeGen/VirtRegMap.h b/lib/CodeGen/VirtRegMap.h
index 90cc44d..3c2f8ee 100644
--- a/lib/CodeGen/VirtRegMap.h
+++ b/lib/CodeGen/VirtRegMap.h
@@ -108,7 +108,14 @@ namespace llvm {
std::ostream& operator<<(std::ostream& os, const VirtRegMap& li);
- void eliminateVirtRegs(MachineFunction& mf, const VirtRegMap& vrm);
+ struct Spiller {
+ virtual ~Spiller();
+
+ virtual bool runOnMachineFunction(MachineFunction& mf, const VirtRegMap& vrm) = 0;
+
+ };
+
+ Spiller* createSpiller();
} // End llvm namespace