• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //=-- SystemZHazardRecognizer.h - SystemZ Hazard Recognizer -----*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file declares a hazard recognizer for the SystemZ scheduler.
11 //
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:
15 //
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
20 // resources.
21 //
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.
25 //
26 // A block that has only one predecessor continues scheduling with the state
27 // of it (which may be updated by emitting branches).
28 //
29 // ===---------------------------------------------------------------------===//
30 
31 #ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZHAZARDRECOGNIZER_H
32 #define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZHAZARDRECOGNIZER_H
33 
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"
41 #include <string>
42 
43 namespace llvm {
44 
45 /// SystemZHazardRecognizer maintains the state for one MBB during scheduling.
46 class SystemZHazardRecognizer : public ScheduleHazardRecognizer {
47 
48   const SystemZInstrInfo *TII;
49   const TargetSchedModel *SchedModel;
50 
51   /// Keep track of the number of decoder slots used in the current
52   /// decoder group.
53   unsigned CurrGroupSize;
54 
55   /// True if an instruction with four reg operands have been scheduled into
56   /// the current decoder group.
57   bool CurrGroupHas4RegOps;
58 
59   /// The tracking of resources here are quite similar to the common
60   /// code use of a critical resource. However, z13 differs in the way
61   /// that it has two processor sides which may be interesting to
62   /// model in the future (a work in progress).
63 
64   /// Counters for the number of uops scheduled per processor
65   /// resource.
66   SmallVector<int, 0> ProcResourceCounters;
67 
68   /// This is the resource with the greatest queue, which the
69   /// scheduler tries to avoid.
70   unsigned CriticalResourceIdx;
71 
72   /// Return the number of decoder slots MI requires.
73   inline unsigned getNumDecoderSlots(SUnit *SU) const;
74 
75   /// Return true if MI fits into current decoder group.
76   bool fitsIntoCurrentGroup(SUnit *SU) const;
77 
78   /// Return true if this instruction has four register operands.
79   bool has4RegOps(const MachineInstr *MI) const;
80 
81   /// Two decoder groups per cycle are formed (for z13), meaning 2x3
82   /// instructions. This function returns a number between 0 and 5,
83   /// representing the current decoder slot of the current cycle.  If an SU
84   /// is passed which will begin a new decoder group, the returned value is
85   /// the cycle index of the next group.
86   unsigned getCurrCycleIdx(SUnit *SU = nullptr) const;
87 
88   /// LastFPdOpCycleIdx stores the numbeer returned by getCurrCycleIdx()
89   /// when a stalling operation is scheduled (which uses the FPd resource).
90   unsigned LastFPdOpCycleIdx;
91 
92   /// A counter of decoder groups scheduled.
93   unsigned GrpCount;
94 
getCurrGroupSize()95   unsigned getCurrGroupSize() {return CurrGroupSize;};
96 
97   /// Start next decoder group.
98   void nextGroup();
99 
100   /// Clear all counters for processor resources.
101   void clearProcResCounters();
102 
103   /// With the goal of alternating processor sides for stalling (FPd)
104   /// ops, return true if it seems good to schedule an FPd op next.
105   bool isFPdOpPreferred_distance(SUnit *SU) const;
106 
107   /// Last emitted instruction or nullptr.
108   MachineInstr *LastEmittedMI;
109 
110 public:
SystemZHazardRecognizer(const SystemZInstrInfo * tii,const TargetSchedModel * SM)111   SystemZHazardRecognizer(const SystemZInstrInfo *tii,
112                           const TargetSchedModel *SM)
113       : TII(tii), SchedModel(SM) {
114     Reset();
115   }
116 
117   HazardType getHazardType(SUnit *m, int Stalls = 0) override;
118   void Reset() override;
119   void EmitInstruction(SUnit *SU) override;
120 
121   /// Resolves and cache a resolved scheduling class for an SUnit.
getSchedClass(SUnit * SU)122   const MCSchedClassDesc *getSchedClass(SUnit *SU) const {
123     if (!SU->SchedClass && SchedModel->hasInstrSchedModel())
124       SU->SchedClass = SchedModel->resolveSchedClass(SU->getInstr());
125     return SU->SchedClass;
126   }
127 
128   /// Wrap a non-scheduled instruction in an SU and emit it.
129   void emitInstruction(MachineInstr *MI, bool TakenBranch = false);
130 
131   // Cost functions used by SystemZPostRASchedStrategy while
132   // evaluating candidates.
133 
134   /// Return the cost of decoder grouping for SU. If SU must start a
135   /// new decoder group, this is negative if this fits the schedule or
136   /// positive if it would mean ending a group prematurely. For normal
137   /// instructions this returns 0.
138   int groupingCost(SUnit *SU) const;
139 
140   /// Return the cost of SU in regards to processor resources usage.
141   /// A positive value means it would be better to wait with SU, while
142   /// a negative value means it would be good to schedule SU next.
143   int resourcesCost(SUnit *SU);
144 
145 #ifndef NDEBUG
146   // Debug dumping.
147   std::string CurGroupDbg; // current group as text
148   void dumpSU(SUnit *SU, raw_ostream &OS) const;
149   void dumpCurrGroup(std::string Msg = "") const;
150   void dumpProcResourceCounters() const;
151   void dumpState() const;
152 #endif
153 
getLastEmittedMI()154   MachineBasicBlock::iterator getLastEmittedMI() { return LastEmittedMI; }
155 
156   /// Copy counters from end of single predecessor.
157   void copyState(SystemZHazardRecognizer *Incoming);
158 };
159 
160 } // namespace llvm
161 
162 #endif /* LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZHAZARDRECOGNIZER_H */
163