summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/CodeGen/ScheduleDAG.h1
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAG.cpp7
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp7
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp72
-rw-r--r--test/CodeGen/X86/loop-hoist.ll4
5 files changed, 54 insertions, 37 deletions
diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h
index ebc21a164b..48f1b78482 100644
--- a/include/llvm/CodeGen/ScheduleDAG.h
+++ b/include/llvm/CodeGen/ScheduleDAG.h
@@ -285,6 +285,7 @@ namespace llvm {
if (isa<JumpTableSDNode>(Node)) return true;
if (isa<ExternalSymbolSDNode>(Node)) return true;
if (isa<MemOperandSDNode>(Node)) return true;
+ if (Node->getOpcode() == ISD::EntryToken) return true;
return false;
}
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp
index 2af394fa8a..430ffe71c1 100644
--- a/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp
@@ -863,8 +863,11 @@ void ScheduleDAG::EmitNode(SDNode *Node, unsigned InstanceNo,
Node->dump(&DAG);
#endif
assert(0 && "This target-independent node should have been selected!");
- case ISD::EntryToken: // fall thru
- case ISD::TokenFactor:
+ break;
+ case ISD::EntryToken:
+ assert(0 && "EntryToken should have been excluded from the schedule!");
+ break;
+ case ISD::TokenFactor: // fall thru
case ISD::LABEL:
case ISD::DECLARE:
case ISD::SRCVALUE:
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp
index 3ae5e13c1c..c2fae25067 100644
--- a/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp
+++ b/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp
@@ -164,21 +164,16 @@ void ScheduleDAGList::ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle) {
/// schedulers.
void ScheduleDAGList::ListScheduleTopDown() {
unsigned CurCycle = 0;
- SUnit *Entry = SUnitMap[DAG.getEntryNode().Val].front();
// All leaves to Available queue.
for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
// It is available if it has no predecessors.
- if (SUnits[i].Preds.empty() && &SUnits[i] != Entry) {
+ if (SUnits[i].Preds.empty()) {
AvailableQueue->push(&SUnits[i]);
SUnits[i].isAvailable = SUnits[i].isPending = true;
}
}
- // Emit the entry node first.
- ScheduleNodeTopDown(Entry, CurCycle);
- HazardRec->EmitInstruction(Entry->Node);
-
// While Available queue is not empty, grab the node with the highest
// priority. If it is not ready put it back. Schedule the node.
std::vector<SUnit*> NotReady;
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
index 558f5f1bfb..ab492f40bc 100644
--- a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
+++ b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
@@ -239,7 +239,8 @@ void ScheduleDAGRRList::Schedule() {
/// possible. It will be commuted when it is translated to a MI.
void ScheduleDAGRRList::CommuteNodesToReducePressure() {
SmallPtrSet<SUnit*, 4> OperandSeen;
- for (unsigned i = Sequence.size()-1; i != 0; --i) { // Ignore first node.
+ for (unsigned i = Sequence.size(); i != 0; ) {
+ --i;
SUnit *SU = Sequence[i];
if (!SU || !SU->Node) continue;
if (SU->isCommutable) {
@@ -311,11 +312,8 @@ void ScheduleDAGRRList::ReleasePred(SUnit *PredSU, bool isChain,
#endif
if (PredSU->NumSuccsLeft == 0) {
- // EntryToken has to go last! Special case it here.
- if (!PredSU->Node || PredSU->Node->getOpcode() != ISD::EntryToken) {
- PredSU->isAvailable = true;
- AvailableQueue->push(PredSU);
- }
+ PredSU->isAvailable = true;
+ AvailableQueue->push(PredSU);
}
}
@@ -735,9 +733,10 @@ SUnit *ScheduleDAGRRList::CopyAndMoveSuccessors(SUnit *SU) {
I->isCtrl, I->isSpecial));
}
- RemovePred(SU, ChainPred, true, false);
- if (isNewLoad) {
- AddPred(LoadSU,ChainPred, true, false);
+ if (ChainPred) {
+ RemovePred(SU, ChainPred, true, false);
+ if (isNewLoad)
+ AddPred(LoadSU, ChainPred, true, false);
}
for (unsigned i = 0, e = LoadPreds.size(); i != e; ++i) {
SDep *Pred = &LoadPreds[i];
@@ -941,9 +940,12 @@ bool ScheduleDAGRRList::DelayForLiveRegsBottomUp(SUnit *SU,
void ScheduleDAGRRList::ListScheduleBottomUp() {
unsigned CurCycle = 0;
// Add root to Available queue.
- SUnit *RootSU = SUnitMap[DAG.getRoot().Val].front();
- RootSU->isAvailable = true;
- AvailableQueue->push(RootSU);
+ if (!SUnits.empty()) {
+ SUnit *RootSU = SUnitMap[DAG.getRoot().Val].front();
+ assert(RootSU->Succs.empty() && "Graph root shouldn't have successors!");
+ RootSU->isAvailable = true;
+ AvailableQueue->push(RootSU);
+ }
// While Available queue is not empty, grab the node with the highest
// priority. If it is not ready put it back. Schedule the node.
@@ -1066,12 +1068,6 @@ void ScheduleDAGRRList::ListScheduleBottomUp() {
++CurCycle;
}
- // Add entry node last
- if (DAG.getEntryNode().Val != DAG.getRoot().Val) {
- SUnit *Entry = SUnitMap[DAG.getEntryNode().Val].front();
- Sequence.push_back(Entry);
- }
-
// Reverse the order if it is bottom up.
std::reverse(Sequence.begin(), Sequence.end());
@@ -1079,16 +1075,30 @@ void ScheduleDAGRRList::ListScheduleBottomUp() {
#ifndef NDEBUG
// Verify that all SUnits were scheduled.
bool AnyNotSched = false;
+ unsigned DeadNodes = 0;
for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
- if (SUnits[i].NumSuccsLeft != 0) {
+ if (!SUnits[i].isScheduled) {
+ if (SUnits[i].NumPreds == 0 && SUnits[i].NumSuccs == 0) {
+ ++DeadNodes;
+ continue;
+ }
if (!AnyNotSched)
cerr << "*** List scheduling failed! ***\n";
SUnits[i].dump(&DAG);
cerr << "has not been scheduled!\n";
AnyNotSched = true;
}
+ if (SUnits[i].NumSuccsLeft != 0) {
+ if (!AnyNotSched)
+ cerr << "*** List scheduling failed! ***\n";
+ SUnits[i].dump(&DAG);
+ cerr << "has successors left!\n";
+ AnyNotSched = true;
+ }
}
assert(!AnyNotSched);
+ assert(Sequence.size() + DeadNodes == SUnits.size() &&
+ "The number of nodes scheduled doesn't match the expected number!");
#endif
}
@@ -1145,22 +1155,16 @@ void ScheduleDAGRRList::ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle) {
/// schedulers.
void ScheduleDAGRRList::ListScheduleTopDown() {
unsigned CurCycle = 0;
- SUnit *Entry = SUnitMap[DAG.getEntryNode().Val].front();
// All leaves to Available queue.
for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
// It is available if it has no predecessors.
- if (SUnits[i].Preds.empty() && &SUnits[i] != Entry) {
+ if (SUnits[i].Preds.empty()) {
AvailableQueue->push(&SUnits[i]);
SUnits[i].isAvailable = true;
}
}
- // Emit the entry node first.
- ScheduleNodeTopDown(Entry, CurCycle);
- Sequence.push_back(Entry);
- ++CurCycle;
-
// While Available queue is not empty, grab the node with the highest
// priority. If it is not ready put it back. Schedule the node.
std::vector<SUnit*> NotReady;
@@ -1181,23 +1185,37 @@ void ScheduleDAGRRList::ListScheduleTopDown() {
ScheduleNodeTopDown(CurSU, CurCycle);
Sequence.push_back(CurSU);
}
- CurCycle++;
+ ++CurCycle;
}
#ifndef NDEBUG
// Verify that all SUnits were scheduled.
bool AnyNotSched = false;
+ unsigned DeadNodes = 0;
for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
if (!SUnits[i].isScheduled) {
+ if (SUnits[i].NumPreds == 0 && SUnits[i].NumSuccs == 0) {
+ ++DeadNodes;
+ continue;
+ }
if (!AnyNotSched)
cerr << "*** List scheduling failed! ***\n";
SUnits[i].dump(&DAG);
cerr << "has not been scheduled!\n";
AnyNotSched = true;
}
+ if (SUnits[i].NumPredsLeft != 0) {
+ if (!AnyNotSched)
+ cerr << "*** List scheduling failed! ***\n";
+ SUnits[i].dump(&DAG);
+ cerr << "has predecessors left!\n";
+ AnyNotSched = true;
+ }
}
assert(!AnyNotSched);
+ assert(Sequence.size() + DeadNodes == SUnits.size() &&
+ "The number of nodes scheduled doesn't match the expected number!");
#endif
}
diff --git a/test/CodeGen/X86/loop-hoist.ll b/test/CodeGen/X86/loop-hoist.ll
index bbfe4f258e..95edb3d13b 100644
--- a/test/CodeGen/X86/loop-hoist.ll
+++ b/test/CodeGen/X86/loop-hoist.ll
@@ -7,13 +7,13 @@
@Arr = external global [0 x i32] ; <[0 x i32]*> [#uses=1]
-define void @foo(i32 %N.in) {
+define void @foo(i32 %N.in, i32 %x) {
entry:
%N = bitcast i32 %N.in to i32 ; <i32> [#uses=1]
br label %cond_true
cond_true: ; preds = %cond_true, %entry
- %indvar = phi i32 [ 0, %entry ], [ %indvar.next, %cond_true ] ; <i32> [#uses=2]
+ %indvar = phi i32 [ %x, %entry ], [ %indvar.next, %cond_true ] ; <i32> [#uses=2]
%i.0.0 = bitcast i32 %indvar to i32 ; <i32> [#uses=2]
%tmp = getelementptr [0 x i32]* @Arr, i32 0, i32 %i.0.0 ; <i32*> [#uses=1]
store i32 %i.0.0, i32* %tmp