xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.h (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===-- GCNHazardRecognizers.h - GCN Hazard Recognizers ---------*- C++ -*-===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // This file defines hazard recognizers for scheduling on GCN processors.
10*0b57cec5SDimitry Andric //
11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
12*0b57cec5SDimitry Andric 
13*0b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_AMDGPUHAZARDRECOGNIZERS_H
14*0b57cec5SDimitry Andric #define LLVM_LIB_TARGET_AMDGPUHAZARDRECOGNIZERS_H
15*0b57cec5SDimitry Andric 
16*0b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h"
17*0b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
18*0b57cec5SDimitry Andric #include "llvm/CodeGen/ScheduleHazardRecognizer.h"
19*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSchedule.h"
20*0b57cec5SDimitry Andric #include <list>
21*0b57cec5SDimitry Andric 
22*0b57cec5SDimitry Andric namespace llvm {
23*0b57cec5SDimitry Andric 
24*0b57cec5SDimitry Andric class MachineFunction;
25*0b57cec5SDimitry Andric class MachineInstr;
26*0b57cec5SDimitry Andric class MachineOperand;
27*0b57cec5SDimitry Andric class MachineRegisterInfo;
28*0b57cec5SDimitry Andric class ScheduleDAG;
29*0b57cec5SDimitry Andric class SIInstrInfo;
30*0b57cec5SDimitry Andric class SIRegisterInfo;
31*0b57cec5SDimitry Andric class GCNSubtarget;
32*0b57cec5SDimitry Andric 
33*0b57cec5SDimitry Andric class GCNHazardRecognizer final : public ScheduleHazardRecognizer {
34*0b57cec5SDimitry Andric public:
35*0b57cec5SDimitry Andric   typedef function_ref<bool(MachineInstr *)> IsHazardFn;
36*0b57cec5SDimitry Andric 
37*0b57cec5SDimitry Andric private:
38*0b57cec5SDimitry Andric   // Distinguish if we are called from scheduler or hazard recognizer
39*0b57cec5SDimitry Andric   bool IsHazardRecognizerMode;
40*0b57cec5SDimitry Andric 
41*0b57cec5SDimitry Andric   // This variable stores the instruction that has been emitted this cycle. It
42*0b57cec5SDimitry Andric   // will be added to EmittedInstrs, when AdvanceCycle() or RecedeCycle() is
43*0b57cec5SDimitry Andric   // called.
44*0b57cec5SDimitry Andric   MachineInstr *CurrCycleInstr;
45*0b57cec5SDimitry Andric   std::list<MachineInstr*> EmittedInstrs;
46*0b57cec5SDimitry Andric   const MachineFunction &MF;
47*0b57cec5SDimitry Andric   const GCNSubtarget &ST;
48*0b57cec5SDimitry Andric   const SIInstrInfo &TII;
49*0b57cec5SDimitry Andric   const SIRegisterInfo &TRI;
50*0b57cec5SDimitry Andric   TargetSchedModel TSchedModel;
51*0b57cec5SDimitry Andric 
52*0b57cec5SDimitry Andric   /// RegUnits of uses in the current soft memory clause.
53*0b57cec5SDimitry Andric   BitVector ClauseUses;
54*0b57cec5SDimitry Andric 
55*0b57cec5SDimitry Andric   /// RegUnits of defs in the current soft memory clause.
56*0b57cec5SDimitry Andric   BitVector ClauseDefs;
57*0b57cec5SDimitry Andric 
58*0b57cec5SDimitry Andric   void resetClause() {
59*0b57cec5SDimitry Andric     ClauseUses.reset();
60*0b57cec5SDimitry Andric     ClauseDefs.reset();
61*0b57cec5SDimitry Andric   }
62*0b57cec5SDimitry Andric 
63*0b57cec5SDimitry Andric   void addClauseInst(const MachineInstr &MI);
64*0b57cec5SDimitry Andric 
65*0b57cec5SDimitry Andric   // Advance over a MachineInstr bundle. Look for hazards in the bundled
66*0b57cec5SDimitry Andric   // instructions.
67*0b57cec5SDimitry Andric   void processBundle();
68*0b57cec5SDimitry Andric 
69*0b57cec5SDimitry Andric   int getWaitStatesSince(IsHazardFn IsHazard, int Limit);
70*0b57cec5SDimitry Andric   int getWaitStatesSinceDef(unsigned Reg, IsHazardFn IsHazardDef, int Limit);
71*0b57cec5SDimitry Andric   int getWaitStatesSinceSetReg(IsHazardFn IsHazard, int Limit);
72*0b57cec5SDimitry Andric 
73*0b57cec5SDimitry Andric   int checkSoftClauseHazards(MachineInstr *SMEM);
74*0b57cec5SDimitry Andric   int checkSMRDHazards(MachineInstr *SMRD);
75*0b57cec5SDimitry Andric   int checkVMEMHazards(MachineInstr* VMEM);
76*0b57cec5SDimitry Andric   int checkDPPHazards(MachineInstr *DPP);
77*0b57cec5SDimitry Andric   int checkDivFMasHazards(MachineInstr *DivFMas);
78*0b57cec5SDimitry Andric   int checkGetRegHazards(MachineInstr *GetRegInstr);
79*0b57cec5SDimitry Andric   int checkSetRegHazards(MachineInstr *SetRegInstr);
80*0b57cec5SDimitry Andric   int createsVALUHazard(const MachineInstr &MI);
81*0b57cec5SDimitry Andric   int checkVALUHazards(MachineInstr *VALU);
82*0b57cec5SDimitry Andric   int checkVALUHazardsHelper(const MachineOperand &Def, const MachineRegisterInfo &MRI);
83*0b57cec5SDimitry Andric   int checkRWLaneHazards(MachineInstr *RWLane);
84*0b57cec5SDimitry Andric   int checkRFEHazards(MachineInstr *RFE);
85*0b57cec5SDimitry Andric   int checkInlineAsmHazards(MachineInstr *IA);
86*0b57cec5SDimitry Andric   int checkAnyInstHazards(MachineInstr *MI);
87*0b57cec5SDimitry Andric   int checkReadM0Hazards(MachineInstr *SMovRel);
88*0b57cec5SDimitry Andric   int checkNSAtoVMEMHazard(MachineInstr *MI);
89*0b57cec5SDimitry Andric   int checkFPAtomicToDenormModeHazard(MachineInstr *MI);
90*0b57cec5SDimitry Andric   void fixHazards(MachineInstr *MI);
91*0b57cec5SDimitry Andric   bool fixVcmpxPermlaneHazards(MachineInstr *MI);
92*0b57cec5SDimitry Andric   bool fixVMEMtoScalarWriteHazards(MachineInstr *MI);
93*0b57cec5SDimitry Andric   bool fixSMEMtoVectorWriteHazards(MachineInstr *MI);
94*0b57cec5SDimitry Andric   bool fixVcmpxExecWARHazard(MachineInstr *MI);
95*0b57cec5SDimitry Andric   bool fixLdsBranchVmemWARHazard(MachineInstr *MI);
96*0b57cec5SDimitry Andric 
97*0b57cec5SDimitry Andric   int checkMAIHazards(MachineInstr *MI);
98*0b57cec5SDimitry Andric   int checkMAILdStHazards(MachineInstr *MI);
99*0b57cec5SDimitry Andric 
100*0b57cec5SDimitry Andric public:
101*0b57cec5SDimitry Andric   GCNHazardRecognizer(const MachineFunction &MF);
102*0b57cec5SDimitry Andric   // We can only issue one instruction per cycle.
103*0b57cec5SDimitry Andric   bool atIssueLimit() const override { return true; }
104*0b57cec5SDimitry Andric   void EmitInstruction(SUnit *SU) override;
105*0b57cec5SDimitry Andric   void EmitInstruction(MachineInstr *MI) override;
106*0b57cec5SDimitry Andric   HazardType getHazardType(SUnit *SU, int Stalls) override;
107*0b57cec5SDimitry Andric   void EmitNoop() override;
108*0b57cec5SDimitry Andric   unsigned PreEmitNoops(SUnit *SU) override;
109*0b57cec5SDimitry Andric   unsigned PreEmitNoops(MachineInstr *) override;
110*0b57cec5SDimitry Andric   unsigned PreEmitNoopsCommon(MachineInstr *);
111*0b57cec5SDimitry Andric   void AdvanceCycle() override;
112*0b57cec5SDimitry Andric   void RecedeCycle() override;
113*0b57cec5SDimitry Andric };
114*0b57cec5SDimitry Andric 
115*0b57cec5SDimitry Andric } // end namespace llvm
116*0b57cec5SDimitry Andric 
117*0b57cec5SDimitry Andric #endif //LLVM_LIB_TARGET_AMDGPUHAZARDRECOGNIZERS_H
118