Expand Up
@@ -11,7 +11,8 @@
// SystemZPostRASchedStrategy is a scheduling strategy which is plugged into
// the MachineScheduler. It has a sorted Available set of SUs and a pickNode()
// implementation that looks to optimize decoder grouping and balance the
// usage of processor resources.
// usage of processor resources. Scheduler states are saved for the end
// region of each MBB, so that a successor block can learn from it.
// ===----------------------------------------------------------------------===//
#include " SystemZMachineScheduler.h"
Expand All
@@ -34,14 +35,118 @@ dump(SystemZHazardRecognizer &HazardRec) const {
}
#endif
// 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 ();
// The loop header has two predecessors, return the latch, but not for a
// single block loop.
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))
PredMBB = (*I == MBB ? nullptr : *I);
}
assert ((PredMBB == nullptr || !Loop || Loop->contains (PredMBB))
&& " Loop MBB should not consider predecessor outside of loop." );
return PredMBB;
}
void SystemZPostRASchedStrategy::
advanceTo (MachineBasicBlock::iterator NextBegin) {
MachineBasicBlock::iterator LastEmittedMI = HazardRec->getLastEmittedMI ();
MachineBasicBlock::iterator I =
((LastEmittedMI != nullptr && LastEmittedMI->getParent () == MBB) ?
std::next (LastEmittedMI) : MBB->begin ());
for (; I != NextBegin; ++I) {
if (I->isPosition () || I->isDebugValue ())
continue ;
HazardRec->emitInstruction (&*I);
}
}
void SystemZPostRASchedStrategy::enterMBB (MachineBasicBlock *NextMBB) {
assert ((SchedStates.find (NextMBB) == SchedStates.end ()) &&
" Entering MBB twice?" );
DEBUG (dbgs () << " +++ Entering MBB#" << NextMBB->getNumber ());
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);
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 ;
DEBUG (dbgs () << " +++ Continued scheduling from MBB#"
<< SinglePredMBB->getNumber () << " \n " ;);
HazardRec->copyState (SchedStates[SinglePredMBB]);
// 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++) {
DEBUG (dbgs () << " +++ Emitting incoming branch: " ; I->dump (););
bool TakenBranch = (I->isBranch () &&
(TII->getBranchInfo (*I).Target ->isReg () || // Relative branch
TII->getBranchInfo (*I).Target ->getMBB () == MBB));
HazardRec->emitInstruction (&*I, TakenBranch);
if (TakenBranch)
break ;
}
}
void SystemZPostRASchedStrategy::leaveMBB () {
DEBUG (dbgs () << " +++ Leaving MBB#" << MBB->getNumber () << " \n " ;);
// Advance to first terminator. The successor block will handle terminators
// dependent on CFG layout (T/NT branch etc).
advanceTo (MBB->getFirstTerminator ());
}
SystemZPostRASchedStrategy::
SystemZPostRASchedStrategy (const MachineSchedContext *C)
: DAG(nullptr ), HazardRec(C) {}
: MLI(C->MLI),
TII(static_cast <const SystemZInstrInfo *>
(C->MF->getSubtarget ().getInstrInfo())),
MBB(nullptr ), HazardRec(nullptr ) {
const TargetSubtargetInfo *ST = &C->MF ->getSubtarget ();
SchedModel.init (ST->getSchedModel (), ST, TII);
}
SystemZPostRASchedStrategy::~SystemZPostRASchedStrategy () {
// Delete hazard recognizers kept around for each MBB.
for (auto I : SchedStates) {
SystemZHazardRecognizer *hazrec = I.second ;
delete hazrec;
}
}
void SystemZPostRASchedStrategy::initPolicy (MachineBasicBlock::iterator Begin,
MachineBasicBlock::iterator End,
unsigned NumRegionInstrs) {
// Don't emit the terminators.
if (Begin->isTerminator ())
return ;
void SystemZPostRASchedStrategy::initialize (ScheduleDAGMI *dag) {
DAG = dag;
HazardRec.setDAG (dag);
HazardRec.Reset ();
// Emit any instructions before start of region.
advanceTo (Begin);
}
// Pick the next node to schedule.
Expand All
@@ -55,25 +160,25 @@ SUnit *SystemZPostRASchedStrategy::pickNode(bool &IsTopNode) {
// If only one choice, return it.
if (Available.size () == 1 ) {
DEBUG (dbgs () << " +++ Only one: " ;
HazardRec. dumpSU (*Available.begin (), dbgs ()); dbgs () << " \n " ;);
HazardRec-> dumpSU (*Available.begin (), dbgs ()); dbgs () << " \n " ;);
return *Available.begin ();
}
// All nodes that are possible to schedule are stored by in the
// Available set.
DEBUG (dbgs () << " +++ Available: " ; Available.dump (HazardRec););
DEBUG (dbgs () << " +++ Available: " ; Available.dump (* HazardRec););
Candidate Best;
for (auto *SU : Available) {
// SU is the next candidate to be compared against current Best.
Candidate c (SU, HazardRec);
Candidate c (SU, * HazardRec);
// Remeber which SU is the best candidate.
if (Best.SU == nullptr || c < Best) {
Best = c;
DEBUG (dbgs () << " +++ Best sofar: " ;
HazardRec. dumpSU (Best.SU , dbgs ());
HazardRec-> dumpSU (Best.SU , dbgs ());
if (Best.GroupingCost != 0 )
dbgs () << " \t Grouping cost:" << Best.GroupingCost ;
if (Best.ResourcesCost != 0 )
Expand Down
Expand Up
@@ -138,13 +243,13 @@ void SystemZPostRASchedStrategy::schedNode(SUnit *SU, bool IsTopNode) {
// Remove SU from Available set and update HazardRec.
Available.erase (SU);
HazardRec. EmitInstruction (SU);
HazardRec-> EmitInstruction (SU);
}
void SystemZPostRASchedStrategy::releaseTopNode (SUnit *SU) {
// Set isScheduleHigh flag on all SUs that we want to consider first in
// pickNode().
const MCSchedClassDesc *SC = DAG ->getSchedClass (SU);
const MCSchedClassDesc *SC = HazardRec ->getSchedClass (SU);
bool AffectsGrouping = (SC->isValid () && (SC->BeginGroup || SC->EndGroup ));
SU->isScheduleHigh = (AffectsGrouping || SU->isUnbuffered );
Expand Down