[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp
Evan Cheng
evan.cheng at apple.com
Tue May 9 00:13:47 PDT 2006
Changes in directory llvm/lib/CodeGen/SelectionDAG:
ScheduleDAGList.cpp updated: 1.55 -> 1.56
---
Log message:
Add pseudo dependency to force a def&use operand to be scheduled last (unless
the distance between the def and another use is much longer). This is under
option control for now "-sched-lower-defnuse".
---
Diffs of the changes: (+108 -17)
ScheduleDAGList.cpp | 125 ++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 108 insertions(+), 17 deletions(-)
Index: llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp:1.55 llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp:1.56
--- llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp:1.55 Thu May 4 20:47:05 2006
+++ llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp Tue May 9 02:13:34 2006
@@ -35,8 +35,8 @@
using namespace llvm;
namespace {
- cl::opt<bool>
- SchedVertically("sched-vertically", cl::Hidden);
+ cl::opt<bool> SchedVertically("sched-vertically", cl::Hidden);
+ cl::opt<bool> SchedLowerDefNUse("sched-lower-defnuse", cl::Hidden);
}
namespace {
@@ -198,6 +198,8 @@
/// of scheduled nodes which are not themselves scheduled.
std::map<const TargetRegisterClass*, std::set<SUnit*> > OpenNodes;
+ /// RegPressureLimits - Keep track of upper limit of register pressure for
+ /// each register class that allows the scheduler to go into vertical mode.
std::map<const TargetRegisterClass*, unsigned> RegPressureLimits;
public:
@@ -418,7 +420,7 @@
// Build scheduling units.
BuildSchedUnits();
-
+
AvailableQueue->initNodes(SUnits);
// Execute the actual scheduling loop Top-Down or Bottom-Up as appropriate.
@@ -917,6 +919,9 @@
void initNodes(const std::vector<SUnit> &sunits) {
SUnits = &sunits;
+ // Add pseudo dependency edges for two-address nodes.
+ if (SchedLowerDefNUse)
+ AddPseudoTwoAddrDeps();
// Calculate node priorities.
CalculatePriorities();
}
@@ -968,6 +973,7 @@
}
private:
+ void AddPseudoTwoAddrDeps();
void CalculatePriorities();
int CalcNodePriority(const SUnit *SU);
};
@@ -993,18 +999,20 @@
if (RIsFloater)
RBonus += 2;
- // Special tie breaker: if two nodes share a operand, the one that use it
- // as a def&use operand is preferred.
- if (LIsTarget && RIsTarget) {
- if (left->isTwoAddress && !right->isTwoAddress) {
- SDNode *DUNode = left->Node->getOperand(0).Val;
- if (DUNode->isOperand(right->Node))
- LBonus += 2;
- }
- if (!left->isTwoAddress && right->isTwoAddress) {
- SDNode *DUNode = right->Node->getOperand(0).Val;
- if (DUNode->isOperand(left->Node))
- RBonus += 2;
+ if (!SchedLowerDefNUse) {
+ // Special tie breaker: if two nodes share a operand, the one that use it
+ // as a def&use operand is preferred.
+ if (LIsTarget && RIsTarget) {
+ if (left->isTwoAddress && !right->isTwoAddress) {
+ SDNode *DUNode = left->Node->getOperand(0).Val;
+ if (DUNode->isOperand(right->Node))
+ LBonus += 2;
+ }
+ if (!left->isTwoAddress && right->isTwoAddress) {
+ SDNode *DUNode = right->Node->getOperand(0).Val;
+ if (DUNode->isOperand(left->Node))
+ RBonus += 2;
+ }
}
}
@@ -1019,6 +1027,88 @@
return false;
}
+static inline bool isCopyFromLiveIn(const SUnit *SU) {
+ SDNode *N = SU->Node;
+ return N->getOpcode() == ISD::CopyFromReg &&
+ N->getOperand(N->getNumOperands()-1).getValueType() != MVT::Flag;
+}
+
+// FIXME: This is probably too slow!
+static void isReachable(SUnit *SU, SUnit *TargetSU,
+ std::set<SUnit *> &Visited, bool &Reached) {
+ if (Reached) return;
+ if (SU == TargetSU) {
+ Reached = true;
+ return;
+ }
+ if (!Visited.insert(SU).second) return;
+
+ for (std::set<std::pair<SUnit*, bool> >::iterator I = SU->Preds.begin(),
+ E = SU->Preds.end(); I != E; ++I)
+ isReachable(I->first, TargetSU, Visited, Reached);
+}
+
+static bool isReachable(SUnit *SU, SUnit *TargetSU) {
+ std::set<SUnit *> Visited;
+ bool Reached = false;
+ isReachable(SU, TargetSU, Visited, Reached);
+ return Reached;
+}
+
+static SUnit *getDefUsePredecessor(SUnit *SU) {
+ SDNode *DU = SU->Node->getOperand(0).Val;
+ for (std::set<std::pair<SUnit*, bool> >::iterator
+ I = SU->Preds.begin(), E = SU->Preds.end(); I != E; ++I) {
+ if (I->second) continue; // ignore chain preds
+ SUnit *PredSU = I->first;
+ if (PredSU->Node == DU)
+ return PredSU;
+ }
+
+ // Must be flagged.
+ return NULL;
+}
+
+static bool canClobber(SUnit *SU, SUnit *Op) {
+ if (SU->isTwoAddress)
+ return Op == getDefUsePredecessor(SU);
+ return false;
+}
+
+/// AddPseudoTwoAddrDeps - If two nodes share an operand and one of them uses
+/// it as a def&use operand. Add a pseudo control edge from it to the other
+/// node (if it won't create a cycle) so the two-address one will be scheduled
+/// first (lower in the schedule).
+void RegReductionPriorityQueue::AddPseudoTwoAddrDeps() {
+ for (unsigned i = 0, e = SUnits->size(); i != e; ++i) {
+ SUnit *SU = (SUnit *)&((*SUnits)[i]);
+ SDNode *Node = SU->Node;
+ if (!Node->isTargetOpcode())
+ continue;
+
+ if (SU->isTwoAddress) {
+ unsigned Depth = SU->Node->getNodeDepth();
+ SUnit *DUSU = getDefUsePredecessor(SU);
+ if (!DUSU) continue;
+
+ for (std::set<std::pair<SUnit*, bool> >::iterator I = DUSU->Succs.begin(),
+ E = DUSU->Succs.end(); I != E; ++I) {
+ SUnit *SuccSU = I->first;
+ if (SuccSU != SU && !canClobber(SuccSU, DUSU)) {
+ if (SuccSU->Node->getNodeDepth() <= Depth+2 &&
+ !isReachable(SuccSU, SU)) {
+ DEBUG(std::cerr << "Adding an edge from SU # " << SU->NodeNum
+ << " to SU #" << SuccSU->NodeNum << "\n");
+ if (SU->Preds.insert(std::make_pair(SuccSU, true)).second)
+ SU->NumChainPredsLeft++;
+ if (SuccSU->Succs.insert(std::make_pair(SU, true)).second)
+ SuccSU->NumChainSuccsLeft++;
+ }
+ }
+ }
+ }
+ }
+}
/// CalcNodePriority - Priority is the Sethi Ullman number.
/// Smaller number is the higher priority.
@@ -1036,7 +1126,8 @@
// Give it a small SethiUllman number so it will be scheduled right before its
// predecessors that it doesn't lengthen their live ranges.
SethiUllmanNumber = INT_MIN + 10;
- else if (SU->NumPredsLeft == 0 && Opc != ISD::CopyFromReg)
+ else if (SU->NumPredsLeft == 0 &&
+ (Opc != ISD::CopyFromReg || isCopyFromLiveIn(SU)))
SethiUllmanNumber = 1;
else {
int Extra = 0;
@@ -1143,7 +1234,7 @@
Queue.pop();
return V;
}
-
+
/// RemoveFromPriorityQueue - This is a really inefficient way to remove a
/// node from a priority queue. We should roll our own heap to make this
/// better or something.
More information about the llvm-commits
mailing list