1 //=-- SystemZHazardRecognizer.h - SystemZ Hazard Recognizer -----*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file declares a hazard recognizer for the SystemZ scheduler.
11 // This class is used by the SystemZ scheduling strategy to maintain
12 // the state during scheduling, and provide cost functions for
13 // scheduling candidates. This includes:
15 // * Decoder grouping. A decoder group can maximally hold 3 uops, and
16 // instructions that always begin a new group should be scheduled when
17 // the current decoder group is empty.
18 // * Processor resources usage. It is beneficial to balance the use of
21 // A goal is to consider all instructions, also those outside of any
22 // scheduling region. Such instructions are "advanced" past and include
23 // single instructions before a scheduling region, branches etc.
25 // A block that has only one predecessor continues scheduling with the state
26 // of it (which may be updated by emitting branches).
28 // ===---------------------------------------------------------------------===//
30 #ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZHAZARDRECOGNIZER_H
31 #define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZHAZARDRECOGNIZER_H
33 #include "SystemZSubtarget.h"
34 #include "llvm/ADT/SmallVector.h"
35 #include "llvm/CodeGen/MachineFunction.h"
36 #include "llvm/CodeGen/MachineScheduler.h"
37 #include "llvm/CodeGen/ScheduleHazardRecognizer.h"
38 #include "llvm/MC/MCInstrDesc.h"
39 #include "llvm/Support/raw_ostream.h"
44 /// SystemZHazardRecognizer maintains the state for one MBB during scheduling.
45 class SystemZHazardRecognizer
: public ScheduleHazardRecognizer
{
47 const SystemZInstrInfo
*TII
;
48 const TargetSchedModel
*SchedModel
;
50 /// Keep track of the number of decoder slots used in the current
52 unsigned CurrGroupSize
;
54 /// True if an instruction with four reg operands have been scheduled into
55 /// the current decoder group.
56 bool CurrGroupHas4RegOps
;
58 /// The tracking of resources here are quite similar to the common
59 /// code use of a critical resource. However, z13 differs in the way
60 /// that it has two processor sides which may be interesting to
61 /// model in the future (a work in progress).
63 /// Counters for the number of uops scheduled per processor
65 SmallVector
<int, 0> ProcResourceCounters
;
67 /// This is the resource with the greatest queue, which the
68 /// scheduler tries to avoid.
69 unsigned CriticalResourceIdx
;
71 /// Return the number of decoder slots MI requires.
72 inline unsigned getNumDecoderSlots(SUnit
*SU
) const;
74 /// Return true if MI fits into current decoder group.
75 bool fitsIntoCurrentGroup(SUnit
*SU
) const;
77 /// Return true if this instruction has four register operands.
78 bool has4RegOps(const MachineInstr
*MI
) const;
80 /// Two decoder groups per cycle are formed (for z13), meaning 2x3
81 /// instructions. This function returns a number between 0 and 5,
82 /// representing the current decoder slot of the current cycle. If an SU
83 /// is passed which will begin a new decoder group, the returned value is
84 /// the cycle index of the next group.
85 unsigned getCurrCycleIdx(SUnit
*SU
= nullptr) const;
87 /// LastFPdOpCycleIdx stores the numbeer returned by getCurrCycleIdx()
88 /// when a stalling operation is scheduled (which uses the FPd resource).
89 unsigned LastFPdOpCycleIdx
;
91 /// A counter of decoder groups scheduled.
94 unsigned getCurrGroupSize() {return CurrGroupSize
;};
96 /// Start next decoder group.
99 /// Clear all counters for processor resources.
100 void clearProcResCounters();
102 /// With the goal of alternating processor sides for stalling (FPd)
103 /// ops, return true if it seems good to schedule an FPd op next.
104 bool isFPdOpPreferred_distance(SUnit
*SU
) const;
106 /// Last emitted instruction or nullptr.
107 MachineInstr
*LastEmittedMI
;
110 SystemZHazardRecognizer(const SystemZInstrInfo
*tii
,
111 const TargetSchedModel
*SM
)
112 : TII(tii
), SchedModel(SM
) {
116 HazardType
getHazardType(SUnit
*m
, int Stalls
= 0) override
;
117 void Reset() override
;
118 void EmitInstruction(SUnit
*SU
) override
;
120 /// Resolves and cache a resolved scheduling class for an SUnit.
121 const MCSchedClassDesc
*getSchedClass(SUnit
*SU
) const {
122 if (!SU
->SchedClass
&& SchedModel
->hasInstrSchedModel())
123 SU
->SchedClass
= SchedModel
->resolveSchedClass(SU
->getInstr());
124 return SU
->SchedClass
;
127 /// Wrap a non-scheduled instruction in an SU and emit it.
128 void emitInstruction(MachineInstr
*MI
, bool TakenBranch
= false);
130 // Cost functions used by SystemZPostRASchedStrategy while
131 // evaluating candidates.
133 /// Return the cost of decoder grouping for SU. If SU must start a
134 /// new decoder group, this is negative if this fits the schedule or
135 /// positive if it would mean ending a group prematurely. For normal
136 /// instructions this returns 0.
137 int groupingCost(SUnit
*SU
) const;
139 /// Return the cost of SU in regards to processor resources usage.
140 /// A positive value means it would be better to wait with SU, while
141 /// a negative value means it would be good to schedule SU next.
142 int resourcesCost(SUnit
*SU
);
146 std::string CurGroupDbg
; // current group as text
147 void dumpSU(SUnit
*SU
, raw_ostream
&OS
) const;
148 void dumpCurrGroup(std::string Msg
= "") const;
149 void dumpProcResourceCounters() const;
150 void dumpState() const;
153 MachineBasicBlock::iterator
getLastEmittedMI() { return LastEmittedMI
; }
155 /// Copy counters from end of single predecessor.
156 void copyState(SystemZHazardRecognizer
*Incoming
);
161 #endif /* LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZHAZARDRECOGNIZER_H */