Home | History | Annotate | Line # | Download | only in SystemZ
      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 
     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:
    110   SystemZHazardRecognizer(const SystemZInstrInfo *tii,
    111                           const TargetSchedModel *SM)
    112       : TII(tii), SchedModel(SM) {
    113     Reset();
    114   }
    115 
    116   HazardType getHazardType(SUnit *SU, 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.
    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 
    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