• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //=-- SystemZHazardRecognizer.h - SystemZ Hazard Recognizer -----*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file declares a hazard recognizer for the SystemZ scheduler.
10 //
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:
14 //
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
19 // resources.
20 //
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.
24 //
25 // A block that has only one predecessor continues scheduling with the state
26 // of it (which may be updated by emitting branches).
27 //
28 // ===---------------------------------------------------------------------===//
29 
30 #ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZHAZARDRECOGNIZER_H
31 #define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZHAZARDRECOGNIZER_H
32 
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"
40 #include <string>
41 
42 namespace llvm {
43 
44 /// SystemZHazardRecognizer maintains the state for one MBB during scheduling.
45 class SystemZHazardRecognizer : public ScheduleHazardRecognizer {
46 
47   const SystemZInstrInfo *TII;
48   const TargetSchedModel *SchedModel;
49 
50   /// Keep track of the number of decoder slots used in the current
51   /// decoder group.
52   unsigned CurrGroupSize;
53 
54   /// True if an instruction with four reg operands have been scheduled into
55   /// the current decoder group.
56   bool CurrGroupHas4RegOps;
57 
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).
62 
63   /// Counters for the number of uops scheduled per processor
64   /// resource.
65   SmallVector<int, 0> ProcResourceCounters;
66 
67   /// This is the resource with the greatest queue, which the
68   /// scheduler tries to avoid.
69   unsigned CriticalResourceIdx;
70 
71   /// Return the number of decoder slots MI requires.
72   inline unsigned getNumDecoderSlots(SUnit *SU) const;
73 
74   /// Return true if MI fits into current decoder group.
75   bool fitsIntoCurrentGroup(SUnit *SU) const;
76 
77   /// Return true if this instruction has four register operands.
78   bool has4RegOps(const MachineInstr *MI) const;
79 
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;
86 
87   /// LastFPdOpCycleIdx stores the numbeer returned by getCurrCycleIdx()
88   /// when a stalling operation is scheduled (which uses the FPd resource).
89   unsigned LastFPdOpCycleIdx;
90 
91   /// A counter of decoder groups scheduled.
92   unsigned GrpCount;
93 
getCurrGroupSize()94   unsigned getCurrGroupSize() {return CurrGroupSize;};
95 
96   /// Start next decoder group.
97   void nextGroup();
98 
99   /// Clear all counters for processor resources.
100   void clearProcResCounters();
101 
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;
105 
106   /// Last emitted instruction or nullptr.
107   MachineInstr *LastEmittedMI;
108 
109 public:
SystemZHazardRecognizer(const SystemZInstrInfo * tii,const TargetSchedModel * SM)110   SystemZHazardRecognizer(const SystemZInstrInfo *tii,
111                           const TargetSchedModel *SM)
112       : TII(tii), SchedModel(SM) {
113     Reset();
114   }
115 
116   HazardType getHazardType(SUnit *m, int Stalls = 0) override;
117   void Reset() override;
118   void EmitInstruction(SUnit *SU) override;
119 
120   /// Resolves and cache a resolved scheduling class for an SUnit.
getSchedClass(SUnit * SU)121   const MCSchedClassDesc *getSchedClass(SUnit *SU) const {
122     if (!SU->SchedClass && SchedModel->hasInstrSchedModel())
123       SU->SchedClass = SchedModel->resolveSchedClass(SU->getInstr());
124     return SU->SchedClass;
125   }
126 
127   /// Wrap a non-scheduled instruction in an SU and emit it.
128   void emitInstruction(MachineInstr *MI, bool TakenBranch = false);
129 
130   // Cost functions used by SystemZPostRASchedStrategy while
131   // evaluating candidates.
132 
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;
138 
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);
143 
144 #ifndef NDEBUG
145   // Debug dumping.
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;
151 #endif
152 
getLastEmittedMI()153   MachineBasicBlock::iterator getLastEmittedMI() { return LastEmittedMI; }
154 
155   /// Copy counters from end of single predecessor.
156   void copyState(SystemZHazardRecognizer *Incoming);
157 };
158 
159 } // namespace llvm
160 
161 #endif /* LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZHAZARDRECOGNIZER_H */
162