1303231Sdim//===-- GCNHazardRecognizers.h - GCN Hazard Recognizers ---------*- C++ -*-===//
2303231Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6303231Sdim//
7303231Sdim//===----------------------------------------------------------------------===//
8303231Sdim//
9303231Sdim// This file defines hazard recognizers for scheduling on GCN processors.
10303231Sdim//
11303231Sdim//===----------------------------------------------------------------------===//
12303231Sdim
13303231Sdim#ifndef LLVM_LIB_TARGET_AMDGPUHAZARDRECOGNIZERS_H
14303231Sdim#define LLVM_LIB_TARGET_AMDGPUHAZARDRECOGNIZERS_H
15303231Sdim
16327952Sdim#include "llvm/ADT/BitVector.h"
17303231Sdim#include "llvm/ADT/STLExtras.h"
18303231Sdim#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
19353358Sdim#include "llvm/CodeGen/TargetSchedule.h"
20303231Sdim#include <list>
21303231Sdim
22303231Sdimnamespace llvm {
23303231Sdim
24303231Sdimclass MachineFunction;
25303231Sdimclass MachineInstr;
26327952Sdimclass MachineOperand;
27327952Sdimclass MachineRegisterInfo;
28303231Sdimclass ScheduleDAG;
29303231Sdimclass SIInstrInfo;
30327952Sdimclass SIRegisterInfo;
31341825Sdimclass GCNSubtarget;
32303231Sdim
33303231Sdimclass GCNHazardRecognizer final : public ScheduleHazardRecognizer {
34353358Sdimpublic:
35353358Sdim  typedef function_ref<bool(MachineInstr *)> IsHazardFn;
36353358Sdim
37353358Sdimprivate:
38353358Sdim  // Distinguish if we are called from scheduler or hazard recognizer
39353358Sdim  bool IsHazardRecognizerMode;
40353358Sdim
41303231Sdim  // This variable stores the instruction that has been emitted this cycle. It
42303231Sdim  // will be added to EmittedInstrs, when AdvanceCycle() or RecedeCycle() is
43303231Sdim  // called.
44303231Sdim  MachineInstr *CurrCycleInstr;
45303231Sdim  std::list<MachineInstr*> EmittedInstrs;
46303231Sdim  const MachineFunction &MF;
47341825Sdim  const GCNSubtarget &ST;
48321369Sdim  const SIInstrInfo &TII;
49327952Sdim  const SIRegisterInfo &TRI;
50353358Sdim  TargetSchedModel TSchedModel;
51303231Sdim
52327952Sdim  /// RegUnits of uses in the current soft memory clause.
53327952Sdim  BitVector ClauseUses;
54327952Sdim
55327952Sdim  /// RegUnits of defs in the current soft memory clause.
56327952Sdim  BitVector ClauseDefs;
57327952Sdim
58327952Sdim  void resetClause() {
59327952Sdim    ClauseUses.reset();
60327952Sdim    ClauseDefs.reset();
61327952Sdim  }
62327952Sdim
63327952Sdim  void addClauseInst(const MachineInstr &MI);
64327952Sdim
65353358Sdim  // Advance over a MachineInstr bundle. Look for hazards in the bundled
66353358Sdim  // instructions.
67353358Sdim  void processBundle();
68303231Sdim
69353358Sdim  int getWaitStatesSince(IsHazardFn IsHazard, int Limit);
70353358Sdim  int getWaitStatesSinceDef(unsigned Reg, IsHazardFn IsHazardDef, int Limit);
71353358Sdim  int getWaitStatesSinceSetReg(IsHazardFn IsHazard, int Limit);
72353358Sdim
73327952Sdim  int checkSoftClauseHazards(MachineInstr *SMEM);
74303231Sdim  int checkSMRDHazards(MachineInstr *SMRD);
75303231Sdim  int checkVMEMHazards(MachineInstr* VMEM);
76303231Sdim  int checkDPPHazards(MachineInstr *DPP);
77314564Sdim  int checkDivFMasHazards(MachineInstr *DivFMas);
78314564Sdim  int checkGetRegHazards(MachineInstr *GetRegInstr);
79314564Sdim  int checkSetRegHazards(MachineInstr *SetRegInstr);
80314564Sdim  int createsVALUHazard(const MachineInstr &MI);
81314564Sdim  int checkVALUHazards(MachineInstr *VALU);
82327952Sdim  int checkVALUHazardsHelper(const MachineOperand &Def, const MachineRegisterInfo &MRI);
83314564Sdim  int checkRWLaneHazards(MachineInstr *RWLane);
84314564Sdim  int checkRFEHazards(MachineInstr *RFE);
85327952Sdim  int checkInlineAsmHazards(MachineInstr *IA);
86321369Sdim  int checkAnyInstHazards(MachineInstr *MI);
87321369Sdim  int checkReadM0Hazards(MachineInstr *SMovRel);
88353358Sdim  int checkNSAtoVMEMHazard(MachineInstr *MI);
89353358Sdim  int checkFPAtomicToDenormModeHazard(MachineInstr *MI);
90353358Sdim  void fixHazards(MachineInstr *MI);
91353358Sdim  bool fixVcmpxPermlaneHazards(MachineInstr *MI);
92353358Sdim  bool fixVMEMtoScalarWriteHazards(MachineInstr *MI);
93353358Sdim  bool fixSMEMtoVectorWriteHazards(MachineInstr *MI);
94353358Sdim  bool fixVcmpxExecWARHazard(MachineInstr *MI);
95353358Sdim  bool fixLdsBranchVmemWARHazard(MachineInstr *MI);
96353358Sdim
97353358Sdim  int checkMAIHazards(MachineInstr *MI);
98353358Sdim  int checkMAILdStHazards(MachineInstr *MI);
99353358Sdim
100303231Sdimpublic:
101303231Sdim  GCNHazardRecognizer(const MachineFunction &MF);
102303231Sdim  // We can only issue one instruction per cycle.
103303231Sdim  bool atIssueLimit() const override { return true; }
104303231Sdim  void EmitInstruction(SUnit *SU) override;
105303231Sdim  void EmitInstruction(MachineInstr *MI) override;
106303231Sdim  HazardType getHazardType(SUnit *SU, int Stalls) override;
107303231Sdim  void EmitNoop() override;
108303231Sdim  unsigned PreEmitNoops(SUnit *SU) override;
109303231Sdim  unsigned PreEmitNoops(MachineInstr *) override;
110353358Sdim  unsigned PreEmitNoopsCommon(MachineInstr *);
111303231Sdim  void AdvanceCycle() override;
112303231Sdim  void RecedeCycle() override;
113303231Sdim};
114303231Sdim
115303231Sdim} // end namespace llvm
116303231Sdim
117303231Sdim#endif //LLVM_LIB_TARGET_AMDGPUHAZARDRECOGNIZERS_H
118