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