109467b48Spatrick //=-- SystemZHazardRecognizer.h - SystemZ Hazard Recognizer -----*- C++ -*-===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file defines a hazard recognizer for the SystemZ scheduler.
1009467b48Spatrick //
1109467b48Spatrick // This class is used by the SystemZ scheduling strategy to maintain
1209467b48Spatrick // the state during scheduling, and provide cost functions for
1309467b48Spatrick // scheduling candidates. This includes:
1409467b48Spatrick //
1509467b48Spatrick // * Decoder grouping. A decoder group can maximally hold 3 uops, and
1609467b48Spatrick // instructions that always begin a new group should be scheduled when
1709467b48Spatrick // the current decoder group is empty.
1809467b48Spatrick // * Processor resources usage. It is beneficial to balance the use of
1909467b48Spatrick // resources.
2009467b48Spatrick //
2109467b48Spatrick // A goal is to consider all instructions, also those outside of any
2209467b48Spatrick // scheduling region. Such instructions are "advanced" past and include
2309467b48Spatrick // single instructions before a scheduling region, branches etc.
2409467b48Spatrick //
2509467b48Spatrick // A block that has only one predecessor continues scheduling with the state
2609467b48Spatrick // of it (which may be updated by emitting branches).
2709467b48Spatrick //
2809467b48Spatrick // ===---------------------------------------------------------------------===//
2909467b48Spatrick
3009467b48Spatrick #include "SystemZHazardRecognizer.h"
3109467b48Spatrick #include "llvm/ADT/Statistic.h"
3209467b48Spatrick
3309467b48Spatrick using namespace llvm;
3409467b48Spatrick
3509467b48Spatrick #define DEBUG_TYPE "machine-scheduler"
3609467b48Spatrick
3709467b48Spatrick // This is the limit of processor resource usage at which the
3809467b48Spatrick // scheduler should try to look for other instructions (not using the
3909467b48Spatrick // critical resource).
4009467b48Spatrick static cl::opt<int> ProcResCostLim("procres-cost-lim", cl::Hidden,
4109467b48Spatrick cl::desc("The OOO window for processor "
4209467b48Spatrick "resources during scheduling."),
4309467b48Spatrick cl::init(8));
4409467b48Spatrick
4509467b48Spatrick unsigned SystemZHazardRecognizer::
getNumDecoderSlots(SUnit * SU) const4609467b48Spatrick getNumDecoderSlots(SUnit *SU) const {
4709467b48Spatrick const MCSchedClassDesc *SC = getSchedClass(SU);
4809467b48Spatrick if (!SC->isValid())
4909467b48Spatrick return 0; // IMPLICIT_DEF / KILL -- will not make impact in output.
5009467b48Spatrick
5109467b48Spatrick assert((SC->NumMicroOps != 2 || (SC->BeginGroup && !SC->EndGroup)) &&
5209467b48Spatrick "Only cracked instruction can have 2 uops.");
5309467b48Spatrick assert((SC->NumMicroOps < 3 || (SC->BeginGroup && SC->EndGroup)) &&
5409467b48Spatrick "Expanded instructions always group alone.");
5509467b48Spatrick assert((SC->NumMicroOps < 3 || (SC->NumMicroOps % 3 == 0)) &&
5609467b48Spatrick "Expanded instructions fill the group(s).");
5709467b48Spatrick
5809467b48Spatrick return SC->NumMicroOps;
5909467b48Spatrick }
6009467b48Spatrick
getCurrCycleIdx(SUnit * SU) const6109467b48Spatrick unsigned SystemZHazardRecognizer::getCurrCycleIdx(SUnit *SU) const {
6209467b48Spatrick unsigned Idx = CurrGroupSize;
6309467b48Spatrick if (GrpCount % 2)
6409467b48Spatrick Idx += 3;
6509467b48Spatrick
6609467b48Spatrick if (SU != nullptr && !fitsIntoCurrentGroup(SU)) {
6709467b48Spatrick if (Idx == 1 || Idx == 2)
6809467b48Spatrick Idx = 3;
6909467b48Spatrick else if (Idx == 4 || Idx == 5)
7009467b48Spatrick Idx = 0;
7109467b48Spatrick }
7209467b48Spatrick
7309467b48Spatrick return Idx;
7409467b48Spatrick }
7509467b48Spatrick
7609467b48Spatrick ScheduleHazardRecognizer::HazardType SystemZHazardRecognizer::
getHazardType(SUnit * SU,int Stalls)77*73471bf0Spatrick getHazardType(SUnit *SU, int Stalls) {
78*73471bf0Spatrick return (fitsIntoCurrentGroup(SU) ? NoHazard : Hazard);
7909467b48Spatrick }
8009467b48Spatrick
Reset()8109467b48Spatrick void SystemZHazardRecognizer::Reset() {
8209467b48Spatrick CurrGroupSize = 0;
8309467b48Spatrick CurrGroupHas4RegOps = false;
8409467b48Spatrick clearProcResCounters();
8509467b48Spatrick GrpCount = 0;
8609467b48Spatrick LastFPdOpCycleIdx = UINT_MAX;
8709467b48Spatrick LastEmittedMI = nullptr;
8809467b48Spatrick LLVM_DEBUG(CurGroupDbg = "";);
8909467b48Spatrick }
9009467b48Spatrick
9109467b48Spatrick bool
fitsIntoCurrentGroup(SUnit * SU) const9209467b48Spatrick SystemZHazardRecognizer::fitsIntoCurrentGroup(SUnit *SU) const {
9309467b48Spatrick const MCSchedClassDesc *SC = getSchedClass(SU);
9409467b48Spatrick if (!SC->isValid())
9509467b48Spatrick return true;
9609467b48Spatrick
9709467b48Spatrick // A cracked instruction only fits into schedule if the current
9809467b48Spatrick // group is empty.
9909467b48Spatrick if (SC->BeginGroup)
10009467b48Spatrick return (CurrGroupSize == 0);
10109467b48Spatrick
10209467b48Spatrick // An instruction with 4 register operands will not fit in last slot.
10309467b48Spatrick assert ((CurrGroupSize < 2 || !CurrGroupHas4RegOps) &&
10409467b48Spatrick "Current decoder group is already full!");
10509467b48Spatrick if (CurrGroupSize == 2 && has4RegOps(SU->getInstr()))
10609467b48Spatrick return false;
10709467b48Spatrick
10809467b48Spatrick // Since a full group is handled immediately in EmitInstruction(),
10909467b48Spatrick // SU should fit into current group. NumSlots should be 1 or 0,
11009467b48Spatrick // since it is not a cracked or expanded instruction.
11109467b48Spatrick assert ((getNumDecoderSlots(SU) <= 1) && (CurrGroupSize < 3) &&
11209467b48Spatrick "Expected normal instruction to fit in non-full group!");
11309467b48Spatrick
11409467b48Spatrick return true;
11509467b48Spatrick }
11609467b48Spatrick
has4RegOps(const MachineInstr * MI) const11709467b48Spatrick bool SystemZHazardRecognizer::has4RegOps(const MachineInstr *MI) const {
11809467b48Spatrick const MachineFunction &MF = *MI->getParent()->getParent();
11909467b48Spatrick const TargetRegisterInfo *TRI = &TII->getRegisterInfo();
12009467b48Spatrick const MCInstrDesc &MID = MI->getDesc();
12109467b48Spatrick unsigned Count = 0;
12209467b48Spatrick for (unsigned OpIdx = 0; OpIdx < MID.getNumOperands(); OpIdx++) {
12309467b48Spatrick const TargetRegisterClass *RC = TII->getRegClass(MID, OpIdx, TRI, MF);
12409467b48Spatrick if (RC == nullptr)
12509467b48Spatrick continue;
12609467b48Spatrick if (OpIdx >= MID.getNumDefs() &&
12709467b48Spatrick MID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)
12809467b48Spatrick continue;
12909467b48Spatrick Count++;
13009467b48Spatrick }
13109467b48Spatrick return Count >= 4;
13209467b48Spatrick }
13309467b48Spatrick
nextGroup()13409467b48Spatrick void SystemZHazardRecognizer::nextGroup() {
13509467b48Spatrick if (CurrGroupSize == 0)
13609467b48Spatrick return;
13709467b48Spatrick
13809467b48Spatrick LLVM_DEBUG(dumpCurrGroup("Completed decode group"));
13909467b48Spatrick LLVM_DEBUG(CurGroupDbg = "";);
14009467b48Spatrick
14109467b48Spatrick int NumGroups = ((CurrGroupSize > 3) ? (CurrGroupSize / 3) : 1);
14209467b48Spatrick assert((CurrGroupSize <= 3 || CurrGroupSize % 3 == 0) &&
14309467b48Spatrick "Current decoder group bad.");
14409467b48Spatrick
14509467b48Spatrick // Reset counter for next group.
14609467b48Spatrick CurrGroupSize = 0;
14709467b48Spatrick CurrGroupHas4RegOps = false;
14809467b48Spatrick
14909467b48Spatrick GrpCount += ((unsigned) NumGroups);
15009467b48Spatrick
15109467b48Spatrick // Decrease counters for execution units.
15209467b48Spatrick for (unsigned i = 0; i < SchedModel->getNumProcResourceKinds(); ++i)
15309467b48Spatrick ProcResourceCounters[i] = ((ProcResourceCounters[i] > NumGroups)
15409467b48Spatrick ? (ProcResourceCounters[i] - NumGroups)
15509467b48Spatrick : 0);
15609467b48Spatrick
15709467b48Spatrick // Clear CriticalResourceIdx if it is now below the threshold.
15809467b48Spatrick if (CriticalResourceIdx != UINT_MAX &&
15909467b48Spatrick (ProcResourceCounters[CriticalResourceIdx] <=
16009467b48Spatrick ProcResCostLim))
16109467b48Spatrick CriticalResourceIdx = UINT_MAX;
16209467b48Spatrick
16309467b48Spatrick LLVM_DEBUG(dumpState(););
16409467b48Spatrick }
16509467b48Spatrick
16609467b48Spatrick #ifndef NDEBUG // Debug output
dumpSU(SUnit * SU,raw_ostream & OS) const16709467b48Spatrick void SystemZHazardRecognizer::dumpSU(SUnit *SU, raw_ostream &OS) const {
16809467b48Spatrick OS << "SU(" << SU->NodeNum << "):";
16909467b48Spatrick OS << TII->getName(SU->getInstr()->getOpcode());
17009467b48Spatrick
17109467b48Spatrick const MCSchedClassDesc *SC = getSchedClass(SU);
17209467b48Spatrick if (!SC->isValid())
17309467b48Spatrick return;
17409467b48Spatrick
17509467b48Spatrick for (TargetSchedModel::ProcResIter
17609467b48Spatrick PI = SchedModel->getWriteProcResBegin(SC),
17709467b48Spatrick PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
17809467b48Spatrick const MCProcResourceDesc &PRD =
17909467b48Spatrick *SchedModel->getProcResource(PI->ProcResourceIdx);
18009467b48Spatrick std::string FU(PRD.Name);
18109467b48Spatrick // trim e.g. Z13_FXaUnit -> FXa
182*73471bf0Spatrick FU = FU.substr(FU.find('_') + 1);
18309467b48Spatrick size_t Pos = FU.find("Unit");
18409467b48Spatrick if (Pos != std::string::npos)
18509467b48Spatrick FU.resize(Pos);
18609467b48Spatrick if (FU == "LS") // LSUnit -> LSU
18709467b48Spatrick FU = "LSU";
18809467b48Spatrick OS << "/" << FU;
18909467b48Spatrick
19009467b48Spatrick if (PI->Cycles > 1)
19109467b48Spatrick OS << "(" << PI->Cycles << "cyc)";
19209467b48Spatrick }
19309467b48Spatrick
19409467b48Spatrick if (SC->NumMicroOps > 1)
19509467b48Spatrick OS << "/" << SC->NumMicroOps << "uops";
19609467b48Spatrick if (SC->BeginGroup && SC->EndGroup)
19709467b48Spatrick OS << "/GroupsAlone";
19809467b48Spatrick else if (SC->BeginGroup)
19909467b48Spatrick OS << "/BeginsGroup";
20009467b48Spatrick else if (SC->EndGroup)
20109467b48Spatrick OS << "/EndsGroup";
20209467b48Spatrick if (SU->isUnbuffered)
20309467b48Spatrick OS << "/Unbuffered";
20409467b48Spatrick if (has4RegOps(SU->getInstr()))
20509467b48Spatrick OS << "/4RegOps";
20609467b48Spatrick }
20709467b48Spatrick
dumpCurrGroup(std::string Msg) const20809467b48Spatrick void SystemZHazardRecognizer::dumpCurrGroup(std::string Msg) const {
20909467b48Spatrick dbgs() << "++ " << Msg;
21009467b48Spatrick dbgs() << ": ";
21109467b48Spatrick
21209467b48Spatrick if (CurGroupDbg.empty())
21309467b48Spatrick dbgs() << " <empty>\n";
21409467b48Spatrick else {
21509467b48Spatrick dbgs() << "{ " << CurGroupDbg << " }";
21609467b48Spatrick dbgs() << " (" << CurrGroupSize << " decoder slot"
21709467b48Spatrick << (CurrGroupSize > 1 ? "s":"")
21809467b48Spatrick << (CurrGroupHas4RegOps ? ", 4RegOps" : "")
21909467b48Spatrick << ")\n";
22009467b48Spatrick }
22109467b48Spatrick }
22209467b48Spatrick
dumpProcResourceCounters() const22309467b48Spatrick void SystemZHazardRecognizer::dumpProcResourceCounters() const {
22409467b48Spatrick bool any = false;
22509467b48Spatrick
22609467b48Spatrick for (unsigned i = 0; i < SchedModel->getNumProcResourceKinds(); ++i)
22709467b48Spatrick if (ProcResourceCounters[i] > 0) {
22809467b48Spatrick any = true;
22909467b48Spatrick break;
23009467b48Spatrick }
23109467b48Spatrick
23209467b48Spatrick if (!any)
23309467b48Spatrick return;
23409467b48Spatrick
23509467b48Spatrick dbgs() << "++ | Resource counters: ";
23609467b48Spatrick for (unsigned i = 0; i < SchedModel->getNumProcResourceKinds(); ++i)
23709467b48Spatrick if (ProcResourceCounters[i] > 0)
23809467b48Spatrick dbgs() << SchedModel->getProcResource(i)->Name
23909467b48Spatrick << ":" << ProcResourceCounters[i] << " ";
24009467b48Spatrick dbgs() << "\n";
24109467b48Spatrick
24209467b48Spatrick if (CriticalResourceIdx != UINT_MAX)
24309467b48Spatrick dbgs() << "++ | Critical resource: "
24409467b48Spatrick << SchedModel->getProcResource(CriticalResourceIdx)->Name
24509467b48Spatrick << "\n";
24609467b48Spatrick }
24709467b48Spatrick
dumpState() const24809467b48Spatrick void SystemZHazardRecognizer::dumpState() const {
24909467b48Spatrick dumpCurrGroup("| Current decoder group");
25009467b48Spatrick dbgs() << "++ | Current cycle index: "
25109467b48Spatrick << getCurrCycleIdx() << "\n";
25209467b48Spatrick dumpProcResourceCounters();
25309467b48Spatrick if (LastFPdOpCycleIdx != UINT_MAX)
25409467b48Spatrick dbgs() << "++ | Last FPd cycle index: " << LastFPdOpCycleIdx << "\n";
25509467b48Spatrick }
25609467b48Spatrick
25709467b48Spatrick #endif //NDEBUG
25809467b48Spatrick
clearProcResCounters()25909467b48Spatrick void SystemZHazardRecognizer::clearProcResCounters() {
26009467b48Spatrick ProcResourceCounters.assign(SchedModel->getNumProcResourceKinds(), 0);
26109467b48Spatrick CriticalResourceIdx = UINT_MAX;
26209467b48Spatrick }
26309467b48Spatrick
isBranchRetTrap(MachineInstr * MI)26409467b48Spatrick static inline bool isBranchRetTrap(MachineInstr *MI) {
26509467b48Spatrick return (MI->isBranch() || MI->isReturn() ||
26609467b48Spatrick MI->getOpcode() == SystemZ::CondTrap);
26709467b48Spatrick }
26809467b48Spatrick
26909467b48Spatrick // Update state with SU as the next scheduled unit.
27009467b48Spatrick void SystemZHazardRecognizer::
EmitInstruction(SUnit * SU)27109467b48Spatrick EmitInstruction(SUnit *SU) {
27209467b48Spatrick const MCSchedClassDesc *SC = getSchedClass(SU);
27309467b48Spatrick LLVM_DEBUG(dbgs() << "++ HazardRecognizer emitting "; dumpSU(SU, dbgs());
27409467b48Spatrick dbgs() << "\n";);
27509467b48Spatrick LLVM_DEBUG(dumpCurrGroup("Decode group before emission"););
27609467b48Spatrick
27709467b48Spatrick // If scheduling an SU that must begin a new decoder group, move on
27809467b48Spatrick // to next group.
27909467b48Spatrick if (!fitsIntoCurrentGroup(SU))
28009467b48Spatrick nextGroup();
28109467b48Spatrick
28209467b48Spatrick LLVM_DEBUG(raw_string_ostream cgd(CurGroupDbg);
28309467b48Spatrick if (CurGroupDbg.length()) cgd << ", "; dumpSU(SU, cgd););
28409467b48Spatrick
28509467b48Spatrick LastEmittedMI = SU->getInstr();
28609467b48Spatrick
28709467b48Spatrick // After returning from a call, we don't know much about the state.
28809467b48Spatrick if (SU->isCall) {
28909467b48Spatrick LLVM_DEBUG(dbgs() << "++ Clearing state after call.\n";);
29009467b48Spatrick Reset();
29109467b48Spatrick LastEmittedMI = SU->getInstr();
29209467b48Spatrick return;
29309467b48Spatrick }
29409467b48Spatrick
29509467b48Spatrick // Increase counter for execution unit(s).
29609467b48Spatrick for (TargetSchedModel::ProcResIter
29709467b48Spatrick PI = SchedModel->getWriteProcResBegin(SC),
29809467b48Spatrick PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
29909467b48Spatrick // Don't handle FPd together with the other resources.
30009467b48Spatrick if (SchedModel->getProcResource(PI->ProcResourceIdx)->BufferSize == 1)
30109467b48Spatrick continue;
30209467b48Spatrick int &CurrCounter =
30309467b48Spatrick ProcResourceCounters[PI->ProcResourceIdx];
30409467b48Spatrick CurrCounter += PI->Cycles;
30509467b48Spatrick // Check if this is now the new critical resource.
30609467b48Spatrick if ((CurrCounter > ProcResCostLim) &&
30709467b48Spatrick (CriticalResourceIdx == UINT_MAX ||
30809467b48Spatrick (PI->ProcResourceIdx != CriticalResourceIdx &&
30909467b48Spatrick CurrCounter >
31009467b48Spatrick ProcResourceCounters[CriticalResourceIdx]))) {
31109467b48Spatrick LLVM_DEBUG(
31209467b48Spatrick dbgs() << "++ New critical resource: "
31309467b48Spatrick << SchedModel->getProcResource(PI->ProcResourceIdx)->Name
31409467b48Spatrick << "\n";);
31509467b48Spatrick CriticalResourceIdx = PI->ProcResourceIdx;
31609467b48Spatrick }
31709467b48Spatrick }
31809467b48Spatrick
31909467b48Spatrick // Make note of an instruction that uses a blocking resource (FPd).
32009467b48Spatrick if (SU->isUnbuffered) {
32109467b48Spatrick LastFPdOpCycleIdx = getCurrCycleIdx(SU);
32209467b48Spatrick LLVM_DEBUG(dbgs() << "++ Last FPd cycle index: " << LastFPdOpCycleIdx
32309467b48Spatrick << "\n";);
32409467b48Spatrick }
32509467b48Spatrick
32609467b48Spatrick // Insert SU into current group by increasing number of slots used
32709467b48Spatrick // in current group.
32809467b48Spatrick CurrGroupSize += getNumDecoderSlots(SU);
32909467b48Spatrick CurrGroupHas4RegOps |= has4RegOps(SU->getInstr());
33009467b48Spatrick unsigned GroupLim = (CurrGroupHas4RegOps ? 2 : 3);
33109467b48Spatrick assert((CurrGroupSize <= GroupLim || CurrGroupSize == getNumDecoderSlots(SU))
33209467b48Spatrick && "SU does not fit into decoder group!");
33309467b48Spatrick
33409467b48Spatrick // Check if current group is now full/ended. If so, move on to next
33509467b48Spatrick // group to be ready to evaluate more candidates.
33609467b48Spatrick if (CurrGroupSize >= GroupLim || SC->EndGroup)
33709467b48Spatrick nextGroup();
33809467b48Spatrick }
33909467b48Spatrick
groupingCost(SUnit * SU) const34009467b48Spatrick int SystemZHazardRecognizer::groupingCost(SUnit *SU) const {
34109467b48Spatrick const MCSchedClassDesc *SC = getSchedClass(SU);
34209467b48Spatrick if (!SC->isValid())
34309467b48Spatrick return 0;
34409467b48Spatrick
34509467b48Spatrick // If SU begins new group, it can either break a current group early
34609467b48Spatrick // or fit naturally if current group is empty (negative cost).
34709467b48Spatrick if (SC->BeginGroup) {
34809467b48Spatrick if (CurrGroupSize)
34909467b48Spatrick return 3 - CurrGroupSize;
35009467b48Spatrick return -1;
35109467b48Spatrick }
35209467b48Spatrick
35309467b48Spatrick // Similarly, a group-ending SU may either fit well (last in group), or
35409467b48Spatrick // end the group prematurely.
35509467b48Spatrick if (SC->EndGroup) {
35609467b48Spatrick unsigned resultingGroupSize =
35709467b48Spatrick (CurrGroupSize + getNumDecoderSlots(SU));
35809467b48Spatrick if (resultingGroupSize < 3)
35909467b48Spatrick return (3 - resultingGroupSize);
36009467b48Spatrick return -1;
36109467b48Spatrick }
36209467b48Spatrick
36309467b48Spatrick // An instruction with 4 register operands will not fit in last slot.
36409467b48Spatrick if (CurrGroupSize == 2 && has4RegOps(SU->getInstr()))
36509467b48Spatrick return 1;
36609467b48Spatrick
36709467b48Spatrick // Most instructions can be placed in any decoder slot.
36809467b48Spatrick return 0;
36909467b48Spatrick }
37009467b48Spatrick
isFPdOpPreferred_distance(SUnit * SU) const37109467b48Spatrick bool SystemZHazardRecognizer::isFPdOpPreferred_distance(SUnit *SU) const {
37209467b48Spatrick assert (SU->isUnbuffered);
37309467b48Spatrick // If this is the first FPd op, it should be scheduled high.
37409467b48Spatrick if (LastFPdOpCycleIdx == UINT_MAX)
37509467b48Spatrick return true;
37609467b48Spatrick // If this is not the first PFd op, it should go into the other side
37709467b48Spatrick // of the processor to use the other FPd unit there. This should
37809467b48Spatrick // generally happen if two FPd ops are placed with 2 other
37909467b48Spatrick // instructions between them (modulo 6).
38009467b48Spatrick unsigned SUCycleIdx = getCurrCycleIdx(SU);
38109467b48Spatrick if (LastFPdOpCycleIdx > SUCycleIdx)
38209467b48Spatrick return ((LastFPdOpCycleIdx - SUCycleIdx) == 3);
38309467b48Spatrick return ((SUCycleIdx - LastFPdOpCycleIdx) == 3);
38409467b48Spatrick }
38509467b48Spatrick
38609467b48Spatrick int SystemZHazardRecognizer::
resourcesCost(SUnit * SU)38709467b48Spatrick resourcesCost(SUnit *SU) {
38809467b48Spatrick int Cost = 0;
38909467b48Spatrick
39009467b48Spatrick const MCSchedClassDesc *SC = getSchedClass(SU);
39109467b48Spatrick if (!SC->isValid())
39209467b48Spatrick return 0;
39309467b48Spatrick
39409467b48Spatrick // For a FPd op, either return min or max value as indicated by the
39509467b48Spatrick // distance to any prior FPd op.
39609467b48Spatrick if (SU->isUnbuffered)
39709467b48Spatrick Cost = (isFPdOpPreferred_distance(SU) ? INT_MIN : INT_MAX);
39809467b48Spatrick // For other instructions, give a cost to the use of the critical resource.
39909467b48Spatrick else if (CriticalResourceIdx != UINT_MAX) {
40009467b48Spatrick for (TargetSchedModel::ProcResIter
40109467b48Spatrick PI = SchedModel->getWriteProcResBegin(SC),
40209467b48Spatrick PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI)
40309467b48Spatrick if (PI->ProcResourceIdx == CriticalResourceIdx)
40409467b48Spatrick Cost = PI->Cycles;
40509467b48Spatrick }
40609467b48Spatrick
40709467b48Spatrick return Cost;
40809467b48Spatrick }
40909467b48Spatrick
emitInstruction(MachineInstr * MI,bool TakenBranch)41009467b48Spatrick void SystemZHazardRecognizer::emitInstruction(MachineInstr *MI,
41109467b48Spatrick bool TakenBranch) {
41209467b48Spatrick // Make a temporary SUnit.
41309467b48Spatrick SUnit SU(MI, 0);
41409467b48Spatrick
41509467b48Spatrick // Set interesting flags.
41609467b48Spatrick SU.isCall = MI->isCall();
41709467b48Spatrick
41809467b48Spatrick const MCSchedClassDesc *SC = SchedModel->resolveSchedClass(MI);
41909467b48Spatrick for (const MCWriteProcResEntry &PRE :
42009467b48Spatrick make_range(SchedModel->getWriteProcResBegin(SC),
42109467b48Spatrick SchedModel->getWriteProcResEnd(SC))) {
42209467b48Spatrick switch (SchedModel->getProcResource(PRE.ProcResourceIdx)->BufferSize) {
42309467b48Spatrick case 0:
42409467b48Spatrick SU.hasReservedResource = true;
42509467b48Spatrick break;
42609467b48Spatrick case 1:
42709467b48Spatrick SU.isUnbuffered = true;
42809467b48Spatrick break;
42909467b48Spatrick default:
43009467b48Spatrick break;
43109467b48Spatrick }
43209467b48Spatrick }
43309467b48Spatrick
43409467b48Spatrick unsigned GroupSizeBeforeEmit = CurrGroupSize;
43509467b48Spatrick EmitInstruction(&SU);
43609467b48Spatrick
43709467b48Spatrick if (!TakenBranch && isBranchRetTrap(MI)) {
43809467b48Spatrick // NT Branch on second slot ends group.
43909467b48Spatrick if (GroupSizeBeforeEmit == 1)
44009467b48Spatrick nextGroup();
44109467b48Spatrick }
44209467b48Spatrick
44309467b48Spatrick if (TakenBranch && CurrGroupSize > 0)
44409467b48Spatrick nextGroup();
44509467b48Spatrick
44609467b48Spatrick assert ((!MI->isTerminator() || isBranchRetTrap(MI)) &&
44709467b48Spatrick "Scheduler: unhandled terminator!");
44809467b48Spatrick }
44909467b48Spatrick
45009467b48Spatrick void SystemZHazardRecognizer::
copyState(SystemZHazardRecognizer * Incoming)45109467b48Spatrick copyState(SystemZHazardRecognizer *Incoming) {
45209467b48Spatrick // Current decoder group
45309467b48Spatrick CurrGroupSize = Incoming->CurrGroupSize;
45409467b48Spatrick LLVM_DEBUG(CurGroupDbg = Incoming->CurGroupDbg;);
45509467b48Spatrick
45609467b48Spatrick // Processor resources
45709467b48Spatrick ProcResourceCounters = Incoming->ProcResourceCounters;
45809467b48Spatrick CriticalResourceIdx = Incoming->CriticalResourceIdx;
45909467b48Spatrick
46009467b48Spatrick // FPd
46109467b48Spatrick LastFPdOpCycleIdx = Incoming->LastFPdOpCycleIdx;
46209467b48Spatrick GrpCount = Incoming->GrpCount;
46309467b48Spatrick }
464