| //=-- 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 *SU, 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 */ |