reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
//=-- SystemZHazardRecognizer.h - SystemZ Hazard Recognizer -----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file declares a hazard recognizer for the SystemZ scheduler.
//
// This class is used by the SystemZ scheduling strategy to maintain
// the state during scheduling, and provide cost functions for
// scheduling candidates. This includes:
//
// * Decoder grouping. A decoder group can maximally hold 3 uops, and
// instructions that always begin a new group should be scheduled when
// the current decoder group is empty.
// * Processor resources usage. It is beneficial to balance the use of
// resources.
//
// A goal is to consider all instructions, also those outside of any
// scheduling region. Such instructions are "advanced" past and include
// single instructions before a scheduling region, branches etc.
//
// A block that has only one predecessor continues scheduling with the state
// of it (which may be updated by emitting branches).
//
// ===---------------------------------------------------------------------===//

#ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZHAZARDRECOGNIZER_H
#define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZHAZARDRECOGNIZER_H

#include "SystemZSubtarget.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineScheduler.h"
#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/Support/raw_ostream.h"
#include <string>

namespace llvm {

/// SystemZHazardRecognizer maintains the state for one MBB during scheduling.
class SystemZHazardRecognizer : public ScheduleHazardRecognizer {

  const SystemZInstrInfo *TII;
  const TargetSchedModel *SchedModel;

  /// Keep track of the number of decoder slots used in the current
  /// decoder group.
  unsigned CurrGroupSize;

  /// True if an instruction with four reg operands have been scheduled into
  /// the current decoder group.
  bool CurrGroupHas4RegOps;

  /// The tracking of resources here are quite similar to the common
  /// code use of a critical resource. However, z13 differs in the way
  /// that it has two processor sides which may be interesting to
  /// model in the future (a work in progress).

  /// Counters for the number of uops scheduled per processor
  /// resource.
  SmallVector<int, 0> ProcResourceCounters;

  /// This is the resource with the greatest queue, which the
  /// scheduler tries to avoid.
  unsigned CriticalResourceIdx;

  /// Return the number of decoder slots MI requires.
  inline unsigned getNumDecoderSlots(SUnit *SU) const;

  /// Return true if MI fits into current decoder group.
  bool fitsIntoCurrentGroup(SUnit *SU) const;

  /// Return true if this instruction has four register operands.
  bool has4RegOps(const MachineInstr *MI) const;

  /// Two decoder groups per cycle are formed (for z13), meaning 2x3
  /// instructions. This function returns a number between 0 and 5,
  /// representing the current decoder slot of the current cycle.  If an SU
  /// is passed which will begin a new decoder group, the returned value is
  /// the cycle index of the next group.
  unsigned getCurrCycleIdx(SUnit *SU = nullptr) const;

  /// LastFPdOpCycleIdx stores the numbeer returned by getCurrCycleIdx()
  /// when a stalling operation is scheduled (which uses the FPd resource).
  unsigned LastFPdOpCycleIdx;

  /// A counter of decoder groups scheduled.
  unsigned GrpCount;

  unsigned getCurrGroupSize() {return CurrGroupSize;};

  /// Start next decoder group.
  void nextGroup();

  /// Clear all counters for processor resources.
  void clearProcResCounters();

  /// With the goal of alternating processor sides for stalling (FPd)
  /// ops, return true if it seems good to schedule an FPd op next.
  bool isFPdOpPreferred_distance(SUnit *SU) const;

  /// Last emitted instruction or nullptr.
  MachineInstr *LastEmittedMI;

public:
  SystemZHazardRecognizer(const SystemZInstrInfo *tii,
                          const TargetSchedModel *SM)
      : TII(tii), SchedModel(SM) {
    Reset();
  }

  HazardType getHazardType(SUnit *m, int Stalls = 0) override;
  void Reset() override;
  void EmitInstruction(SUnit *SU) override;

  /// Resolves and cache a resolved scheduling class for an SUnit.
  const MCSchedClassDesc *getSchedClass(SUnit *SU) const {
    if (!SU->SchedClass && SchedModel->hasInstrSchedModel())
      SU->SchedClass = SchedModel->resolveSchedClass(SU->getInstr());
    return SU->SchedClass;
  }

  /// Wrap a non-scheduled instruction in an SU and emit it.
  void emitInstruction(MachineInstr *MI, bool TakenBranch = false);

  // Cost functions used by SystemZPostRASchedStrategy while
  // evaluating candidates.

  /// Return the cost of decoder grouping for SU. If SU must start a
  /// new decoder group, this is negative if this fits the schedule or
  /// positive if it would mean ending a group prematurely. For normal
  /// instructions this returns 0.
  int groupingCost(SUnit *SU) const;

  /// Return the cost of SU in regards to processor resources usage.
  /// A positive value means it would be better to wait with SU, while
  /// a negative value means it would be good to schedule SU next.
  int resourcesCost(SUnit *SU);

#ifndef NDEBUG
  // Debug dumping.
  std::string CurGroupDbg; // current group as text
  void dumpSU(SUnit *SU, raw_ostream &OS) const;
  void dumpCurrGroup(std::string Msg = "") const;
  void dumpProcResourceCounters() const;
  void dumpState() const;
#endif

  MachineBasicBlock::iterator getLastEmittedMI() { return LastEmittedMI; }

  /// Copy counters from end of single predecessor.
  void copyState(SystemZHazardRecognizer *Incoming);
};

} // namespace llvm

#endif /* LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZHAZARDRECOGNIZER_H */