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. _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits