[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp
Evan Cheng
evan.cheng at apple.com
Thu Mar 2 13:38:41 PST 2006
Changes in directory llvm/lib/CodeGen/SelectionDAG:
ScheduleDAGList.cpp updated: 1.6 -> 1.7
---
Log message:
- Fixed some priority calculation bugs that were causing bug 478: http://llvm.cs.uiuc.edu/PR478 . Among them:
a predecessor appearing more than once in the operand list was counted as
multiple predecessor; priority1 should be updated during scheduling;
CycleBound was updated after the node is inserted into priority queue; one
of the tie breaking condition was flipped.
- Take into consideration of two address opcodes. If a predecessor is a def&use
operand, it should have a higher priority.
- Scheduler should also favor floaters, i.e. nodes that do not have real
predecessors such as MOV32ri.
- The scheduling fixes / tweaks fixed bug 478: http://llvm.cs.uiuc.edu/PR478 :
.text
.align 4
.globl _f
_f:
movl 4(%esp), %eax
movl 8(%esp), %ecx
movl %eax, %edx
imull %ecx, %edx
imull %eax, %eax
imull %ecx, %ecx
addl %eax, %ecx
leal (%ecx,%edx,2), %eax
ret
It is also a slight performance win (1% - 3%) for most tests.
---
Diffs of the changes: (+98 -64)
ScheduleDAGList.cpp | 162 +++++++++++++++++++++++++++++++---------------------
1 files changed, 98 insertions(+), 64 deletions(-)
Index: llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp:1.6 llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp:1.7
--- llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp:1.6 Wed Feb 1 18:38:08 2006
+++ llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp Thu Mar 2 15:38:29 2006
@@ -21,8 +21,9 @@
#include "llvm/Support/Debug.h"
#include <climits>
#include <iostream>
-#include <memory>
#include <queue>
+#include <set>
+#include <vector>
using namespace llvm;
namespace {
@@ -32,14 +33,17 @@
struct SUnit {
SDNode *Node; // Representative node.
std::vector<SDNode*> FlaggedNodes; // All nodes flagged to Node.
- std::vector<SUnit*> Preds; // All real predecessors.
- std::vector<SUnit*> ChainPreds; // All chain predecessors.
- std::vector<SUnit*> Succs; // All real successors.
- std::vector<SUnit*> ChainSuccs; // All chain successors.
+ std::set<SUnit*> Preds; // All real predecessors.
+ std::set<SUnit*> ChainPreds; // All chain predecessors.
+ std::set<SUnit*> Succs; // All real successors.
+ std::set<SUnit*> ChainSuccs; // All chain successors.
int NumPredsLeft; // # of preds not scheduled.
int NumSuccsLeft; // # of succs not scheduled.
+ int NumChainPredsLeft; // # of chain preds not scheduled.
+ int NumChainSuccsLeft; // # of chain succs not scheduled.
int Priority1; // Scheduling priority 1.
int Priority2; // Scheduling priority 2.
+ bool isDefNUseOperand; // Is a def&use operand.
unsigned Latency; // Node latency.
unsigned CycleBound; // Upper/lower cycle to be scheduled at.
unsigned Slot; // Cycle node is scheduled at.
@@ -47,8 +51,9 @@
SUnit(SDNode *node)
: Node(node), NumPredsLeft(0), NumSuccsLeft(0),
- Priority1(INT_MIN), Priority2(INT_MIN), Latency(0),
- CycleBound(0), Slot(0), Next(NULL) {}
+ NumChainPredsLeft(0), NumChainSuccsLeft(0),
+ Priority1(INT_MIN), Priority2(INT_MIN), isDefNUseOperand(false),
+ Latency(0), CycleBound(0), Slot(0), Next(NULL) {}
void dump(const SelectionDAG *G, bool All=true) const;
};
@@ -66,37 +71,43 @@
}
if (All) {
- std::cerr << "# preds left : " << NumPredsLeft << "\n";
- std::cerr << "# succs left : " << NumSuccsLeft << "\n";
- std::cerr << "Latency : " << Latency << "\n";
- std::cerr << "Priority : " << Priority1 << " , " << Priority2 << "\n";
+ std::cerr << "# preds left : " << NumPredsLeft << "\n";
+ std::cerr << "# succs left : " << NumSuccsLeft << "\n";
+ std::cerr << "# chain preds left : " << NumChainPredsLeft << "\n";
+ std::cerr << "# chain succs left : " << NumChainSuccsLeft << "\n";
+ std::cerr << "Latency : " << Latency << "\n";
+ std::cerr << "Priority : " << Priority1 << " , " << Priority2 << "\n";
if (Preds.size() != 0) {
std::cerr << "Predecessors :\n";
- for (unsigned i = 0, e = Preds.size(); i != e; i++) {
+ for (std::set<SUnit*>::iterator I = Preds.begin(),
+ E = Preds.end(); I != E; ++I) {
std::cerr << " ";
- Preds[i]->dump(G, false);
+ (*I)->dump(G, false);
}
}
if (ChainPreds.size() != 0) {
std::cerr << "Chained Preds :\n";
- for (unsigned i = 0, e = ChainPreds.size(); i != e; i++) {
+ for (std::set<SUnit*>::iterator I = ChainPreds.begin(),
+ E = ChainPreds.end(); I != E; ++I) {
std::cerr << " ";
- ChainPreds[i]->dump(G, false);
+ (*I)->dump(G, false);
}
}
if (Succs.size() != 0) {
std::cerr << "Successors :\n";
- for (unsigned i = 0, e = Succs.size(); i != e; i++) {
+ for (std::set<SUnit*>::iterator I = Succs.begin(),
+ E = Succs.end(); I != E; ++I) {
std::cerr << " ";
- Succs[i]->dump(G, false);
+ (*I)->dump(G, false);
}
}
if (ChainSuccs.size() != 0) {
std::cerr << "Chained succs :\n";
- for (unsigned i = 0, e = ChainSuccs.size(); i != e; i++) {
+ for (std::set<SUnit*>::iterator I = ChainSuccs.begin(),
+ E = ChainSuccs.end(); I != E; ++I) {
std::cerr << " ";
- ChainSuccs[i]->dump(G, false);
+ (*I)->dump(G, false);
}
}
}
@@ -105,24 +116,30 @@
/// Sorting functions for the Available queue.
struct ls_rr_sort : public std::binary_function<SUnit*, SUnit*, bool> {
bool operator()(const SUnit* left, const SUnit* right) const {
- if (left->Priority1 > right->Priority1) {
+ bool LFloater = (left ->Preds.size() == 0);
+ bool RFloater = (right->Preds.size() == 0);
+ int LBonus = (int)left ->isDefNUseOperand;
+ int RBonus = (int)right->isDefNUseOperand;
+ int LPriority1 = left ->Priority1 - LBonus;
+ int RPriority1 = right->Priority1 - RBonus;
+ int LPriority2 = left ->Priority2 + LBonus;
+ int RPriority2 = right->Priority2 + RBonus;
+
+ // Favor floaters (i.e. node with no non-passive predecessors):
+ // e.g. MOV32ri.
+ if (!LFloater && RFloater)
return true;
- } else if (left->Priority1 == right->Priority1) {
- unsigned lf = left->FlaggedNodes.size();
- unsigned rf = right->FlaggedNodes.size();
- if (lf > rf)
+ else if (LFloater == RFloater)
+ if (LPriority1 > RPriority1)
return true;
- else if (lf == rf) {
- if (left->Priority2 > right->Priority2)
+ else if (LPriority1 == RPriority1)
+ if (LPriority2 < RPriority2)
return true;
- else if (left->Priority2 == right->Priority2) {
+ else if (LPriority1 == RPriority1)
if (left->CycleBound > right->CycleBound)
return true;
else
return left->Node->getNodeDepth() < right->Node->getNodeDepth();
- }
- }
- }
return false;
}
@@ -163,7 +180,7 @@
private:
SUnit *NewSUnit(SDNode *N);
- void ReleasePred(SUnit *PredSU);
+ void ReleasePred(SUnit *PredSU, bool isChain = false);
void ScheduleNode(SUnit *SU);
int CalcNodePriority(SUnit *SU);
void CalculatePriorities();
@@ -189,11 +206,21 @@
/// ReleasePred - Decrement the NumSuccsLeft count of a predecessor. Add it to
/// the Available queue is the count reaches zero. Also update its cycle bound.
-void ScheduleDAGList::ReleasePred(SUnit *PredSU) {
+void ScheduleDAGList::ReleasePred(SUnit *PredSU, bool isChain) {
SDNode *PredNode = PredSU->Node;
- PredSU->NumSuccsLeft--;
- if (PredSU->NumSuccsLeft == 0) {
+ // FIXME: the distance between two nodes is not always == the predecessor's
+ // latency. For example, the reader can very well read the register written
+ // by the predecessor later than the issue cycle. It also depends on the
+ // interrupt model (drain vs. freeze).
+ PredSU->CycleBound = std::max(PredSU->CycleBound, CurrCycle + PredSU->Latency);
+
+ if (!isChain) {
+ PredSU->NumSuccsLeft--;
+ PredSU->Priority1++;
+ } else
+ PredSU->NumChainSuccsLeft--;
+ if (PredSU->NumSuccsLeft == 0 && PredSU->NumChainSuccsLeft == 0) {
// EntryToken has to go last!
if (PredNode->getOpcode() != ISD::EntryToken)
Available.push(PredSU);
@@ -205,12 +232,6 @@
assert(0);
#endif
}
-
- // FIXME: the distance between two nodes is not always == the predecessor's
- // latency. For example, the reader can very well read the register written
- // by the predecessor later than the issue cycle. It also depends on the
- // interrupt model (drain vs. freeze).
- PredSU->CycleBound = std::max(PredSU->CycleBound, CurrCycle + PredSU->Latency);
}
/// ScheduleNode - Add the node to the schedule. Decrement the pending count of
@@ -221,10 +242,15 @@
SU->Slot = CurrCycle;
// Bottom up: release predecessors
- for (unsigned i = 0, e = SU->Preds.size(); i != e; i++)
- ReleasePred(SU->Preds[i]);
- for (unsigned i = 0, e = SU->ChainPreds.size(); i != e; i++)
- ReleasePred(SU->ChainPreds[i]);
+ for (std::set<SUnit*>::iterator I1 = SU->Preds.begin(),
+ E1 = SU->Preds.end(); I1 != E1; ++I1) {
+ ReleasePred(*I1);
+ SU->NumPredsLeft--;
+ SU->Priority1--;
+ }
+ for (std::set<SUnit*>::iterator I2 = SU->ChainPreds.begin(),
+ E2 = SU->ChainPreds.end(); I2 != E2; ++I2)
+ ReleasePred(*I2, true);
CurrCycle++;
}
@@ -272,7 +298,7 @@
#ifndef NDEBUG
bool AnyNotSched = false;
for (SUnit *SU = HeadSUnit; SU != NULL; SU = SU->Next) {
- if (SU->NumSuccsLeft != 0) {
+ if (SU->NumSuccsLeft != 0 || SU->NumChainSuccsLeft != 0) {
if (!AnyNotSched)
std::cerr << "*** List scheduling failed! ***\n";
SU->dump(&DAG);
@@ -292,22 +318,24 @@
DEBUG(std::cerr << "\n");
}
-/// CalcNodePriority - Priority 1 is just the number of live range genned - number
-/// of live range killed. Priority 2 is the Sethi Ullman number. It returns
-/// priority 2 since it is calculated recursively.
-/// Smaller number is the higher priority in both cases.
+/// CalcNodePriority - Priority1 is just the number of live range genned -
+/// number of live range killed. Priority2 is the Sethi Ullman number. It
+/// returns Priority2 since it is calculated recursively.
+/// Smaller number is the higher priority for Priority2. Reverse is true for
+/// Priority1.
int ScheduleDAGList::CalcNodePriority(SUnit *SU) {
if (SU->Priority2 != INT_MIN)
return SU->Priority2;
- SU->Priority1 = SU->Preds.size() - SU->Succs.size();
+ SU->Priority1 = SU->NumPredsLeft - SU->NumSuccsLeft;
if (SU->Preds.size() == 0) {
SU->Priority2 = 1;
} else {
int Extra = 0;
- for (unsigned i = 0, e = SU->Preds.size(); i != e; i++) {
- SUnit *PredSU = SU->Preds[i];
+ for (std::set<SUnit*>::iterator I = SU->Preds.begin(),
+ E = SU->Preds.end(); I != E; ++I) {
+ SUnit *PredSU = *I;
int PredPriority = CalcNodePriority(PredSU);
if (PredPriority > SU->Priority2) {
SU->Priority2 = PredPriority;
@@ -387,14 +415,16 @@
assert(VT != MVT::Flag);
SUnit *OpSU = SUnitMap[OpN];
if (VT == MVT::Other) {
- SU ->ChainPreds.push_back(OpSU);
- OpSU->ChainSuccs.push_back(SU);
+ if (SU->ChainPreds.insert(OpSU).second)
+ SU->NumChainPredsLeft++;
+ if (OpSU->ChainSuccs.insert(SU).second)
+ OpSU->NumChainSuccsLeft++;
} else {
- SU ->Preds.push_back(OpSU);
- OpSU->Succs.push_back(SU);
+ if (SU->Preds.insert(OpSU).second)
+ SU->NumPredsLeft++;
+ if (OpSU->Succs.insert(SU).second)
+ OpSU->NumSuccsLeft++;
}
- SU->NumPredsLeft++;
- OpSU->NumSuccsLeft++;
}
}
} else {
@@ -407,14 +437,18 @@
assert(VT != MVT::Flag);
SUnit *OpSU = SUnitMap[OpN];
if (VT == MVT::Other) {
- SU ->ChainPreds.push_back(OpSU);
- OpSU->ChainSuccs.push_back(SU);
+ if (SU->ChainPreds.insert(OpSU).second)
+ SU->NumChainPredsLeft++;
+ if (OpSU->ChainSuccs.insert(SU).second)
+ OpSU->NumChainSuccsLeft++;
} else {
- SU ->Preds.push_back(OpSU);
- OpSU->Succs.push_back(SU);
+ if (SU->Preds.insert(OpSU).second)
+ SU->NumPredsLeft++;
+ if (OpSU->Succs.insert(SU).second)
+ OpSU->NumSuccsLeft++;
+ if (j == 0 && TII->isTwoAddrInstr(N->getTargetOpcode()))
+ OpSU->isDefNUseOperand = true;
}
- SU->NumPredsLeft++;
- OpSU->NumSuccsLeft++;
}
}
}
More information about the llvm-commits
mailing list