summaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/Target/SystemZ/SystemZHazardRecognizer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Target/SystemZ/SystemZHazardRecognizer.cpp')
-rw-r--r--contrib/llvm/lib/Target/SystemZ/SystemZHazardRecognizer.cpp463
1 files changed, 0 insertions, 463 deletions
diff --git a/contrib/llvm/lib/Target/SystemZ/SystemZHazardRecognizer.cpp b/contrib/llvm/lib/Target/SystemZ/SystemZHazardRecognizer.cpp
deleted file mode 100644
index e2af02227999..000000000000
--- a/contrib/llvm/lib/Target/SystemZ/SystemZHazardRecognizer.cpp
+++ /dev/null
@@ -1,463 +0,0 @@
-//=-- SystemZHazardRecognizer.h - SystemZ Hazard Recognizer -----*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines a hazard recognizer for the SystemZ scheduler.
-//
-// This class is used by the SystemZ scheduling strategy to maintain
-// the state during scheduling, and provide cost functions for
-// scheduling candidates. This includes:
-//
-// * Decoder grouping. A decoder group can maximally hold 3 uops, and
-// instructions that always begin a new group should be scheduled when
-// the current decoder group is empty.
-// * Processor resources usage. It is beneficial to balance the use of
-// resources.
-//
-// A goal is to consider all instructions, also those outside of any
-// scheduling region. Such instructions are "advanced" past and include
-// single instructions before a scheduling region, branches etc.
-//
-// A block that has only one predecessor continues scheduling with the state
-// of it (which may be updated by emitting branches).
-//
-// ===---------------------------------------------------------------------===//
-
-#include "SystemZHazardRecognizer.h"
-#include "llvm/ADT/Statistic.h"
-
-using namespace llvm;
-
-#define DEBUG_TYPE "machine-scheduler"
-
-// This is the limit of processor resource usage at which the
-// scheduler should try to look for other instructions (not using the
-// critical resource).
-static cl::opt<int> ProcResCostLim("procres-cost-lim", cl::Hidden,
- cl::desc("The OOO window for processor "
- "resources during scheduling."),
- cl::init(8));
-
-unsigned SystemZHazardRecognizer::
-getNumDecoderSlots(SUnit *SU) const {
- const MCSchedClassDesc *SC = getSchedClass(SU);
- if (!SC->isValid())
- return 0; // IMPLICIT_DEF / KILL -- will not make impact in output.
-
- assert((SC->NumMicroOps != 2 || (SC->BeginGroup && !SC->EndGroup)) &&
- "Only cracked instruction can have 2 uops.");
- assert((SC->NumMicroOps < 3 || (SC->BeginGroup && SC->EndGroup)) &&
- "Expanded instructions always group alone.");
- assert((SC->NumMicroOps < 3 || (SC->NumMicroOps % 3 == 0)) &&
- "Expanded instructions fill the group(s).");
-
- return SC->NumMicroOps;
-}
-
-unsigned SystemZHazardRecognizer::getCurrCycleIdx(SUnit *SU) const {
- unsigned Idx = CurrGroupSize;
- if (GrpCount % 2)
- Idx += 3;
-
- if (SU != nullptr && !fitsIntoCurrentGroup(SU)) {
- if (Idx == 1 || Idx == 2)
- Idx = 3;
- else if (Idx == 4 || Idx == 5)
- Idx = 0;
- }
-
- return Idx;
-}
-
-ScheduleHazardRecognizer::HazardType SystemZHazardRecognizer::
-getHazardType(SUnit *m, int Stalls) {
- return (fitsIntoCurrentGroup(m) ? NoHazard : Hazard);
-}
-
-void SystemZHazardRecognizer::Reset() {
- CurrGroupSize = 0;
- CurrGroupHas4RegOps = false;
- clearProcResCounters();
- GrpCount = 0;
- LastFPdOpCycleIdx = UINT_MAX;
- LastEmittedMI = nullptr;
- LLVM_DEBUG(CurGroupDbg = "";);
-}
-
-bool
-SystemZHazardRecognizer::fitsIntoCurrentGroup(SUnit *SU) const {
- const MCSchedClassDesc *SC = getSchedClass(SU);
- if (!SC->isValid())
- return true;
-
- // A cracked instruction only fits into schedule if the current
- // group is empty.
- if (SC->BeginGroup)
- return (CurrGroupSize == 0);
-
- // An instruction with 4 register operands will not fit in last slot.
- assert ((CurrGroupSize < 2 || !CurrGroupHas4RegOps) &&
- "Current decoder group is already full!");
- if (CurrGroupSize == 2 && has4RegOps(SU->getInstr()))
- return false;
-
- // Since a full group is handled immediately in EmitInstruction(),
- // SU should fit into current group. NumSlots should be 1 or 0,
- // since it is not a cracked or expanded instruction.
- assert ((getNumDecoderSlots(SU) <= 1) && (CurrGroupSize < 3) &&
- "Expected normal instruction to fit in non-full group!");
-
- return true;
-}
-
-bool SystemZHazardRecognizer::has4RegOps(const MachineInstr *MI) const {
- const MachineFunction &MF = *MI->getParent()->getParent();
- const TargetRegisterInfo *TRI = &TII->getRegisterInfo();
- const MCInstrDesc &MID = MI->getDesc();
- unsigned Count = 0;
- for (unsigned OpIdx = 0; OpIdx < MID.getNumOperands(); OpIdx++) {
- const TargetRegisterClass *RC = TII->getRegClass(MID, OpIdx, TRI, MF);
- if (RC == nullptr)
- continue;
- if (OpIdx >= MID.getNumDefs() &&
- MID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)
- continue;
- Count++;
- }
- return Count >= 4;
-}
-
-void SystemZHazardRecognizer::nextGroup() {
- if (CurrGroupSize == 0)
- return;
-
- LLVM_DEBUG(dumpCurrGroup("Completed decode group"));
- LLVM_DEBUG(CurGroupDbg = "";);
-
- int NumGroups = ((CurrGroupSize > 3) ? (CurrGroupSize / 3) : 1);
- assert((CurrGroupSize <= 3 || CurrGroupSize % 3 == 0) &&
- "Current decoder group bad.");
-
- // Reset counter for next group.
- CurrGroupSize = 0;
- CurrGroupHas4RegOps = false;
-
- GrpCount += ((unsigned) NumGroups);
-
- // Decrease counters for execution units.
- for (unsigned i = 0; i < SchedModel->getNumProcResourceKinds(); ++i)
- ProcResourceCounters[i] = ((ProcResourceCounters[i] > NumGroups)
- ? (ProcResourceCounters[i] - NumGroups)
- : 0);
-
- // Clear CriticalResourceIdx if it is now below the threshold.
- if (CriticalResourceIdx != UINT_MAX &&
- (ProcResourceCounters[CriticalResourceIdx] <=
- ProcResCostLim))
- CriticalResourceIdx = UINT_MAX;
-
- LLVM_DEBUG(dumpState(););
-}
-
-#ifndef NDEBUG // Debug output
-void SystemZHazardRecognizer::dumpSU(SUnit *SU, raw_ostream &OS) const {
- OS << "SU(" << SU->NodeNum << "):";
- OS << TII->getName(SU->getInstr()->getOpcode());
-
- const MCSchedClassDesc *SC = getSchedClass(SU);
- if (!SC->isValid())
- return;
-
- for (TargetSchedModel::ProcResIter
- PI = SchedModel->getWriteProcResBegin(SC),
- PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
- const MCProcResourceDesc &PRD =
- *SchedModel->getProcResource(PI->ProcResourceIdx);
- std::string FU(PRD.Name);
- // trim e.g. Z13_FXaUnit -> FXa
- FU = FU.substr(FU.find("_") + 1);
- size_t Pos = FU.find("Unit");
- if (Pos != std::string::npos)
- FU.resize(Pos);
- if (FU == "LS") // LSUnit -> LSU
- FU = "LSU";
- OS << "/" << FU;
-
- if (PI->Cycles > 1)
- OS << "(" << PI->Cycles << "cyc)";
- }
-
- if (SC->NumMicroOps > 1)
- OS << "/" << SC->NumMicroOps << "uops";
- if (SC->BeginGroup && SC->EndGroup)
- OS << "/GroupsAlone";
- else if (SC->BeginGroup)
- OS << "/BeginsGroup";
- else if (SC->EndGroup)
- OS << "/EndsGroup";
- if (SU->isUnbuffered)
- OS << "/Unbuffered";
- if (has4RegOps(SU->getInstr()))
- OS << "/4RegOps";
-}
-
-void SystemZHazardRecognizer::dumpCurrGroup(std::string Msg) const {
- dbgs() << "++ " << Msg;
- dbgs() << ": ";
-
- if (CurGroupDbg.empty())
- dbgs() << " <empty>\n";
- else {
- dbgs() << "{ " << CurGroupDbg << " }";
- dbgs() << " (" << CurrGroupSize << " decoder slot"
- << (CurrGroupSize > 1 ? "s":"")
- << (CurrGroupHas4RegOps ? ", 4RegOps" : "")
- << ")\n";
- }
-}
-
-void SystemZHazardRecognizer::dumpProcResourceCounters() const {
- bool any = false;
-
- for (unsigned i = 0; i < SchedModel->getNumProcResourceKinds(); ++i)
- if (ProcResourceCounters[i] > 0) {
- any = true;
- break;
- }
-
- if (!any)
- return;
-
- dbgs() << "++ | Resource counters: ";
- for (unsigned i = 0; i < SchedModel->getNumProcResourceKinds(); ++i)
- if (ProcResourceCounters[i] > 0)
- dbgs() << SchedModel->getProcResource(i)->Name
- << ":" << ProcResourceCounters[i] << " ";
- dbgs() << "\n";
-
- if (CriticalResourceIdx != UINT_MAX)
- dbgs() << "++ | Critical resource: "
- << SchedModel->getProcResource(CriticalResourceIdx)->Name
- << "\n";
-}
-
-void SystemZHazardRecognizer::dumpState() const {
- dumpCurrGroup("| Current decoder group");
- dbgs() << "++ | Current cycle index: "
- << getCurrCycleIdx() << "\n";
- dumpProcResourceCounters();
- if (LastFPdOpCycleIdx != UINT_MAX)
- dbgs() << "++ | Last FPd cycle index: " << LastFPdOpCycleIdx << "\n";
-}
-
-#endif //NDEBUG
-
-void SystemZHazardRecognizer::clearProcResCounters() {
- ProcResourceCounters.assign(SchedModel->getNumProcResourceKinds(), 0);
- CriticalResourceIdx = UINT_MAX;
-}
-
-static inline bool isBranchRetTrap(MachineInstr *MI) {
- return (MI->isBranch() || MI->isReturn() ||
- MI->getOpcode() == SystemZ::CondTrap);
-}
-
-// Update state with SU as the next scheduled unit.
-void SystemZHazardRecognizer::
-EmitInstruction(SUnit *SU) {
- const MCSchedClassDesc *SC = getSchedClass(SU);
- LLVM_DEBUG(dbgs() << "++ HazardRecognizer emitting "; dumpSU(SU, dbgs());
- dbgs() << "\n";);
- LLVM_DEBUG(dumpCurrGroup("Decode group before emission"););
-
- // If scheduling an SU that must begin a new decoder group, move on
- // to next group.
- if (!fitsIntoCurrentGroup(SU))
- nextGroup();
-
- LLVM_DEBUG(raw_string_ostream cgd(CurGroupDbg);
- if (CurGroupDbg.length()) cgd << ", "; dumpSU(SU, cgd););
-
- LastEmittedMI = SU->getInstr();
-
- // After returning from a call, we don't know much about the state.
- if (SU->isCall) {
- LLVM_DEBUG(dbgs() << "++ Clearing state after call.\n";);
- Reset();
- LastEmittedMI = SU->getInstr();
- return;
- }
-
- // Increase counter for execution unit(s).
- for (TargetSchedModel::ProcResIter
- PI = SchedModel->getWriteProcResBegin(SC),
- PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
- // Don't handle FPd together with the other resources.
- if (SchedModel->getProcResource(PI->ProcResourceIdx)->BufferSize == 1)
- continue;
- int &CurrCounter =
- ProcResourceCounters[PI->ProcResourceIdx];
- CurrCounter += PI->Cycles;
- // Check if this is now the new critical resource.
- if ((CurrCounter > ProcResCostLim) &&
- (CriticalResourceIdx == UINT_MAX ||
- (PI->ProcResourceIdx != CriticalResourceIdx &&
- CurrCounter >
- ProcResourceCounters[CriticalResourceIdx]))) {
- LLVM_DEBUG(
- dbgs() << "++ New critical resource: "
- << SchedModel->getProcResource(PI->ProcResourceIdx)->Name
- << "\n";);
- CriticalResourceIdx = PI->ProcResourceIdx;
- }
- }
-
- // Make note of an instruction that uses a blocking resource (FPd).
- if (SU->isUnbuffered) {
- LastFPdOpCycleIdx = getCurrCycleIdx(SU);
- LLVM_DEBUG(dbgs() << "++ Last FPd cycle index: " << LastFPdOpCycleIdx
- << "\n";);
- }
-
- // Insert SU into current group by increasing number of slots used
- // in current group.
- CurrGroupSize += getNumDecoderSlots(SU);
- CurrGroupHas4RegOps |= has4RegOps(SU->getInstr());
- unsigned GroupLim = (CurrGroupHas4RegOps ? 2 : 3);
- assert((CurrGroupSize <= GroupLim || CurrGroupSize == getNumDecoderSlots(SU))
- && "SU does not fit into decoder group!");
-
- // Check if current group is now full/ended. If so, move on to next
- // group to be ready to evaluate more candidates.
- if (CurrGroupSize >= GroupLim || SC->EndGroup)
- nextGroup();
-}
-
-int SystemZHazardRecognizer::groupingCost(SUnit *SU) const {
- const MCSchedClassDesc *SC = getSchedClass(SU);
- if (!SC->isValid())
- return 0;
-
- // If SU begins new group, it can either break a current group early
- // or fit naturally if current group is empty (negative cost).
- if (SC->BeginGroup) {
- if (CurrGroupSize)
- return 3 - CurrGroupSize;
- return -1;
- }
-
- // Similarly, a group-ending SU may either fit well (last in group), or
- // end the group prematurely.
- if (SC->EndGroup) {
- unsigned resultingGroupSize =
- (CurrGroupSize + getNumDecoderSlots(SU));
- if (resultingGroupSize < 3)
- return (3 - resultingGroupSize);
- return -1;
- }
-
- // An instruction with 4 register operands will not fit in last slot.
- if (CurrGroupSize == 2 && has4RegOps(SU->getInstr()))
- return 1;
-
- // Most instructions can be placed in any decoder slot.
- return 0;
-}
-
-bool SystemZHazardRecognizer::isFPdOpPreferred_distance(SUnit *SU) const {
- assert (SU->isUnbuffered);
- // If this is the first FPd op, it should be scheduled high.
- if (LastFPdOpCycleIdx == UINT_MAX)
- return true;
- // If this is not the first PFd op, it should go into the other side
- // of the processor to use the other FPd unit there. This should
- // generally happen if two FPd ops are placed with 2 other
- // instructions between them (modulo 6).
- unsigned SUCycleIdx = getCurrCycleIdx(SU);
- if (LastFPdOpCycleIdx > SUCycleIdx)
- return ((LastFPdOpCycleIdx - SUCycleIdx) == 3);
- return ((SUCycleIdx - LastFPdOpCycleIdx) == 3);
-}
-
-int SystemZHazardRecognizer::
-resourcesCost(SUnit *SU) {
- int Cost = 0;
-
- const MCSchedClassDesc *SC = getSchedClass(SU);
- if (!SC->isValid())
- return 0;
-
- // For a FPd op, either return min or max value as indicated by the
- // distance to any prior FPd op.
- if (SU->isUnbuffered)
- Cost = (isFPdOpPreferred_distance(SU) ? INT_MIN : INT_MAX);
- // For other instructions, give a cost to the use of the critical resource.
- else if (CriticalResourceIdx != UINT_MAX) {
- for (TargetSchedModel::ProcResIter
- PI = SchedModel->getWriteProcResBegin(SC),
- PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI)
- if (PI->ProcResourceIdx == CriticalResourceIdx)
- Cost = PI->Cycles;
- }
-
- return Cost;
-}
-
-void SystemZHazardRecognizer::emitInstruction(MachineInstr *MI,
- bool TakenBranch) {
- // Make a temporary SUnit.
- SUnit SU(MI, 0);
-
- // Set interesting flags.
- SU.isCall = MI->isCall();
-
- const MCSchedClassDesc *SC = SchedModel->resolveSchedClass(MI);
- for (const MCWriteProcResEntry &PRE :
- make_range(SchedModel->getWriteProcResBegin(SC),
- SchedModel->getWriteProcResEnd(SC))) {
- switch (SchedModel->getProcResource(PRE.ProcResourceIdx)->BufferSize) {
- case 0:
- SU.hasReservedResource = true;
- break;
- case 1:
- SU.isUnbuffered = true;
- break;
- default:
- break;
- }
- }
-
- unsigned GroupSizeBeforeEmit = CurrGroupSize;
- EmitInstruction(&SU);
-
- if (!TakenBranch && isBranchRetTrap(MI)) {
- // NT Branch on second slot ends group.
- if (GroupSizeBeforeEmit == 1)
- nextGroup();
- }
-
- if (TakenBranch && CurrGroupSize > 0)
- nextGroup();
-
- assert ((!MI->isTerminator() || isBranchRetTrap(MI)) &&
- "Scheduler: unhandled terminator!");
-}
-
-void SystemZHazardRecognizer::
-copyState(SystemZHazardRecognizer *Incoming) {
- // Current decoder group
- CurrGroupSize = Incoming->CurrGroupSize;
- LLVM_DEBUG(CurGroupDbg = Incoming->CurGroupDbg;);
-
- // Processor resources
- ProcResourceCounters = Incoming->ProcResourceCounters;
- CriticalResourceIdx = Incoming->CriticalResourceIdx;
-
- // FPd
- LastFPdOpCycleIdx = Incoming->LastFPdOpCycleIdx;
- GrpCount = Incoming->GrpCount;
-}