/// addPred - This adds the specified edge as a pred of the current node if /// not already. It also adds the current node as a successor of the /// specified node. bool SUnit::addPred(const SDep &D) { // If this node already has this depenence, don't add a redundant one. for (SmallVector<SDep, 4>::iterator I = Preds.begin(), E = Preds.end(); I != E; ++I) { if (I->overlaps(D)) { // Extend the latency if needed. Equivalent to removePred(I) + addPred(D). if (I->getLatency() < D.getLatency()) { SUnit *PredSU = I->getSUnit(); // Find the corresponding successor in N. SDep ForwardD = *I; ForwardD.setSUnit(this); for (SmallVector<SDep, 4>::iterator II = PredSU->Succs.begin(), EE = PredSU->Succs.end(); II != EE; ++II) { if (*II == ForwardD) { II->setLatency(D.getLatency()); break; } } I->setLatency(D.getLatency()); } return false; } } // Now add a corresponding succ to N. SDep P = D; P.setSUnit(this); SUnit *N = D.getSUnit(); // Update the bookkeeping. if (D.getKind() == SDep::Data) { assert(NumPreds < UINT_MAX && "NumPreds will overflow!"); assert(N->NumSuccs < UINT_MAX && "NumSuccs will overflow!"); ++NumPreds; ++N->NumSuccs; } if (!N->isScheduled) { assert(NumPredsLeft < UINT_MAX && "NumPredsLeft will overflow!"); ++NumPredsLeft; } if (!isScheduled) { assert(N->NumSuccsLeft < UINT_MAX && "NumSuccsLeft will overflow!"); ++N->NumSuccsLeft; } Preds.push_back(D); N->Succs.push_back(P); if (P.getLatency() != 0) { this->setDepthDirty(); N->setHeightDirty(); } return true; }
/// addPred - This adds the specified edge as a pred of the current node if /// not already. It also adds the current node as a successor of the /// specified node. void SUnit::addPred(const SDep &D) { // If this node already has this depenence, don't add a redundant one. for (unsigned i = 0, e = (unsigned)Preds.size(); i != e; ++i) if (Preds[i] == D) return; // Now add a corresponding succ to N. SDep P = D; P.setSUnit(this); SUnit *N = D.getSUnit(); // Update the bookkeeping. if (D.getKind() == SDep::Data) { ++NumPreds; ++N->NumSuccs; } if (!N->isScheduled) ++NumPredsLeft; if (!isScheduled) ++N->NumSuccsLeft; Preds.push_back(D); N->Succs.push_back(P); if (P.getLatency() != 0) { this->setDepthDirty(); N->setHeightDirty(); } }
/// removePred - This removes the specified edge as a pred of the current /// node if it exists. It also removes the current node as a successor of /// the specified node. void SUnit::removePred(const SDep &D) { // Find the matching predecessor. for (SmallVector<SDep, 4>::iterator I = Preds.begin(), E = Preds.end(); I != E; ++I) if (*I == D) { bool FoundSucc = false; // Find the corresponding successor in N. SDep P = D; P.setSUnit(this); SUnit *N = D.getSUnit(); for (SmallVector<SDep, 4>::iterator II = N->Succs.begin(), EE = N->Succs.end(); II != EE; ++II) if (*II == P) { FoundSucc = true; N->Succs.erase(II); break; } assert(FoundSucc && "Mismatching preds / succs lists!"); Preds.erase(I); // Update the bookkeeping. if (P.getKind() == SDep::Data) { --NumPreds; --N->NumSuccs; } if (!N->isScheduled) --NumPredsLeft; if (!isScheduled) --N->NumSuccsLeft; if (P.getLatency() != 0) { this->setDepthDirty(); N->setHeightDirty(); } return; } }
/// addPred - This adds the specified edge as a pred of the current node if /// not already. It also adds the current node as a successor of the /// specified node. bool SUnit::addPred(const SDep &D) { // If this node already has this depenence, don't add a redundant one. for (SmallVector<SDep, 4>::const_iterator I = Preds.begin(), E = Preds.end(); I != E; ++I) if (*I == D) return false; // Now add a corresponding succ to N. SDep P = D; P.setSUnit(this); SUnit *N = D.getSUnit(); // Update the bookkeeping. if (D.getKind() == SDep::Data) { assert(NumPreds < UINT_MAX && "NumPreds will overflow!"); assert(N->NumSuccs < UINT_MAX && "NumSuccs will overflow!"); ++NumPreds; ++N->NumSuccs; } if (!N->isScheduled) { assert(NumPredsLeft < UINT_MAX && "NumPredsLeft will overflow!"); ++NumPredsLeft; } if (!isScheduled) { assert(N->NumSuccsLeft < UINT_MAX && "NumSuccsLeft will overflow!"); ++N->NumSuccsLeft; } Preds.push_back(D); N->Succs.push_back(P); if (P.getLatency() != 0) { this->setDepthDirty(); N->setHeightDirty(); } return true; }
// Update the latency of a Phi when the Phi bridges two instructions that // require a multi-cycle latency. void HexagonSubtarget::changePhiLatency(MachineInstr &SrcInst, SUnit *Dst, SDep &Dep) const { if (!SrcInst.isPHI() || Dst->NumPreds == 0 || Dep.getLatency() != 0) return; for (const SDep &PI : Dst->Preds) { if (PI.getLatency() != 0) continue; Dep.setLatency(2); break; } }
// This helper function is responsible for increasing the latency only. void HexagonSubtarget::updateLatency(MachineInstr &SrcInst, MachineInstr &DstInst, SDep &Dep) const { if (!hasV60TOps()) return; auto &QII = static_cast<const HexagonInstrInfo&>(*getInstrInfo()); if (EnableVecFrwdSched && QII.addLatencyToSchedule(SrcInst, DstInst)) { // Vec frwd scheduling. Dep.setLatency(Dep.getLatency() + 1); } else if (useBSBScheduling() && QII.isLateInstrFeedsEarlyInstr(SrcInst, DstInst)) { // BSB scheduling. Dep.setLatency(Dep.getLatency() + 1); } else if (EnableTCLatencySched) { // TClass latency scheduling. // Check if SrcInst produces in 2C an operand of DstInst taken in stage 2B. if (QII.isTC1(SrcInst) || QII.isTC2(SrcInst)) if (!QII.isTC1(DstInst) && !QII.isTC2(DstInst)) Dep.setLatency(Dep.getLatency() + 1); } }
/// removePred - This removes the specified edge as a pred of the current /// node if it exists. It also removes the current node as a successor of /// the specified node. void SUnit::removePred(const SDep &D) { // Find the matching predecessor. for (SmallVector<SDep, 4>::iterator I = Preds.begin(), E = Preds.end(); I != E; ++I) if (*I == D) { // Find the corresponding successor in N. SDep P = D; P.setSUnit(this); SUnit *N = D.getSUnit(); SmallVectorImpl<SDep>::iterator Succ = std::find(N->Succs.begin(), N->Succs.end(), P); assert(Succ != N->Succs.end() && "Mismatching preds / succs lists!"); N->Succs.erase(Succ); Preds.erase(I); // Update the bookkeeping. if (P.getKind() == SDep::Data) { assert(NumPreds > 0 && "NumPreds will underflow!"); assert(N->NumSuccs > 0 && "NumSuccs will underflow!"); --NumPreds; --N->NumSuccs; } if (!N->isScheduled) { if (D.isWeak()) --WeakPredsLeft; else { assert(NumPredsLeft > 0 && "NumPredsLeft will underflow!"); --NumPredsLeft; } } if (!isScheduled) { if (D.isWeak()) --N->WeakSuccsLeft; else { assert(N->NumSuccsLeft > 0 && "NumSuccsLeft will underflow!"); --N->NumSuccsLeft; } } if (P.getLatency() != 0) { this->setDepthDirty(); N->setHeightDirty(); } return; } }
/// ReleaseSucc - Decrement the NumPredsLeft count of a successor. Add it to /// the PendingQueue if the count reaches zero. Also update its cycle bound. void ScheduleDAGList::ReleaseSucc(SUnit *SU, const SDep &D) { SUnit *SuccSU = D.getSUnit(); #ifndef NDEBUG if (SuccSU->NumPredsLeft == 0) { errs() << "*** Scheduling failed! ***\n"; SuccSU->dump(this); errs() << " has been released too many times!\n"; llvm_unreachable(0); } #endif --SuccSU->NumPredsLeft; SuccSU->setDepthToAtLeast(SU->getDepth() + D.getLatency()); // If all the node's predecessors are scheduled, this node is ready // to be scheduled. Ignore the special ExitSU node. if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU) PendingQueue.push_back(SuccSU); }
/// releaseSucc - Decrement the NumPredsLeft count of a successor. Add it to /// the PendingQueue if the count reaches zero. Also update its cycle bound. void ScheduleDAGVLIW::releaseSucc(SUnit *SU, const SDep &D) { SUnit *SuccSU = D.getSUnit(); #ifndef NDEBUG if (SuccSU->NumPredsLeft == 0) { dbgs() << "*** Scheduling failed! ***\n"; SuccSU->dump(this); dbgs() << " has been released too many times!\n"; llvm_unreachable(nullptr); } #endif assert(!D.isWeak() && "unexpected artificial DAG edge"); --SuccSU->NumPredsLeft; SuccSU->setDepthToAtLeast(SU->getDepth() + D.getLatency()); // If all the node's predecessors are scheduled, this node is ready // to be scheduled. Ignore the special ExitSU node. if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU) { PendingQueue.push_back(SuccSU); } }
/// addPred - This adds the specified edge as a pred of the current node if /// not already. It also adds the current node as a successor of the /// specified node. bool SUnit::addPred(const SDep &D, bool Required) { // If this node already has this dependence, don't add a redundant one. for (SmallVectorImpl<SDep>::iterator I = Preds.begin(), E = Preds.end(); I != E; ++I) { // Zero-latency weak edges may be added purely for heuristic ordering. Don't // add them if another kind of edge already exists. if (!Required && I->getSUnit() == D.getSUnit()) return false; if (I->overlaps(D)) { // Extend the latency if needed. Equivalent to removePred(I) + addPred(D). if (I->getLatency() < D.getLatency()) { SUnit *PredSU = I->getSUnit(); // Find the corresponding successor in N. SDep ForwardD = *I; ForwardD.setSUnit(this); for (SmallVectorImpl<SDep>::iterator II = PredSU->Succs.begin(), EE = PredSU->Succs.end(); II != EE; ++II) { if (*II == ForwardD) { II->setLatency(D.getLatency()); break; } } I->setLatency(D.getLatency()); } return false; } } // Now add a corresponding succ to N. SDep P = D; P.setSUnit(this); SUnit *N = D.getSUnit(); // Update the bookkeeping. if (D.getKind() == SDep::Data) { assert(NumPreds < UINT_MAX && "NumPreds will overflow!"); assert(N->NumSuccs < UINT_MAX && "NumSuccs will overflow!"); ++NumPreds; ++N->NumSuccs; } if (!N->isScheduled) { if (D.isWeak()) { ++WeakPredsLeft; } else { assert(NumPredsLeft < UINT_MAX && "NumPredsLeft will overflow!"); ++NumPredsLeft; } } if (!isScheduled) { if (D.isWeak()) { ++N->WeakSuccsLeft; } else { assert(N->NumSuccsLeft < UINT_MAX && "NumSuccsLeft will overflow!"); ++N->NumSuccsLeft; } } Preds.push_back(D); N->Succs.push_back(P); if (P.getLatency() != 0) { this->setDepthDirty(); N->setHeightDirty(); } return true; }