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 #ifndef NDEBUG 49 const SystemZInstrInfo *TII; 50 #endif 51 const TargetSchedModel *SchedModel; 52 53 /// Keep track of the number of decoder slots used in the current 54 /// decoder group. 55 unsigned CurrGroupSize; 56 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). 61 62 /// Counters for the number of uops scheduled per processor 63 /// resource. 64 SmallVector<int, 0> ProcResourceCounters; 65 66 /// This is the resource with the greatest queue, which the 67 /// scheduler tries to avoid. 68 unsigned CriticalResourceIdx; 69 70 /// Return the number of decoder slots MI requires. 71 inline unsigned getNumDecoderSlots(SUnit *SU) const; 72 73 /// Return true if MI fits into current decoder group. 74 bool fitsIntoCurrentGroup(SUnit *SU) const; 75 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(); 80 81 /// LastFPdOpCycleIdx stores the numbeer returned by getCurrCycleIdx() 82 /// when a stalling operation is scheduled (which uses the FPd resource). 83 unsigned LastFPdOpCycleIdx; 84 85 /// A counter of decoder groups scheduled. 86 unsigned GrpCount; 87 88 unsigned getCurrGroupSize() {return CurrGroupSize;}; 89 90 /// Start next decoder group. 91 void nextGroup(bool DbgOutput = true); 92 93 /// Clear all counters for processor resources. 94 void clearProcResCounters(); 95 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); 99 100 /// Last emitted instruction or nullptr. 101 MachineInstr *LastEmittedMI; 102 103 public: 104 SystemZHazardRecognizer(const SystemZInstrInfo *tii, 105 const TargetSchedModel *SM) 106 : 107 #ifndef NDEBUG 108 TII(tii), 109 #endif 110 SchedModel(SM) { 111 Reset(); 112 } 113 114 HazardType getHazardType(SUnit *m, int Stalls = 0) override; 115 void Reset() override; 116 void EmitInstruction(SUnit *SU) override; 117 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; 123 } 124 125 /// Wrap a non-scheduled instruction in an SU and emit it. 126 void emitInstruction(MachineInstr *MI, bool TakenBranch = false); 127 128 // Cost functions used by SystemZPostRASchedStrategy while 129 // evaluating candidates. 130 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; 136 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); 141 142 #ifndef NDEBUG 143 // Debug dumping. 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; 148 #endif 149 150 MachineBasicBlock::iterator getLastEmittedMI() { return LastEmittedMI; } 151 152 /// Copy counters from end of single predecessor. 153 void copyState(SystemZHazardRecognizer *Incoming); 154 }; 155 156 } // namespace llvm 157 158 #endif /* LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZHAZARDRECOGNIZER_H */ 159