diff --git a/lib/Target/Hexagon/HexagonMachineScheduler.cpp b/lib/Target/Hexagon/HexagonMachineScheduler.cpp index 6a37639889a..b131a8f8d20 100644 --- a/lib/Target/Hexagon/HexagonMachineScheduler.cpp +++ b/lib/Target/Hexagon/HexagonMachineScheduler.cpp @@ -190,6 +190,9 @@ void VLIWMachineScheduler::initRegPressure() { std::vector RegionPressure = RPTracker.getPressure().MaxSetPressure; for (unsigned i = 0, e = RegionPressure.size(); i < e; ++i) { unsigned Limit = TRI->getRegPressureSetLimit(i); + DEBUG(dbgs() << TRI->getRegPressureSetName(i) + << "Limit " << Limit + << " Actual " << RegionPressure[i] << "\n"); if (RegionPressure[i] > Limit) RegionCriticalPSets.push_back(PressureElement(i, 0)); } @@ -199,11 +202,6 @@ void VLIWMachineScheduler::initRegPressure() { RegionCriticalPSets[i].PSetID) << " "; dbgs() << "\n"); - // Reset resource state. - TopResourceModel->resetPacketState(); - TopResourceModel->resetDFA(); - BotResourceModel->resetPacketState(); - BotResourceModel->resetDFA(); TotalPackets = 0; } @@ -264,13 +262,15 @@ bool VLIWResourceModel::isResourceAvailable(SUnit *SU) { } /// Keep track of available resources. -void VLIWResourceModel::reserveResources(SUnit *SU) { +bool VLIWResourceModel::reserveResources(SUnit *SU) { + bool startNewCycle = false; // If this SU does not fit in the packet // start a new one. if (!isResourceAvailable(SU)) { ResourcesModel->clearResources(); Packet.clear(); TotalPackets++; + startNewCycle = true; } switch (SU->getInstr()->getOpcode()) { @@ -295,7 +295,8 @@ void VLIWResourceModel::reserveResources(SUnit *SU) { DEBUG(dbgs() << "Packet[" << TotalPackets << "]:\n"); for (unsigned i = 0, e = Packet.size(); i != e; ++i) { DEBUG(dbgs() << "\t[" << i << "] SU("); - DEBUG(dbgs() << Packet[i]->NodeNum << ")\n"); + DEBUG(dbgs() << Packet[i]->NodeNum << ")\t"); + DEBUG(Packet[i]->getInstr()->dump()); } #endif @@ -305,7 +306,10 @@ void VLIWResourceModel::reserveResources(SUnit *SU) { ResourcesModel->clearResources(); Packet.clear(); TotalPackets++; + startNewCycle = true; } + + return startNewCycle; } // Release all DAG roots for scheduling. @@ -352,6 +356,17 @@ void VLIWMachineScheduler::schedule() { // Initialize top/bottom trackers after computing region pressure. initRegPressure(); + // To view Height/Depth correctly, they should be accessed at least once. + DEBUG(unsigned maxH = 0; + for (unsigned su = 0, e = SUnits.size(); su != e; ++su) + if (SUnits[su].getHeight() > maxH) + maxH = SUnits[su].getHeight(); + dbgs() << "Max Height " << maxH << "\n";); + DEBUG(unsigned maxD = 0; + for (unsigned su = 0, e = SUnits.size(); su != e; ++su) + if (SUnits[su].getDepth() > maxD) + maxD = SUnits[su].getDepth(); + dbgs() << "Max Depth " << maxD << "\n";); DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su) SUnits[su].dumpAll(this)); @@ -390,13 +405,9 @@ void VLIWMachineScheduler::schedule() { assert(TopRPTracker.getPos() == CurrentTop && "out of sync"); updateScheduledPressure(TopRPTracker.getPressure().MaxSetPressure); - // Update DFA state. - TopResourceModel->reserveResources(SU); - // Release dependent instructions for scheduling. releaseSuccessors(SU); - } - else { + } else { assert(SU->isBottomReady() && "node still has unscheduled dependencies"); MachineBasicBlock::iterator priorII = priorNonDebug(CurrentBottom, CurrentTop); @@ -415,9 +426,6 @@ void VLIWMachineScheduler::schedule() { assert(BotRPTracker.getPos() == CurrentBottom && "out of sync"); updateScheduledPressure(BotRPTracker.getPressure().MaxSetPressure); - // Update DFA state. - BotResourceModel->reserveResources(SU); - // Release dependent instructions for scheduling. releasePredecessors(SU); } @@ -426,9 +434,6 @@ void VLIWMachineScheduler::schedule() { } assert(CurrentTop == CurrentBottom && "Nonempty unscheduled zone."); - DEBUG(dbgs() << "Final schedule has " << TopResourceModel->getTotalPackets() + - BotResourceModel->getTotalPackets()<< "packets.\n"); - placeDebugValues(); } @@ -465,6 +470,9 @@ void ConvergingVLIWScheduler::initialize(VLIWMachineScheduler *dag) { Top.HazardRec = TM.getInstrInfo()->CreateTargetMIHazardRecognizer(Itin, DAG); Bot.HazardRec = TM.getInstrInfo()->CreateTargetMIHazardRecognizer(Itin, DAG); + Top.ResourceModel = new VLIWResourceModel(TM); + Bot.ResourceModel = new VLIWResourceModel(TM); + assert((!ForceTopDown || !ForceBottomUp) && "-misched-topdown incompatible with -misched-bottomup"); } @@ -553,8 +561,7 @@ void ConvergingVLIWScheduler::SchedBoundary::bumpCycle() { if (!HazardRec->isEnabled()) { // Bypass HazardRec virtual calls. CurrCycle = NextCycle; - } - else { + } else { // Bypass getHazardType calls in case of long latency. for (; CurrCycle != NextCycle; ++CurrCycle) { if (isTop()) @@ -571,6 +578,7 @@ void ConvergingVLIWScheduler::SchedBoundary::bumpCycle() { /// Move the boundary of scheduled code by one SUnit. void ConvergingVLIWScheduler::SchedBoundary::bumpNode(SUnit *SU) { + bool startNewCycle = false; // Update the reservation table. if (HazardRec->isEnabled()) { @@ -581,13 +589,20 @@ void ConvergingVLIWScheduler::SchedBoundary::bumpNode(SUnit *SU) { } HazardRec->EmitInstruction(SU); } + + // Update DFA model. + startNewCycle = ResourceModel->reserveResources(SU); + // Check the instruction group dispatch limit. // TODO: Check if this SU must end a dispatch group. IssueCount += DAG->getNumMicroOps(SU->getInstr()); - if (IssueCount >= DAG->getIssueWidth()) { + if (startNewCycle) { DEBUG(dbgs() << "*** Max instrs at cycle " << CurrCycle << '\n'); bumpCycle(); } + else + DEBUG(dbgs() << "*** IssueCount " << IssueCount + << " at cycle " << CurrCycle << '\n'); } /// Release pending ready nodes in to the available queue. This makes them @@ -648,8 +663,9 @@ SUnit *ConvergingVLIWScheduler::SchedBoundary::pickOnlyChoice() { } #ifndef NDEBUG -void ConvergingVLIWScheduler::traceCandidate(const char *Label, const ReadyQueue &Q, - SUnit *SU, PressureElement P) { +void ConvergingVLIWScheduler::traceCandidate(const char *Label, + const ReadyQueue &Q, + SUnit *SU, PressureElement P) { dbgs() << Label << " " << Q.getName() << " "; if (P.isValid()) dbgs() << TRI->getRegPressureSetName(P.PSetID) << ":" << P.UnitIncrease @@ -660,10 +676,48 @@ void ConvergingVLIWScheduler::traceCandidate(const char *Label, const ReadyQueue } #endif +/// getSingleUnscheduledPred - If there is exactly one unscheduled predecessor +/// of SU, return it, otherwise return null. +static SUnit *getSingleUnscheduledPred(SUnit *SU) { + SUnit *OnlyAvailablePred = 0; + for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + SUnit &Pred = *I->getSUnit(); + if (!Pred.isScheduled) { + // We found an available, but not scheduled, predecessor. If it's the + // only one we have found, keep track of it... otherwise give up. + if (OnlyAvailablePred && OnlyAvailablePred != &Pred) + return 0; + OnlyAvailablePred = &Pred; + } + } + return OnlyAvailablePred; +} + +/// getSingleUnscheduledSucc - If there is exactly one unscheduled successor +/// of SU, return it, otherwise return null. +static SUnit *getSingleUnscheduledSucc(SUnit *SU) { + SUnit *OnlyAvailableSucc = 0; + for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) { + SUnit &Succ = *I->getSUnit(); + if (!Succ.isScheduled) { + // We found an available, but not scheduled, successor. If it's the + // only one we have found, keep track of it... otherwise give up. + if (OnlyAvailableSucc && OnlyAvailableSucc != &Succ) + return 0; + OnlyAvailableSucc = &Succ; + } + } + return OnlyAvailableSucc; +} + // Constants used to denote relative importance of // heuristic components for cost computation. static const unsigned PriorityOne = 200; +static const unsigned PriorityTwo = 100; static const unsigned PriorityThree = 50; +static const unsigned PriorityFour = 20; static const unsigned ScaleTwo = 10; static const unsigned FactorOne = 2; @@ -685,19 +739,44 @@ int ConvergingVLIWScheduler::SchedulingCost(ReadyQueue &Q, SUnit *SU, ResCount += PriorityOne; // Critical path first. - if (Q.getID() == TopQID) + if (Q.getID() == TopQID) { ResCount += (SU->getHeight() * ScaleTwo); - else + + // If resources are available for it, multiply the + // chance of scheduling. + if (Top.ResourceModel->isResourceAvailable(SU)) + ResCount <<= FactorOne; + } else { ResCount += (SU->getDepth() * ScaleTwo); - // If resources are available for it, multiply the - // chance of scheduling. - if (DAG->getTopResourceModel()->isResourceAvailable(SU)) - ResCount <<= FactorOne; + // If resources are available for it, multiply the + // chance of scheduling. + if (Bot.ResourceModel->isResourceAvailable(SU)) + ResCount <<= FactorOne; + } + + unsigned NumNodesBlocking = 0; + if (Q.getID() == TopQID) { + // How many SUs does it block from scheduling? + // Look at all of the successors of this node. + // Count the number of nodes that + // this node is the sole unscheduled node for. + for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); + I != E; ++I) + if (getSingleUnscheduledPred(I->getSUnit()) == SU) + ++NumNodesBlocking; + } else { + // How many unscheduled predecessors block this node? + for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) + if (getSingleUnscheduledSucc(I->getSUnit()) == SU) + ++NumNodesBlocking; + } + ResCount += (NumNodesBlocking * ScaleTwo); // Factor in reg pressure as a heuristic. - ResCount -= (Delta.Excess.UnitIncrease * PriorityThree); - ResCount -= (Delta.CriticalMax.UnitIncrease * PriorityThree); + ResCount -= (Delta.Excess.UnitIncrease*PriorityThree); + ResCount -= (Delta.CriticalMax.UnitIncrease*PriorityThree); DEBUG(if (verbose) dbgs() << " Total(" << ResCount << ")"); @@ -736,7 +815,6 @@ pickNodeFromQueue(ReadyQueue &Q, const RegPressureTracker &RPTracker, continue; } - // Best cost. if (CurrentCost > Candidate.SCost) { DEBUG(traceCandidate("CCAND", Q, *I)); @@ -859,14 +937,14 @@ SUnit *ConvergingVLIWScheduler::pickNode(bool &IsTopNode) { } /// Update the scheduler's state after scheduling a node. This is the same node -/// that was just returned by pickNode(). However, VLIWMachineScheduler needs to update -/// it's state based on the current cycle before MachineSchedStrategy does. +/// that was just returned by pickNode(). However, VLIWMachineScheduler needs +/// to update it's state based on the current cycle before MachineSchedStrategy +/// does. void ConvergingVLIWScheduler::schedNode(SUnit *SU, bool IsTopNode) { if (IsTopNode) { SU->TopReadyCycle = Top.CurrCycle; Top.bumpNode(SU); - } - else { + } else { SU->BotReadyCycle = Bot.CurrCycle; Bot.bumpNode(SU); } diff --git a/lib/Target/Hexagon/HexagonMachineScheduler.h b/lib/Target/Hexagon/HexagonMachineScheduler.h index 7d8cc3d24e0..f3643d64f69 100644 --- a/lib/Target/Hexagon/HexagonMachineScheduler.h +++ b/lib/Target/Hexagon/HexagonMachineScheduler.h @@ -40,11 +40,10 @@ using namespace llvm; namespace llvm { class VLIWMachineScheduler; -/// MachineSchedStrategy - Interface used by VLIWMachineScheduler to drive the selected -/// scheduling algorithm. +/// MachineSchedStrategy - Interface used by VLIWMachineScheduler to drive +/// the selected scheduling algorithm. /// -/// If this works well and targets wish to reuse VLIWMachineScheduler, we may expose it -/// in ScheduleDAGInstrs.h +/// TODO: Move this to ScheduleDAGInstrs.h class MachineSchedStrategy { public: virtual ~MachineSchedStrategy() {} @@ -57,7 +56,8 @@ public: /// be scheduled at the bottom. virtual SUnit *pickNode(bool &IsTopNode) = 0; - /// Notify MachineSchedStrategy that VLIWMachineScheduler has scheduled a node. + /// Notify MachineSchedStrategy that VLIWMachineScheduler has + /// scheduled a node. virtual void schedNode(SUnit *SU, bool IsTopNode) = 0; /// When all predecessor dependencies have been resolved, free this node for @@ -69,7 +69,8 @@ public: }; //===----------------------------------------------------------------------===// -// ConvergingVLIWScheduler - Implementation of the standard MachineSchedStrategy. +// ConvergingVLIWScheduler - Implementation of the standard +// MachineSchedStrategy. //===----------------------------------------------------------------------===// /// ReadyQueue encapsulates vector of "ready" SUnits with basic convenience @@ -123,12 +124,197 @@ public: } }; -/// ConvergingVLIWScheduler shrinks the unscheduled zone using heuristics to balance -/// the schedule. +class VLIWResourceModel { + /// ResourcesModel - Represents VLIW state. + /// Not limited to VLIW targets per say, but assumes + /// definition of DFA by a target. + DFAPacketizer *ResourcesModel; + + const InstrItineraryData *InstrItins; + + /// Local packet/bundle model. Purely + /// internal to the MI schedulre at the time. + std::vector Packet; + + /// Total packets created. + unsigned TotalPackets; + +public: + VLIWResourceModel(MachineSchedContext *C, const InstrItineraryData *IID) : + InstrItins(IID), TotalPackets(0) { + const TargetMachine &TM = C->MF->getTarget(); + ResourcesModel = TM.getInstrInfo()->CreateTargetScheduleState(&TM,NULL); + + // This hard requirement could be relaxed, + // but for now do not let it proceed. + assert(ResourcesModel && "Unimplemented CreateTargetScheduleState."); + + Packet.resize(InstrItins->SchedModel->IssueWidth); + Packet.clear(); + ResourcesModel->clearResources(); + } + + VLIWResourceModel(const TargetMachine &TM) : + InstrItins(TM.getInstrItineraryData()), TotalPackets(0) { + ResourcesModel = TM.getInstrInfo()->CreateTargetScheduleState(&TM,NULL); + + // This hard requirement could be relaxed, + // but for now do not let it proceed. + assert(ResourcesModel && "Unimplemented CreateTargetScheduleState."); + + Packet.resize(InstrItins->SchedModel->IssueWidth); + Packet.clear(); + ResourcesModel->clearResources(); + } + + ~VLIWResourceModel() { + delete ResourcesModel; + } + + void resetPacketState() { + Packet.clear(); + } + + void resetDFA() { + ResourcesModel->clearResources(); + } + + void reset() { + Packet.clear(); + ResourcesModel->clearResources(); + } + + bool isResourceAvailable(SUnit *SU); + bool reserveResources(SUnit *SU); + unsigned getTotalPackets() const { return TotalPackets; } +}; + +class VLIWMachineScheduler : public ScheduleDAGInstrs { + /// AA - AliasAnalysis for making memory reference queries. + AliasAnalysis *AA; + + RegisterClassInfo *RegClassInfo; + MachineSchedStrategy *SchedImpl; + + MachineBasicBlock::iterator LiveRegionEnd; + + /// Register pressure in this region computed by buildSchedGraph. + IntervalPressure RegPressure; + RegPressureTracker RPTracker; + + /// List of pressure sets that exceed the target's pressure limit before + /// scheduling, listed in increasing set ID order. Each pressure set is paired + /// with its max pressure in the currently scheduled regions. + std::vector RegionCriticalPSets; + + /// The top of the unscheduled zone. + MachineBasicBlock::iterator CurrentTop; + IntervalPressure TopPressure; + RegPressureTracker TopRPTracker; + + /// The bottom of the unscheduled zone. + MachineBasicBlock::iterator CurrentBottom; + IntervalPressure BotPressure; + RegPressureTracker BotRPTracker; + +#ifndef NDEBUG + /// The number of instructions scheduled so far. Used to cut off the + /// scheduler at the point determined by misched-cutoff. + unsigned NumInstrsScheduled; +#endif + + /// Total packets in the region. + unsigned TotalPackets; + + const MachineLoopInfo *MLI; +public: + VLIWMachineScheduler(MachineSchedContext *C, MachineSchedStrategy *S): + ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, /*IsPostRA=*/false, C->LIS), + AA(C->AA), RegClassInfo(C->RegClassInfo), SchedImpl(S), + RPTracker(RegPressure), CurrentTop(), TopRPTracker(TopPressure), + CurrentBottom(), BotRPTracker(BotPressure), MLI(C->MLI) { +#ifndef NDEBUG + NumInstrsScheduled = 0; +#endif + TotalPackets = 0; + } + + virtual ~VLIWMachineScheduler() { + delete SchedImpl; + } + + MachineBasicBlock::iterator top() const { return CurrentTop; } + MachineBasicBlock::iterator bottom() const { return CurrentBottom; } + + /// Implement the ScheduleDAGInstrs interface for handling the next scheduling + /// region. This covers all instructions in a block, while schedule() may only + /// cover a subset. + void enterRegion(MachineBasicBlock *bb, + MachineBasicBlock::iterator begin, + MachineBasicBlock::iterator end, + unsigned endcount); + + /// Schedule - This is called back from ScheduleDAGInstrs::Run() when it's + /// time to do some work. + void schedule(); + + unsigned CurCycle; + + /// Get current register pressure for the top scheduled instructions. + const IntervalPressure &getTopPressure() const { return TopPressure; } + const RegPressureTracker &getTopRPTracker() const { return TopRPTracker; } + + /// Get current register pressure for the bottom scheduled instructions. + const IntervalPressure &getBotPressure() const { return BotPressure; } + const RegPressureTracker &getBotRPTracker() const { return BotRPTracker; } + + /// Get register pressure for the entire scheduling region before scheduling. + const IntervalPressure &getRegPressure() const { return RegPressure; } + + const std::vector &getRegionCriticalPSets() const { + return RegionCriticalPSets; + } + + /// getIssueWidth - Return the max instructions per scheduling group. + unsigned getIssueWidth() const { + return (InstrItins && InstrItins->SchedModel) + ? InstrItins->SchedModel->IssueWidth : 1; + } + + /// getNumMicroOps - Return the number of issue slots required for this MI. + unsigned getNumMicroOps(MachineInstr *MI) const { + return 1; + //if (!InstrItins) return 1; + //int UOps = InstrItins->getNumMicroOps(MI->getDesc().getSchedClass()); + //return (UOps >= 0) ? UOps : TII->getNumMicroOps(InstrItins, MI); + } + +private: + void scheduleNodeTopDown(SUnit *SU); + void listScheduleTopDown(); + + void initRegPressure(); + void updateScheduledPressure(std::vector NewMaxPressure); + + void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos); + bool checkSchedLimit(); + + void releaseRoots(); + + void releaseSucc(SUnit *SU, SDep *SuccEdge); + void releaseSuccessors(SUnit *SU); + void releasePred(SUnit *SU, SDep *PredEdge); + void releasePredecessors(SUnit *SU); + + void placeDebugValues(); +}; + +/// ConvergingVLIWScheduler shrinks the unscheduled zone using heuristics +/// to balance the schedule. class ConvergingVLIWScheduler : public MachineSchedStrategy { - /// Store the state used by ConvergingVLIWScheduler heuristics, required for the - /// lifetime of one invocation of pickNode(). + /// Store the state used by ConvergingVLIWScheduler heuristics, required + /// for the lifetime of one invocation of pickNode(). struct SchedCandidate { // The best SUnit candidate. SUnit *SU; @@ -157,6 +343,7 @@ class ConvergingVLIWScheduler : public MachineSchedStrategy { bool CheckPending; ScheduleHazardRecognizer *HazardRec; + VLIWResourceModel *ResourceModel; unsigned CurrCycle; unsigned IssueCount; @@ -172,10 +359,14 @@ class ConvergingVLIWScheduler : public MachineSchedStrategy { SchedBoundary(unsigned ID, const Twine &Name): DAG(0), Available(ID, Name+".A"), Pending(ID << ConvergingVLIWScheduler::LogMaxQID, Name+".P"), - CheckPending(false), HazardRec(0), CurrCycle(0), IssueCount(0), + CheckPending(false), HazardRec(0), ResourceModel(0), + CurrCycle(0), IssueCount(0), MinReadyCycle(UINT_MAX), MaxMinLatency(0) {} - ~SchedBoundary() { delete HazardRec; } + ~SchedBoundary() { + delete ResourceModel; + delete HazardRec; + } bool isTop() const { return Available.getID() == ConvergingVLIWScheduler::TopQID; @@ -240,183 +431,6 @@ protected: #endif }; -class VLIWResourceModel { - /// ResourcesModel - Represents VLIW state. - /// Not limited to VLIW targets per say, but assumes - /// definition of DFA by a target. - DFAPacketizer *ResourcesModel; - - const InstrItineraryData *InstrItins; - - /// Local packet/bundle model. Purely - /// internal to the MI schedulre at the time. - std::vector Packet; - - /// Total packets created. - unsigned TotalPackets; - -public: - VLIWResourceModel(MachineSchedContext *C, const InstrItineraryData *IID) : - InstrItins(IID), TotalPackets(0) { - const TargetMachine &TM = C->MF->getTarget(); - ResourcesModel = TM.getInstrInfo()->CreateTargetScheduleState(&TM,NULL); - - // This hard requirement could be relaxed, but for now do not let it proceed. - assert(ResourcesModel && "Unimplemented CreateTargetScheduleState."); - - Packet.resize(InstrItins->SchedModel->IssueWidth); - Packet.clear(); - ResourcesModel->clearResources(); - } - - ~VLIWResourceModel() { - delete ResourcesModel; - } - - void resetPacketState() { - Packet.clear(); - } - - void resetDFA() { - ResourcesModel->clearResources(); - } - - bool isResourceAvailable(SUnit *SU); - void reserveResources(SUnit *SU); - unsigned getTotalPackets() const { return TotalPackets; } -}; - -class VLIWMachineScheduler : public ScheduleDAGInstrs { - /// AA - AliasAnalysis for making memory reference queries. - AliasAnalysis *AA; - - RegisterClassInfo *RegClassInfo; - MachineSchedStrategy *SchedImpl; - - /// state separatly for top/bottom sectioins. - VLIWResourceModel *TopResourceModel; - VLIWResourceModel *BotResourceModel; - - MachineBasicBlock::iterator LiveRegionEnd; - - /// Register pressure in this region computed by buildSchedGraph. - IntervalPressure RegPressure; - RegPressureTracker RPTracker; - - /// List of pressure sets that exceed the target's pressure limit before - /// scheduling, listed in increasing set ID order. Each pressure set is paired - /// with its max pressure in the currently scheduled regions. - std::vector RegionCriticalPSets; - - /// The top of the unscheduled zone. - MachineBasicBlock::iterator CurrentTop; - IntervalPressure TopPressure; - RegPressureTracker TopRPTracker; - - /// The bottom of the unscheduled zone. - MachineBasicBlock::iterator CurrentBottom; - IntervalPressure BotPressure; - RegPressureTracker BotRPTracker; - -#ifndef NDEBUG - /// The number of instructions scheduled so far. Used to cut off the - /// scheduler at the point determined by misched-cutoff. - unsigned NumInstrsScheduled; -#endif - - /// Total packets in the region. - unsigned TotalPackets; - - const MachineLoopInfo *MLI; -public: - VLIWMachineScheduler(MachineSchedContext *C, MachineSchedStrategy *S): - ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, /*IsPostRA=*/false, C->LIS), - AA(C->AA), RegClassInfo(C->RegClassInfo), SchedImpl(S), - RPTracker(RegPressure), CurrentTop(), TopRPTracker(TopPressure), - CurrentBottom(), BotRPTracker(BotPressure), MLI(C->MLI) { - - TopResourceModel = new VLIWResourceModel(C, InstrItins); - BotResourceModel = new VLIWResourceModel(C, InstrItins); - -#ifndef NDEBUG - NumInstrsScheduled = 0; -#endif - TotalPackets = 0; - } - - virtual ~VLIWMachineScheduler() { - delete SchedImpl; - delete TopResourceModel; - delete BotResourceModel; - } - - MachineBasicBlock::iterator top() const { return CurrentTop; } - MachineBasicBlock::iterator bottom() const { return CurrentBottom; } - - /// Implement the ScheduleDAGInstrs interface for handling the next scheduling - /// region. This covers all instructions in a block, while schedule() may only - /// cover a subset. - void enterRegion(MachineBasicBlock *bb, - MachineBasicBlock::iterator begin, - MachineBasicBlock::iterator end, - unsigned endcount); - - /// Schedule - This is called back from ScheduleDAGInstrs::Run() when it's - /// time to do some work. - void schedule(); - - unsigned CurCycle; - - /// Get current register pressure for the top scheduled instructions. - const IntervalPressure &getTopPressure() const { return TopPressure; } - const RegPressureTracker &getTopRPTracker() const { return TopRPTracker; } - - /// Get current register pressure for the bottom scheduled instructions. - const IntervalPressure &getBotPressure() const { return BotPressure; } - const RegPressureTracker &getBotRPTracker() const { return BotRPTracker; } - - /// Get register pressure for the entire scheduling region before scheduling. - const IntervalPressure &getRegPressure() const { return RegPressure; } - - const std::vector &getRegionCriticalPSets() const { - return RegionCriticalPSets; - } - - VLIWResourceModel *getTopResourceModel() { return TopResourceModel; } - VLIWResourceModel *getBotResourceModel() { return BotResourceModel; } - - /// getIssueWidth - Return the max instructions per scheduling group. - unsigned getIssueWidth() const { - return (InstrItins && InstrItins->SchedModel) - ? InstrItins->SchedModel->IssueWidth : 1; - } - - /// getNumMicroOps - Return the number of issue slots required for this MI. - unsigned getNumMicroOps(MachineInstr *MI) const { - if (!InstrItins) return 1; - int UOps = InstrItins->getNumMicroOps(MI->getDesc().getSchedClass()); - return (UOps >= 0) ? UOps : TII->getNumMicroOps(InstrItins, MI); - } - -private: - void scheduleNodeTopDown(SUnit *SU); - void listScheduleTopDown(); - - void initRegPressure(); - void updateScheduledPressure(std::vector NewMaxPressure); - - void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos); - bool checkSchedLimit(); - - void releaseRoots(); - - void releaseSucc(SUnit *SU, SDep *SuccEdge); - void releaseSuccessors(SUnit *SU); - void releasePred(SUnit *SU, SDep *PredEdge); - void releasePredecessors(SUnit *SU); - - void placeDebugValues(); -}; } // namespace