18010b631SJonas Paulsson //-- SystemZMachineScheduler.cpp - SystemZ Scheduler Interface -*- C++ -*---==//
28010b631SJonas Paulsson //
38010b631SJonas Paulsson //                     The LLVM Compiler Infrastructure
48010b631SJonas Paulsson //
58010b631SJonas Paulsson // This file is distributed under the University of Illinois Open Source
68010b631SJonas Paulsson // License. See LICENSE.TXT for details.
78010b631SJonas Paulsson //
88010b631SJonas Paulsson //===----------------------------------------------------------------------===//
98010b631SJonas Paulsson //
108010b631SJonas Paulsson // -------------------------- Post RA scheduling ---------------------------- //
118010b631SJonas Paulsson // SystemZPostRASchedStrategy is a scheduling strategy which is plugged into
128010b631SJonas Paulsson // the MachineScheduler. It has a sorted Available set of SUs and a pickNode()
138010b631SJonas Paulsson // implementation that looks to optimize decoder grouping and balance the
148010b631SJonas Paulsson // usage of processor resources.
158010b631SJonas Paulsson //===----------------------------------------------------------------------===//
168010b631SJonas Paulsson 
178010b631SJonas Paulsson #include "SystemZMachineScheduler.h"
188010b631SJonas Paulsson 
198010b631SJonas Paulsson using namespace llvm;
208010b631SJonas Paulsson 
21*0cd23f56SEvandro Menezes #define DEBUG_TYPE "machine-scheduler"
228010b631SJonas Paulsson 
238010b631SJonas Paulsson #ifndef NDEBUG
248010b631SJonas Paulsson // Print the set of SUs
258010b631SJonas Paulsson void SystemZPostRASchedStrategy::SUSet::
266da25f4fSRafael Espindola dump(SystemZHazardRecognizer &HazardRec) const {
278010b631SJonas Paulsson   dbgs() << "{";
288010b631SJonas Paulsson   for (auto &SU : *this) {
298010b631SJonas Paulsson     HazardRec.dumpSU(SU, dbgs());
308010b631SJonas Paulsson     if (SU != *rbegin())
318010b631SJonas Paulsson       dbgs() << ",  ";
328010b631SJonas Paulsson   }
338010b631SJonas Paulsson   dbgs() << "}\n";
348010b631SJonas Paulsson }
358010b631SJonas Paulsson #endif
368010b631SJonas Paulsson 
378010b631SJonas Paulsson SystemZPostRASchedStrategy::
388010b631SJonas Paulsson SystemZPostRASchedStrategy(const MachineSchedContext *C)
398010b631SJonas Paulsson   : DAG(nullptr), HazardRec(C) {}
408010b631SJonas Paulsson 
418010b631SJonas Paulsson void SystemZPostRASchedStrategy::initialize(ScheduleDAGMI *dag) {
428010b631SJonas Paulsson   DAG = dag;
438010b631SJonas Paulsson   HazardRec.setDAG(dag);
448010b631SJonas Paulsson   HazardRec.Reset();
458010b631SJonas Paulsson }
468010b631SJonas Paulsson 
478010b631SJonas Paulsson // Pick the next node to schedule.
488010b631SJonas Paulsson SUnit *SystemZPostRASchedStrategy::pickNode(bool &IsTopNode) {
498010b631SJonas Paulsson   // Only scheduling top-down.
508010b631SJonas Paulsson   IsTopNode = true;
518010b631SJonas Paulsson 
528010b631SJonas Paulsson   if (Available.empty())
538010b631SJonas Paulsson     return nullptr;
548010b631SJonas Paulsson 
558010b631SJonas Paulsson   // If only one choice, return it.
568010b631SJonas Paulsson   if (Available.size() == 1) {
578010b631SJonas Paulsson     DEBUG (dbgs() << "+++ Only one: ";
588010b631SJonas Paulsson            HazardRec.dumpSU(*Available.begin(), dbgs()); dbgs() << "\n";);
598010b631SJonas Paulsson     return *Available.begin();
608010b631SJonas Paulsson   }
618010b631SJonas Paulsson 
628010b631SJonas Paulsson   // All nodes that are possible to schedule are stored by in the
638010b631SJonas Paulsson   // Available set.
648010b631SJonas Paulsson   DEBUG(dbgs() << "+++ Available: "; Available.dump(HazardRec););
658010b631SJonas Paulsson 
668010b631SJonas Paulsson   Candidate Best;
678010b631SJonas Paulsson   for (auto *SU : Available) {
688010b631SJonas Paulsson 
698010b631SJonas Paulsson     // SU is the next candidate to be compared against current Best.
708010b631SJonas Paulsson     Candidate c(SU, HazardRec);
718010b631SJonas Paulsson 
728010b631SJonas Paulsson     // Remeber which SU is the best candidate.
738010b631SJonas Paulsson     if (Best.SU == nullptr || c < Best) {
748010b631SJonas Paulsson       Best = c;
758010b631SJonas Paulsson       DEBUG(dbgs() << "+++ Best sofar: ";
768010b631SJonas Paulsson             HazardRec.dumpSU(Best.SU, dbgs());
778010b631SJonas Paulsson             if (Best.GroupingCost != 0)
788010b631SJonas Paulsson               dbgs() << "\tGrouping cost:" << Best.GroupingCost;
798010b631SJonas Paulsson             if (Best.ResourcesCost != 0)
808010b631SJonas Paulsson               dbgs() << " Resource cost:" << Best.ResourcesCost;
818010b631SJonas Paulsson             dbgs() << " Height:" << Best.SU->getHeight();
828010b631SJonas Paulsson             dbgs() << "\n";);
838010b631SJonas Paulsson     }
848010b631SJonas Paulsson 
858010b631SJonas Paulsson     // Once we know we have seen all SUs that affect grouping or use unbuffered
868010b631SJonas Paulsson     // resources, we can stop iterating if Best looks good.
878010b631SJonas Paulsson     if (!SU->isScheduleHigh && Best.noCost())
888010b631SJonas Paulsson       break;
898010b631SJonas Paulsson   }
908010b631SJonas Paulsson 
918010b631SJonas Paulsson   assert (Best.SU != nullptr);
928010b631SJonas Paulsson   return Best.SU;
938010b631SJonas Paulsson }
948010b631SJonas Paulsson 
958010b631SJonas Paulsson SystemZPostRASchedStrategy::Candidate::
968010b631SJonas Paulsson Candidate(SUnit *SU_, SystemZHazardRecognizer &HazardRec) : Candidate() {
978010b631SJonas Paulsson   SU = SU_;
988010b631SJonas Paulsson 
998010b631SJonas Paulsson   // Check the grouping cost. For a node that must begin / end a
1008010b631SJonas Paulsson   // group, it is positive if it would do so prematurely, or negative
1018010b631SJonas Paulsson   // if it would fit naturally into the schedule.
1028010b631SJonas Paulsson   GroupingCost = HazardRec.groupingCost(SU);
1038010b631SJonas Paulsson 
1048010b631SJonas Paulsson     // Check the resources cost for this SU.
1058010b631SJonas Paulsson   ResourcesCost = HazardRec.resourcesCost(SU);
1068010b631SJonas Paulsson }
1078010b631SJonas Paulsson 
1088010b631SJonas Paulsson bool SystemZPostRASchedStrategy::Candidate::
1098010b631SJonas Paulsson operator<(const Candidate &other) {
1108010b631SJonas Paulsson 
1118010b631SJonas Paulsson   // Check decoder grouping.
1128010b631SJonas Paulsson   if (GroupingCost < other.GroupingCost)
1138010b631SJonas Paulsson     return true;
1148010b631SJonas Paulsson   if (GroupingCost > other.GroupingCost)
1158010b631SJonas Paulsson     return false;
1168010b631SJonas Paulsson 
1178010b631SJonas Paulsson   // Compare the use of resources.
1188010b631SJonas Paulsson   if (ResourcesCost < other.ResourcesCost)
1198010b631SJonas Paulsson     return true;
1208010b631SJonas Paulsson   if (ResourcesCost > other.ResourcesCost)
1218010b631SJonas Paulsson     return false;
1228010b631SJonas Paulsson 
1238010b631SJonas Paulsson   // Higher SU is otherwise generally better.
1248010b631SJonas Paulsson   if (SU->getHeight() > other.SU->getHeight())
1258010b631SJonas Paulsson     return true;
1268010b631SJonas Paulsson   if (SU->getHeight() < other.SU->getHeight())
1278010b631SJonas Paulsson     return false;
1288010b631SJonas Paulsson 
1298010b631SJonas Paulsson   // If all same, fall back to original order.
1308010b631SJonas Paulsson   if (SU->NodeNum < other.SU->NodeNum)
1318010b631SJonas Paulsson     return true;
1328010b631SJonas Paulsson 
1338010b631SJonas Paulsson   return false;
1348010b631SJonas Paulsson }
1358010b631SJonas Paulsson 
1368010b631SJonas Paulsson void SystemZPostRASchedStrategy::schedNode(SUnit *SU, bool IsTopNode) {
1378010b631SJonas Paulsson   DEBUG(dbgs() << "+++ Scheduling SU(" << SU->NodeNum << ")\n";);
1388010b631SJonas Paulsson 
1398010b631SJonas Paulsson   // Remove SU from Available set and update HazardRec.
1408010b631SJonas Paulsson   Available.erase(SU);
1418010b631SJonas Paulsson   HazardRec.EmitInstruction(SU);
1428010b631SJonas Paulsson }
1438010b631SJonas Paulsson 
1448010b631SJonas Paulsson void SystemZPostRASchedStrategy::releaseTopNode(SUnit *SU) {
1458010b631SJonas Paulsson   // Set isScheduleHigh flag on all SUs that we want to consider first in
1468010b631SJonas Paulsson   // pickNode().
1478010b631SJonas Paulsson   const MCSchedClassDesc *SC = DAG->getSchedClass(SU);
1488010b631SJonas Paulsson   bool AffectsGrouping = (SC->isValid() && (SC->BeginGroup || SC->EndGroup));
1498010b631SJonas Paulsson   SU->isScheduleHigh = (AffectsGrouping || SU->isUnbuffered);
1508010b631SJonas Paulsson 
1518010b631SJonas Paulsson   // Put all released SUs in the Available set.
1528010b631SJonas Paulsson   Available.insert(SU);
1538010b631SJonas Paulsson }
154