1 //=-- SystemZHazardRecognizer.h - SystemZ Hazard Recognizer -----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file declares a hazard recognizer for the SystemZ scheduler.
12 // This class is used by the SystemZ scheduling strategy to maintain
13 // the state during scheduling, and provide cost functions for
14 // scheduling candidates. This includes:
16 // * Decoder grouping. A decoder group can maximally hold 3 uops, and
17 // instructions that always begin a new group should be scheduled when
18 // the current decoder group is empty.
19 // * Processor resources usage. It is beneficial to balance the use of
22 // A goal is to consider all instructions, also those outside of any
23 // scheduling region. Such instructions are "advanced" past and include
24 // single instructions before a scheduling region, branches etc.
26 // A block that has only one predecessor continues scheduling with the state
27 // of it (which may be updated by emitting branches).
29 // ===---------------------------------------------------------------------===//
31 #ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZHAZARDRECOGNIZER_H
32 #define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZHAZARDRECOGNIZER_H
34 #include "SystemZSubtarget.h"
35 #include "llvm/ADT/SmallVector.h"
36 #include "llvm/CodeGen/MachineFunction.h"
37 #include "llvm/CodeGen/MachineScheduler.h"
38 #include "llvm/CodeGen/ScheduleHazardRecognizer.h"
39 #include "llvm/MC/MCInstrDesc.h"
40 #include "llvm/Support/raw_ostream.h"
45 /// SystemZHazardRecognizer maintains the state for one MBB during scheduling.
46 class SystemZHazardRecognizer : public ScheduleHazardRecognizer {
49 const SystemZInstrInfo *TII;
51 const TargetSchedModel *SchedModel;
53 /// Keep track of the number of decoder slots used in the current
55 unsigned CurrGroupSize;
57 /// The tracking of resources here are quite similar to the common
58 /// code use of a critical resource. However, z13 differs in the way
59 /// that it has two processor sides which may be interesting to
60 /// model in the future (a work in progress).
62 /// Counters for the number of uops scheduled per processor
64 SmallVector<int, 0> ProcResourceCounters;
66 /// This is the resource with the greatest queue, which the
67 /// scheduler tries to avoid.
68 unsigned CriticalResourceIdx;
70 /// Return the number of decoder slots MI requires.
71 inline unsigned getNumDecoderSlots(SUnit *SU) const;
73 /// Return true if MI fits into current decoder group.
74 bool fitsIntoCurrentGroup(SUnit *SU) const;
76 /// Two decoder groups per cycle are formed (for z13), meaning 2x3
77 /// instructions. This function returns a number between 0 and 5,
78 /// representing the current decoder slot of the current cycle.
79 unsigned getCurrCycleIdx();
81 /// LastFPdOpCycleIdx stores the numbeer returned by getCurrCycleIdx()
82 /// when a stalling operation is scheduled (which uses the FPd resource).
83 unsigned LastFPdOpCycleIdx;
85 /// A counter of decoder groups scheduled.
88 unsigned getCurrGroupSize() {return CurrGroupSize;};
90 /// Start next decoder group.
91 void nextGroup(bool DbgOutput = true);
93 /// Clear all counters for processor resources.
94 void clearProcResCounters();
96 /// With the goal of alternating processor sides for stalling (FPd)
97 /// ops, return true if it seems good to schedule an FPd op next.
98 bool isFPdOpPreferred_distance(const SUnit *SU);
100 /// Last emitted instruction or nullptr.
101 MachineInstr *LastEmittedMI;
104 SystemZHazardRecognizer(const SystemZInstrInfo *tii,
105 const TargetSchedModel *SM)
114 HazardType getHazardType(SUnit *m, int Stalls = 0) override;
115 void Reset() override;
116 void EmitInstruction(SUnit *SU) override;
118 /// Resolves and cache a resolved scheduling class for an SUnit.
119 const MCSchedClassDesc *getSchedClass(SUnit *SU) const {
120 if (!SU->SchedClass && SchedModel->hasInstrSchedModel())
121 SU->SchedClass = SchedModel->resolveSchedClass(SU->getInstr());
122 return SU->SchedClass;
125 /// Wrap a non-scheduled instruction in an SU and emit it.
126 void emitInstruction(MachineInstr *MI, bool TakenBranch = false);
128 // Cost functions used by SystemZPostRASchedStrategy while
129 // evaluating candidates.
131 /// Return the cost of decoder grouping for SU. If SU must start a
132 /// new decoder group, this is negative if this fits the schedule or
133 /// positive if it would mean ending a group prematurely. For normal
134 /// instructions this returns 0.
135 int groupingCost(SUnit *SU) const;
137 /// Return the cost of SU in regards to processor resources usage.
138 /// A positive value means it would be better to wait with SU, while
139 /// a negative value means it would be good to schedule SU next.
140 int resourcesCost(SUnit *SU);
144 std::string CurGroupDbg; // current group as text
145 void dumpSU(SUnit *SU, raw_ostream &OS) const;
146 void dumpCurrGroup(std::string Msg = "") const;
147 void dumpProcResourceCounters() const;
150 MachineBasicBlock::iterator getLastEmittedMI() { return LastEmittedMI; }
152 /// Copy counters from end of single predecessor.
153 void copyState(SystemZHazardRecognizer *Incoming);
158 #endif /* LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZHAZARDRECOGNIZER_H */