Index: llvm/include/llvm/CodeGen/MachineScheduler.h =================================================================== --- llvm/include/llvm/CodeGen/MachineScheduler.h +++ llvm/include/llvm/CodeGen/MachineScheduler.h @@ -229,6 +229,19 @@ /// Tell the strategy that current MBB is done. virtual void leaveMBB() {}; + /// Return true if scheduled state is saved successfully before leaving + /// the MBB. + virtual bool saveScheduledState(MachineBasicBlock *MBB) { return false; } + + /// Return true if scheduled state is restored from predecessor MBB. + virtual bool restoreScheduledState(MachineBasicBlock *MBB) { return false; } + + /// Return predecessor if MBB have only a single predecessor. + virtual MachineBasicBlock *getScheduledPredMBB(MachineBasicBlock *MBB); + + /// Return true if scheduled state is forwarded between MBBs. + virtual bool forwardScheduledState() const { return false; } + /// Notify this strategy that all roots have been released (including those /// that depend on EntrySU or ExitSU). virtual void registerRoots() {} @@ -296,7 +309,8 @@ /// themselves (in case of a scheduling boundary in MBB) will be done /// beginning with the topmost region of MBB. bool doMBBSchedRegionsTopDown() const override { - return SchedImpl->doMBBSchedRegionsTopDown(); + return SchedImpl->doMBBSchedRegionsTopDown() || + SchedImpl->forwardScheduledState(); } // Returns LiveIntervals instance for use in DAG mutators and such. Index: llvm/lib/CodeGen/MachineScheduler.cpp =================================================================== --- llvm/lib/CodeGen/MachineScheduler.cpp +++ llvm/lib/CodeGen/MachineScheduler.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/PriorityQueue.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/CodeGen/LiveInterval.h" @@ -72,6 +73,8 @@ #define DEBUG_TYPE "machine-scheduler" +STATISTIC(NumFwdSchedState, "Number of scheduled state forwarded"); + namespace llvm { cl::opt ForceTopDown("misched-topdown", cl::Hidden, @@ -145,6 +148,11 @@ delete RegClassInfo; } +MachineBasicBlock *MachineSchedStrategy::getScheduledPredMBB( + MachineBasicBlock *MBB) { + return MBB->pred_size() == 1 ? *MBB->pred_begin() : nullptr; +} + namespace { /// Base class for a machine scheduler class that can run at any point. @@ -685,9 +693,22 @@ void ScheduleDAGMI::startBlock(MachineBasicBlock *bb) { ScheduleDAGInstrs::startBlock(bb); SchedImpl->enterMBB(bb); + + // If current BB has single pred MBB, forward its scheduled + // state to current MBB. + if (SchedImpl->forwardScheduledState()) { + MachineBasicBlock *PredMBB = SchedImpl->getScheduledPredMBB(bb); + if (PredMBB && SchedImpl->restoreScheduledState(PredMBB)) { + NumFwdSchedState ++; + LLVM_DEBUG(dbgs() << "** Initialize scheduled state from " + << printMBBReference(*PredMBB) << "\n";); + } + } } void ScheduleDAGMI::finishBlock() { + if (SchedImpl->forwardScheduledState()) + SchedImpl->saveScheduledState(BB); SchedImpl->leaveMBB(); ScheduleDAGInstrs::finishBlock(); } Index: llvm/lib/Target/SystemZ/SystemZMachineScheduler.h =================================================================== --- llvm/lib/Target/SystemZ/SystemZMachineScheduler.h +++ llvm/lib/Target/SystemZ/SystemZMachineScheduler.h @@ -132,6 +132,9 @@ /// Tell the strategy that MBB is about to be processed. void enterMBB(MachineBasicBlock *NextMBB) override; + // Copy & continue the scheduler states over scheduling boundaries. + bool forwardScheduledState() const override { return true; } + /// Tell the strategy that current MBB is done. void leaveMBB() override;