Index: llvm/lib/Target/SystemZ/SystemZMachineScheduler.h =================================================================== --- llvm/lib/Target/SystemZ/SystemZMachineScheduler.h +++ llvm/lib/Target/SystemZ/SystemZMachineScheduler.h @@ -96,7 +96,7 @@ SUSet Available; /// Current MBB - MachineBasicBlock *MBB; + MachineBasicBlock *CurrentMBB; /// Maintain hazard recognizers for all blocks, so that the scheduler state /// can be maintained past BB boundaries when appropariate. @@ -135,6 +135,20 @@ /// Tell the strategy that current MBB is done. void leaveMBB() override; + /// Tell the stragegy to save the scheduled state before leaving the MBB, so + /// that, its scheduled state could be forward to successor MBB. + bool saveScheduledState(MachineBasicBlock *MBB) override; + + /// Tell the strategy to restore the scheduled state, from its single pred + /// MBB, before entering new MBB. Return true if succeed. + bool restoreScheduledState(MachineBasicBlock *MBB) override; + + /// Get the single pred MBB if has. Though the loop header has two + /// predecessors, return the latch if it is not a single blook loop. Because, + /// we are going from latch to the loop header most time, except the first + /// time. + MachineBasicBlock *getScheduledPredMBB(MachineBasicBlock *MBB) override; + /// Pick the next node to schedule, or return NULL. SUnit *pickNode(bool &IsTopNode) override; Index: llvm/lib/Target/SystemZ/SystemZMachineScheduler.cpp =================================================================== --- llvm/lib/Target/SystemZ/SystemZMachineScheduler.cpp +++ llvm/lib/Target/SystemZ/SystemZMachineScheduler.cpp @@ -36,14 +36,15 @@ // Try to find a single predecessor that would be interesting for the // scheduler in the top-most region of MBB. -static MachineBasicBlock *getSingleSchedPred(MachineBasicBlock *MBB, - const MachineLoop *Loop) { - MachineBasicBlock *PredMBB = nullptr; - if (MBB->pred_size() == 1) - PredMBB = *MBB->pred_begin(); +MachineBasicBlock * +SystemZPostRASchedStrategy::getScheduledPredMBB(MachineBasicBlock *MBB) { + MachineBasicBlock *PredMBB = MachineSchedStrategy::getScheduledPredMBB(MBB); + if (PredMBB) + return PredMBB; // The loop header has two predecessors, return the latch, but not for a // single block loop. + const MachineLoop *Loop = MLI->getLoopFor(MBB); if (MBB->pred_size() == 2 && Loop != nullptr && Loop->getHeader() == MBB) { for (auto I = MBB->pred_begin(); I != MBB->pred_end(); ++I) if (Loop->contains(*I)) @@ -60,8 +61,8 @@ advanceTo(MachineBasicBlock::iterator NextBegin) { MachineBasicBlock::iterator LastEmittedMI = HazardRec->getLastEmittedMI(); MachineBasicBlock::iterator I = - ((LastEmittedMI != nullptr && LastEmittedMI->getParent() == MBB) ? - std::next(LastEmittedMI) : MBB->begin()); + ((LastEmittedMI != nullptr && LastEmittedMI->getParent() == CurrentMBB) ? + std::next(LastEmittedMI) : CurrentMBB->begin()); for (; I != NextBegin; ++I) { if (I->isPosition() || I->isDebugInstr()) @@ -74,54 +75,60 @@ LLVM_DEBUG(HazardRec->dumpState();); } -void SystemZPostRASchedStrategy::enterMBB(MachineBasicBlock *NextMBB) { - assert ((SchedStates.find(NextMBB) == SchedStates.end()) && - "Entering MBB twice?"); - LLVM_DEBUG(dbgs() << "** Entering " << printMBBReference(*NextMBB)); +// Save the scheduled state for 'MBB' before leaving it, so that, it could be +// restored if it is the singled pred MBB. +bool SystemZPostRASchedStrategy::saveScheduledState(MachineBasicBlock *MBB) { + assert ((SchedStates.find(MBB) == SchedStates.end()) && + "Saving scheduled state for MBB twice?"); + assert(HazardRec && "HazardRec must be set when enter the MBB"); - MBB = NextMBB; - - /// Create a HazardRec for MBB, save it in SchedStates and set HazardRec to - /// point to it. - HazardRec = SchedStates[MBB] = new SystemZHazardRecognizer(TII, &SchedModel); - LLVM_DEBUG(const MachineLoop *Loop = MLI->getLoopFor(MBB); - if (Loop && Loop->getHeader() == MBB) dbgs() << " (Loop header)"; - dbgs() << ":\n";); - - // Try to take over the state from a single predecessor, if it has been - // scheduled. If this is not possible, we are done. - MachineBasicBlock *SinglePredMBB = - getSingleSchedPred(MBB, MLI->getLoopFor(MBB)); - if (SinglePredMBB == nullptr || - SchedStates.find(SinglePredMBB) == SchedStates.end()) - return; + SchedStates[MBB] = HazardRec; + return true; +} - LLVM_DEBUG(dbgs() << "** Continued scheduling from " - << printMBBReference(*SinglePredMBB) << "\n";); +// Restore the scheduled state from its single pred MBB if it has. +bool SystemZPostRASchedStrategy::restoreScheduledState(MachineBasicBlock *MBB) { + if (SchedStates.find(MBB) == SchedStates.end()) + return false; - HazardRec->copyState(SchedStates[SinglePredMBB]); + HazardRec->copyState(SchedStates[MBB]); LLVM_DEBUG(HazardRec->dumpState();); // Emit incoming terminator(s). Be optimistic and assume that branch // prediction will generally do "the right thing". - for (MachineBasicBlock::iterator I = SinglePredMBB->getFirstTerminator(); - I != SinglePredMBB->end(); I++) { + for (MachineBasicBlock::iterator I = MBB->getFirstTerminator(); + I != MBB->end(); I++) { LLVM_DEBUG(dbgs() << "** Emitting incoming branch: "; I->dump();); bool TakenBranch = (I->isBranch() && (TII->getBranchInfo(*I).Target->isReg() || // Relative branch - TII->getBranchInfo(*I).Target->getMBB() == MBB)); + TII->getBranchInfo(*I).Target->getMBB() == CurrentMBB)); HazardRec->emitInstruction(&*I, TakenBranch); if (TakenBranch) break; } + + return true; +} + +void SystemZPostRASchedStrategy::enterMBB(MachineBasicBlock *NextMBB) { + LLVM_DEBUG(dbgs() << "** Entering " << printMBBReference(*NextMBB)); + + CurrentMBB = NextMBB; + HazardRec = new SystemZHazardRecognizer(TII, &SchedModel); + + LLVM_DEBUG( + const MachineLoop *Loop = MLI->getLoopFor(CurrentMBB); + if (Loop && Loop->getHeader() == CurrentMBB) dbgs() << " (Loop header)"; + dbgs() << ":\n";); } void SystemZPostRASchedStrategy::leaveMBB() { - LLVM_DEBUG(dbgs() << "** Leaving " << printMBBReference(*MBB) << "\n";); + LLVM_DEBUG(dbgs() << "** Leaving " << + printMBBReference(*CurrentMBB) << "\n";); // Advance to first terminator. The successor block will handle terminators // dependent on CFG layout (T/NT branch etc). - advanceTo(MBB->getFirstTerminator()); + advanceTo(CurrentMBB->getFirstTerminator()); } SystemZPostRASchedStrategy:: @@ -129,7 +136,7 @@ : MLI(C->MLI), TII(static_cast (C->MF->getSubtarget().getInstrInfo())), - MBB(nullptr), HazardRec(nullptr) { + CurrentMBB(nullptr), HazardRec(nullptr) { const TargetSubtargetInfo *ST = &C->MF->getSubtarget(); SchedModel.init(ST); }