summaryrefslogtreecommitdiff
path: root/lib/CodeGen/ScheduleDAGInstrs.cpp
diff options
context:
space:
mode:
authorMichael Ilseman <milseman@apple.com>2013-01-21 18:18:53 +0000
committerMichael Ilseman <milseman@apple.com>2013-01-21 18:18:53 +0000
commitafe77f33b2a361ed0d001596dcdde0e16d57abee (patch)
treeb25cc464c5327a8b8b188c8c67a4c7ef507431c7 /lib/CodeGen/ScheduleDAGInstrs.cpp
parent47543a8a66fb9451126f134808b55853aca57e1c (diff)
downloadllvm-afe77f33b2a361ed0d001596dcdde0e16d57abee.tar.gz
llvm-afe77f33b2a361ed0d001596dcdde0e16d57abee.tar.bz2
llvm-afe77f33b2a361ed0d001596dcdde0e16d57abee.tar.xz
Introduce a new data structure, the SparseMultiSet, and changes to the MI scheduler to use it.
A SparseMultiSet adds multiset behavior to SparseSet, while retaining SparseSet's desirable properties. Essentially, SparseMultiSet provides multiset behavior by storing its dense data in doubly linked lists that are inlined into the dense vector. This allows it to provide good data locality as well as vector-like constant-time clear() and fast constant time find(), insert(), and erase(). It also allows SparseMultiSet to have a builtin recycler rather than keeping SparseSet's behavior of always swapping upon removal, which allows it to preserve more iterators. It's often a better alternative to a SparseSet of a growable container or vector-of-vector. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@173064 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/ScheduleDAGInstrs.cpp')
-rw-r--r--lib/CodeGen/ScheduleDAGInstrs.cpp78
1 files changed, 33 insertions, 45 deletions
diff --git a/lib/CodeGen/ScheduleDAGInstrs.cpp b/lib/CodeGen/ScheduleDAGInstrs.cpp
index 662fc0e6d1..411c46b8f5 100644
--- a/lib/CodeGen/ScheduleDAGInstrs.cpp
+++ b/lib/CodeGen/ScheduleDAGInstrs.cpp
@@ -168,20 +168,6 @@ void ScheduleDAGInstrs::finishBlock() {
BB = 0;
}
-/// Initialize the map with the number of registers.
-void Reg2SUnitsMap::setRegLimit(unsigned Limit) {
- PhysRegSet.setUniverse(Limit);
- SUnits.resize(Limit);
-}
-
-/// Clear the map without deallocating storage.
-void Reg2SUnitsMap::clear() {
- for (const_iterator I = reg_begin(), E = reg_end(); I != E; ++I) {
- SUnits[*I].clear();
- }
- PhysRegSet.clear();
-}
-
/// Initialize the DAG and common scheduler state for the current scheduling
/// region. This does not actually create the DAG, only clears it. The
/// scheduling driver may call BuildSchedGraph multiple times per scheduling
@@ -228,7 +214,7 @@ void ScheduleDAGInstrs::addSchedBarrierDeps() {
if (Reg == 0) continue;
if (TRI->isPhysicalRegister(Reg))
- Uses[Reg].push_back(PhysRegSUOper(&ExitSU, -1));
+ Uses.insert(PhysRegSUOper(&ExitSU, -1, Reg));
else {
assert(!IsPostRA && "Virtual register encountered after regalloc.");
if (MO.readsReg()) // ignore undef operands
@@ -245,7 +231,7 @@ void ScheduleDAGInstrs::addSchedBarrierDeps() {
E = (*SI)->livein_end(); I != E; ++I) {
unsigned Reg = *I;
if (!Uses.contains(Reg))
- Uses[Reg].push_back(PhysRegSUOper(&ExitSU, -1));
+ Uses.insert(PhysRegSUOper(&ExitSU, -1, Reg));
}
}
}
@@ -263,15 +249,14 @@ void ScheduleDAGInstrs::addPhysRegDataDeps(SUnit *SU, unsigned OperIdx) {
Alias.isValid(); ++Alias) {
if (!Uses.contains(*Alias))
continue;
- std::vector<PhysRegSUOper> &UseList = Uses[*Alias];
- for (unsigned i = 0, e = UseList.size(); i != e; ++i) {
- SUnit *UseSU = UseList[i].SU;
+ for (Reg2SUnitsMap::iterator I = Uses.find(*Alias); I != Uses.end(); ++I) {
+ SUnit *UseSU = I->SU;
if (UseSU == SU)
continue;
// Adjust the dependence latency using operand def/use information,
// then allow the target to perform its own adjustments.
- int UseOp = UseList[i].OpIdx;
+ int UseOp = I->OpIdx;
MachineInstr *RegUse = 0;
SDep Dep;
if (UseOp < 0)
@@ -311,9 +296,8 @@ void ScheduleDAGInstrs::addPhysRegDeps(SUnit *SU, unsigned OperIdx) {
Alias.isValid(); ++Alias) {
if (!Defs.contains(*Alias))
continue;
- std::vector<PhysRegSUOper> &DefList = Defs[*Alias];
- for (unsigned i = 0, e = DefList.size(); i != e; ++i) {
- SUnit *DefSU = DefList[i].SU;
+ for (Reg2SUnitsMap::iterator I = Defs.find(*Alias); I != Defs.end(); ++I) {
+ SUnit *DefSU = I->SU;
if (DefSU == &ExitSU)
continue;
if (DefSU != SU &&
@@ -337,33 +321,37 @@ void ScheduleDAGInstrs::addPhysRegDeps(SUnit *SU, unsigned OperIdx) {
// Either insert a new Reg2SUnits entry with an empty SUnits list, or
// retrieve the existing SUnits list for this register's uses.
// Push this SUnit on the use list.
- Uses[MO.getReg()].push_back(PhysRegSUOper(SU, OperIdx));
+ Uses.insert(PhysRegSUOper(SU, OperIdx, MO.getReg()));
}
else {
addPhysRegDataDeps(SU, OperIdx);
-
- // Either insert a new Reg2SUnits entry with an empty SUnits list, or
- // retrieve the existing SUnits list for this register's defs.
- std::vector<PhysRegSUOper> &DefList = Defs[MO.getReg()];
+ unsigned Reg = MO.getReg();
// clear this register's use list
- if (Uses.contains(MO.getReg()))
- Uses[MO.getReg()].clear();
-
- if (!MO.isDead())
- DefList.clear();
-
- // Calls will not be reordered because of chain dependencies (see
- // below). Since call operands are dead, calls may continue to be added
- // to the DefList making dependence checking quadratic in the size of
- // the block. Instead, we leave only one call at the back of the
- // DefList.
- if (SU->isCall) {
- while (!DefList.empty() && DefList.back().SU->isCall)
- DefList.pop_back();
+ if (Uses.contains(Reg))
+ Uses.eraseAll(Reg);
+
+ if (!MO.isDead()) {
+ Defs.eraseAll(Reg);
+ } else if (SU->isCall) {
+ // Calls will not be reordered because of chain dependencies (see
+ // below). Since call operands are dead, calls may continue to be added
+ // to the DefList making dependence checking quadratic in the size of
+ // the block. Instead, we leave only one call at the back of the
+ // DefList.
+ Reg2SUnitsMap::RangePair P = Defs.equal_range(Reg);
+ Reg2SUnitsMap::iterator B = P.first;
+ Reg2SUnitsMap::iterator I = P.second;
+ for (bool isBegin = I == B; !isBegin; /* empty */) {
+ isBegin = (--I) == B;
+ if (!I->SU->isCall)
+ break;
+ I = Defs.erase(I);
+ }
}
+
// Defs are pushed in the order they are visited and never reordered.
- DefList.push_back(PhysRegSUOper(SU, OperIdx));
+ Defs.insert(PhysRegSUOper(SU, OperIdx, Reg));
}
}
@@ -726,8 +714,8 @@ void ScheduleDAGInstrs::buildSchedGraph(AliasAnalysis *AA,
assert(Defs.empty() && Uses.empty() &&
"Only BuildGraph should update Defs/Uses");
- Defs.setRegLimit(TRI->getNumRegs());
- Uses.setRegLimit(TRI->getNumRegs());
+ Defs.setUniverse(TRI->getNumRegs());
+ Uses.setUniverse(TRI->getNumRegs());
assert(VRegDefs.empty() && "Only BuildSchedGraph may access VRegDefs");
// FIXME: Allow SparseSet to reserve space for the creation of virtual