mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-07 12:28:24 +00:00
Treat EntryToken nodes as "passive" so that they aren't added to the
ScheduleDAG; they don't correspond to any actual instructions so they don't need to be scheduled. This fixes a bug where the EntryToken was being scheduled multiple times in some cases, though it ended up not causing any trouble because EntryToken doesn't expand into anything. With this fixed the schedulers reliably schedule the expected number of units, so we can check this with an assertion. This requires a tweak to test/CodeGen/X86/loop-hoist.ll because it ends up getting scheduled differently in a trivial way, though it was enough to fool the prcontext+grep that the test does. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@49701 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -285,6 +285,7 @@ namespace llvm {
|
|||||||
if (isa<JumpTableSDNode>(Node)) return true;
|
if (isa<JumpTableSDNode>(Node)) return true;
|
||||||
if (isa<ExternalSymbolSDNode>(Node)) return true;
|
if (isa<ExternalSymbolSDNode>(Node)) return true;
|
||||||
if (isa<MemOperandSDNode>(Node)) return true;
|
if (isa<MemOperandSDNode>(Node)) return true;
|
||||||
|
if (Node->getOpcode() == ISD::EntryToken) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -863,8 +863,11 @@ void ScheduleDAG::EmitNode(SDNode *Node, unsigned InstanceNo,
|
|||||||
Node->dump(&DAG);
|
Node->dump(&DAG);
|
||||||
#endif
|
#endif
|
||||||
assert(0 && "This target-independent node should have been selected!");
|
assert(0 && "This target-independent node should have been selected!");
|
||||||
case ISD::EntryToken: // fall thru
|
break;
|
||||||
case ISD::TokenFactor:
|
case ISD::EntryToken:
|
||||||
|
assert(0 && "EntryToken should have been excluded from the schedule!");
|
||||||
|
break;
|
||||||
|
case ISD::TokenFactor: // fall thru
|
||||||
case ISD::LABEL:
|
case ISD::LABEL:
|
||||||
case ISD::DECLARE:
|
case ISD::DECLARE:
|
||||||
case ISD::SRCVALUE:
|
case ISD::SRCVALUE:
|
||||||
|
@@ -164,21 +164,16 @@ void ScheduleDAGList::ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle) {
|
|||||||
/// schedulers.
|
/// schedulers.
|
||||||
void ScheduleDAGList::ListScheduleTopDown() {
|
void ScheduleDAGList::ListScheduleTopDown() {
|
||||||
unsigned CurCycle = 0;
|
unsigned CurCycle = 0;
|
||||||
SUnit *Entry = SUnitMap[DAG.getEntryNode().Val].front();
|
|
||||||
|
|
||||||
// All leaves to Available queue.
|
// All leaves to Available queue.
|
||||||
for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
|
for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
|
||||||
// It is available if it has no predecessors.
|
// 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]);
|
AvailableQueue->push(&SUnits[i]);
|
||||||
SUnits[i].isAvailable = SUnits[i].isPending = true;
|
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
|
// While Available queue is not empty, grab the node with the highest
|
||||||
// priority. If it is not ready put it back. Schedule the node.
|
// priority. If it is not ready put it back. Schedule the node.
|
||||||
std::vector<SUnit*> NotReady;
|
std::vector<SUnit*> NotReady;
|
||||||
|
@@ -239,7 +239,8 @@ void ScheduleDAGRRList::Schedule() {
|
|||||||
/// possible. It will be commuted when it is translated to a MI.
|
/// possible. It will be commuted when it is translated to a MI.
|
||||||
void ScheduleDAGRRList::CommuteNodesToReducePressure() {
|
void ScheduleDAGRRList::CommuteNodesToReducePressure() {
|
||||||
SmallPtrSet<SUnit*, 4> OperandSeen;
|
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];
|
SUnit *SU = Sequence[i];
|
||||||
if (!SU || !SU->Node) continue;
|
if (!SU || !SU->Node) continue;
|
||||||
if (SU->isCommutable) {
|
if (SU->isCommutable) {
|
||||||
@@ -311,11 +312,8 @@ void ScheduleDAGRRList::ReleasePred(SUnit *PredSU, bool isChain,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (PredSU->NumSuccsLeft == 0) {
|
if (PredSU->NumSuccsLeft == 0) {
|
||||||
// EntryToken has to go last! Special case it here.
|
PredSU->isAvailable = true;
|
||||||
if (!PredSU->Node || PredSU->Node->getOpcode() != ISD::EntryToken) {
|
AvailableQueue->push(PredSU);
|
||||||
PredSU->isAvailable = true;
|
|
||||||
AvailableQueue->push(PredSU);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -735,9 +733,10 @@ SUnit *ScheduleDAGRRList::CopyAndMoveSuccessors(SUnit *SU) {
|
|||||||
I->isCtrl, I->isSpecial));
|
I->isCtrl, I->isSpecial));
|
||||||
}
|
}
|
||||||
|
|
||||||
RemovePred(SU, ChainPred, true, false);
|
if (ChainPred) {
|
||||||
if (isNewLoad) {
|
RemovePred(SU, ChainPred, true, false);
|
||||||
AddPred(LoadSU,ChainPred, true, false);
|
if (isNewLoad)
|
||||||
|
AddPred(LoadSU, ChainPred, true, false);
|
||||||
}
|
}
|
||||||
for (unsigned i = 0, e = LoadPreds.size(); i != e; ++i) {
|
for (unsigned i = 0, e = LoadPreds.size(); i != e; ++i) {
|
||||||
SDep *Pred = &LoadPreds[i];
|
SDep *Pred = &LoadPreds[i];
|
||||||
@@ -941,9 +940,12 @@ bool ScheduleDAGRRList::DelayForLiveRegsBottomUp(SUnit *SU,
|
|||||||
void ScheduleDAGRRList::ListScheduleBottomUp() {
|
void ScheduleDAGRRList::ListScheduleBottomUp() {
|
||||||
unsigned CurCycle = 0;
|
unsigned CurCycle = 0;
|
||||||
// Add root to Available queue.
|
// Add root to Available queue.
|
||||||
SUnit *RootSU = SUnitMap[DAG.getRoot().Val].front();
|
if (!SUnits.empty()) {
|
||||||
RootSU->isAvailable = true;
|
SUnit *RootSU = SUnitMap[DAG.getRoot().Val].front();
|
||||||
AvailableQueue->push(RootSU);
|
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
|
// While Available queue is not empty, grab the node with the highest
|
||||||
// priority. If it is not ready put it back. Schedule the node.
|
// priority. If it is not ready put it back. Schedule the node.
|
||||||
@@ -1066,12 +1068,6 @@ void ScheduleDAGRRList::ListScheduleBottomUp() {
|
|||||||
++CurCycle;
|
++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.
|
// Reverse the order if it is bottom up.
|
||||||
std::reverse(Sequence.begin(), Sequence.end());
|
std::reverse(Sequence.begin(), Sequence.end());
|
||||||
|
|
||||||
@@ -1079,16 +1075,30 @@ void ScheduleDAGRRList::ListScheduleBottomUp() {
|
|||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// Verify that all SUnits were scheduled.
|
// Verify that all SUnits were scheduled.
|
||||||
bool AnyNotSched = false;
|
bool AnyNotSched = false;
|
||||||
|
unsigned DeadNodes = 0;
|
||||||
for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
|
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)
|
if (!AnyNotSched)
|
||||||
cerr << "*** List scheduling failed! ***\n";
|
cerr << "*** List scheduling failed! ***\n";
|
||||||
SUnits[i].dump(&DAG);
|
SUnits[i].dump(&DAG);
|
||||||
cerr << "has not been scheduled!\n";
|
cerr << "has not been scheduled!\n";
|
||||||
AnyNotSched = true;
|
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(!AnyNotSched);
|
||||||
|
assert(Sequence.size() + DeadNodes == SUnits.size() &&
|
||||||
|
"The number of nodes scheduled doesn't match the expected number!");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1145,22 +1155,16 @@ void ScheduleDAGRRList::ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle) {
|
|||||||
/// schedulers.
|
/// schedulers.
|
||||||
void ScheduleDAGRRList::ListScheduleTopDown() {
|
void ScheduleDAGRRList::ListScheduleTopDown() {
|
||||||
unsigned CurCycle = 0;
|
unsigned CurCycle = 0;
|
||||||
SUnit *Entry = SUnitMap[DAG.getEntryNode().Val].front();
|
|
||||||
|
|
||||||
// All leaves to Available queue.
|
// All leaves to Available queue.
|
||||||
for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
|
for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
|
||||||
// It is available if it has no predecessors.
|
// 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]);
|
AvailableQueue->push(&SUnits[i]);
|
||||||
SUnits[i].isAvailable = true;
|
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
|
// While Available queue is not empty, grab the node with the highest
|
||||||
// priority. If it is not ready put it back. Schedule the node.
|
// priority. If it is not ready put it back. Schedule the node.
|
||||||
std::vector<SUnit*> NotReady;
|
std::vector<SUnit*> NotReady;
|
||||||
@@ -1181,23 +1185,37 @@ void ScheduleDAGRRList::ListScheduleTopDown() {
|
|||||||
ScheduleNodeTopDown(CurSU, CurCycle);
|
ScheduleNodeTopDown(CurSU, CurCycle);
|
||||||
Sequence.push_back(CurSU);
|
Sequence.push_back(CurSU);
|
||||||
}
|
}
|
||||||
CurCycle++;
|
++CurCycle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// Verify that all SUnits were scheduled.
|
// Verify that all SUnits were scheduled.
|
||||||
bool AnyNotSched = false;
|
bool AnyNotSched = false;
|
||||||
|
unsigned DeadNodes = 0;
|
||||||
for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
|
for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
|
||||||
if (!SUnits[i].isScheduled) {
|
if (!SUnits[i].isScheduled) {
|
||||||
|
if (SUnits[i].NumPreds == 0 && SUnits[i].NumSuccs == 0) {
|
||||||
|
++DeadNodes;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!AnyNotSched)
|
if (!AnyNotSched)
|
||||||
cerr << "*** List scheduling failed! ***\n";
|
cerr << "*** List scheduling failed! ***\n";
|
||||||
SUnits[i].dump(&DAG);
|
SUnits[i].dump(&DAG);
|
||||||
cerr << "has not been scheduled!\n";
|
cerr << "has not been scheduled!\n";
|
||||||
AnyNotSched = true;
|
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(!AnyNotSched);
|
||||||
|
assert(Sequence.size() + DeadNodes == SUnits.size() &&
|
||||||
|
"The number of nodes scheduled doesn't match the expected number!");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7,13 +7,13 @@
|
|||||||
|
|
||||||
@Arr = external global [0 x i32] ; <[0 x i32]*> [#uses=1]
|
@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:
|
entry:
|
||||||
%N = bitcast i32 %N.in to i32 ; <i32> [#uses=1]
|
%N = bitcast i32 %N.in to i32 ; <i32> [#uses=1]
|
||||||
br label %cond_true
|
br label %cond_true
|
||||||
|
|
||||||
cond_true: ; preds = %cond_true, %entry
|
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]
|
%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]
|
%tmp = getelementptr [0 x i32]* @Arr, i32 0, i32 %i.0.0 ; <i32*> [#uses=1]
|
||||||
store i32 %i.0.0, i32* %tmp
|
store i32 %i.0.0, i32* %tmp
|
||||||
|
Reference in New Issue
Block a user