diff options
Diffstat (limited to 'contrib/llvm/lib/Target/SystemZ/SystemZMachineScheduler.cpp')
-rw-r--r-- | contrib/llvm/lib/Target/SystemZ/SystemZMachineScheduler.cpp | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZMachineScheduler.cpp b/contrib/llvm/lib/Target/SystemZ/SystemZMachineScheduler.cpp new file mode 100644 index 0000000..ab6020f --- /dev/null +++ b/contrib/llvm/lib/Target/SystemZ/SystemZMachineScheduler.cpp @@ -0,0 +1,153 @@ +//-- SystemZMachineScheduler.cpp - SystemZ Scheduler Interface -*- C++ -*---==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// -------------------------- Post RA scheduling ---------------------------- // +// 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. +//===----------------------------------------------------------------------===// + +#include "SystemZMachineScheduler.h" + +using namespace llvm; + +#define DEBUG_TYPE "misched" + +#ifndef NDEBUG +// Print the set of SUs +void SystemZPostRASchedStrategy::SUSet:: +dump(SystemZHazardRecognizer &HazardRec) { + dbgs() << "{"; + for (auto &SU : *this) { + HazardRec.dumpSU(SU, dbgs()); + if (SU != *rbegin()) + dbgs() << ", "; + } + dbgs() << "}\n"; +} +#endif + +SystemZPostRASchedStrategy:: +SystemZPostRASchedStrategy(const MachineSchedContext *C) + : DAG(nullptr), HazardRec(C) {} + +void SystemZPostRASchedStrategy::initialize(ScheduleDAGMI *dag) { + DAG = dag; + HazardRec.setDAG(dag); + HazardRec.Reset(); +} + +// Pick the next node to schedule. +SUnit *SystemZPostRASchedStrategy::pickNode(bool &IsTopNode) { + // Only scheduling top-down. + IsTopNode = true; + + if (Available.empty()) + return nullptr; + + // If only one choice, return it. + if (Available.size() == 1) { + DEBUG (dbgs() << "+++ Only one: "; + 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);); + + Candidate Best; + for (auto *SU : Available) { + + // SU is the next candidate to be compared against current Best. + 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()); + if (Best.GroupingCost != 0) + dbgs() << "\tGrouping cost:" << Best.GroupingCost; + if (Best.ResourcesCost != 0) + dbgs() << " Resource cost:" << Best.ResourcesCost; + dbgs() << " Height:" << Best.SU->getHeight(); + dbgs() << "\n";); + } + + // Once we know we have seen all SUs that affect grouping or use unbuffered + // resources, we can stop iterating if Best looks good. + if (!SU->isScheduleHigh && Best.noCost()) + break; + } + + assert (Best.SU != nullptr); + return Best.SU; +} + +SystemZPostRASchedStrategy::Candidate:: +Candidate(SUnit *SU_, SystemZHazardRecognizer &HazardRec) : Candidate() { + SU = SU_; + + // Check the grouping cost. For a node that must begin / end a + // group, it is positive if it would do so prematurely, or negative + // if it would fit naturally into the schedule. + GroupingCost = HazardRec.groupingCost(SU); + + // Check the resources cost for this SU. + ResourcesCost = HazardRec.resourcesCost(SU); +} + +bool SystemZPostRASchedStrategy::Candidate:: +operator<(const Candidate &other) { + + // Check decoder grouping. + if (GroupingCost < other.GroupingCost) + return true; + if (GroupingCost > other.GroupingCost) + return false; + + // Compare the use of resources. + if (ResourcesCost < other.ResourcesCost) + return true; + if (ResourcesCost > other.ResourcesCost) + return false; + + // Higher SU is otherwise generally better. + if (SU->getHeight() > other.SU->getHeight()) + return true; + if (SU->getHeight() < other.SU->getHeight()) + return false; + + // If all same, fall back to original order. + if (SU->NodeNum < other.SU->NodeNum) + return true; + + return false; +} + +void SystemZPostRASchedStrategy::schedNode(SUnit *SU, bool IsTopNode) { + DEBUG(dbgs() << "+++ Scheduling SU(" << SU->NodeNum << ")\n";); + + // Remove SU from Available set and update HazardRec. + Available.erase(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); + bool AffectsGrouping = (SC->isValid() && (SC->BeginGroup || SC->EndGroup)); + SU->isScheduleHigh = (AffectsGrouping || SU->isUnbuffered); + + // Put all released SUs in the Available set. + Available.insert(SU); +} |