xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.h (revision fe6060f10f634930ff71b7c50291ddc610da2475)
10b57cec5SDimitry Andric //===-- GCNHazardRecognizers.h - GCN Hazard Recognizers ---------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines hazard recognizers for scheduling on GCN processors.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_AMDGPUHAZARDRECOGNIZERS_H
140b57cec5SDimitry Andric #define LLVM_LIB_TARGET_AMDGPUHAZARDRECOGNIZERS_H
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h"
170b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/ScheduleHazardRecognizer.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSchedule.h"
200b57cec5SDimitry Andric #include <list>
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric namespace llvm {
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric class MachineFunction;
250b57cec5SDimitry Andric class MachineInstr;
260b57cec5SDimitry Andric class MachineOperand;
270b57cec5SDimitry Andric class MachineRegisterInfo;
280b57cec5SDimitry Andric class ScheduleDAG;
290b57cec5SDimitry Andric class SIInstrInfo;
300b57cec5SDimitry Andric class SIRegisterInfo;
310b57cec5SDimitry Andric class GCNSubtarget;
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric class GCNHazardRecognizer final : public ScheduleHazardRecognizer {
340b57cec5SDimitry Andric public:
35*fe6060f1SDimitry Andric   typedef function_ref<bool(const MachineInstr &)> IsHazardFn;
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric private:
380b57cec5SDimitry Andric   // Distinguish if we are called from scheduler or hazard recognizer
390b57cec5SDimitry Andric   bool IsHazardRecognizerMode;
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric   // This variable stores the instruction that has been emitted this cycle. It
420b57cec5SDimitry Andric   // will be added to EmittedInstrs, when AdvanceCycle() or RecedeCycle() is
430b57cec5SDimitry Andric   // called.
440b57cec5SDimitry Andric   MachineInstr *CurrCycleInstr;
450b57cec5SDimitry Andric   std::list<MachineInstr*> EmittedInstrs;
460b57cec5SDimitry Andric   const MachineFunction &MF;
470b57cec5SDimitry Andric   const GCNSubtarget &ST;
480b57cec5SDimitry Andric   const SIInstrInfo &TII;
490b57cec5SDimitry Andric   const SIRegisterInfo &TRI;
500b57cec5SDimitry Andric   TargetSchedModel TSchedModel;
51*fe6060f1SDimitry Andric   bool RunLdsBranchVmemWARHazardFixup;
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   /// RegUnits of uses in the current soft memory clause.
540b57cec5SDimitry Andric   BitVector ClauseUses;
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric   /// RegUnits of defs in the current soft memory clause.
570b57cec5SDimitry Andric   BitVector ClauseDefs;
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   void resetClause() {
600b57cec5SDimitry Andric     ClauseUses.reset();
610b57cec5SDimitry Andric     ClauseDefs.reset();
620b57cec5SDimitry Andric   }
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   void addClauseInst(const MachineInstr &MI);
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric   // Advance over a MachineInstr bundle. Look for hazards in the bundled
670b57cec5SDimitry Andric   // instructions.
680b57cec5SDimitry Andric   void processBundle();
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric   int getWaitStatesSince(IsHazardFn IsHazard, int Limit);
710b57cec5SDimitry Andric   int getWaitStatesSinceDef(unsigned Reg, IsHazardFn IsHazardDef, int Limit);
720b57cec5SDimitry Andric   int getWaitStatesSinceSetReg(IsHazardFn IsHazard, int Limit);
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   int checkSoftClauseHazards(MachineInstr *SMEM);
750b57cec5SDimitry Andric   int checkSMRDHazards(MachineInstr *SMRD);
760b57cec5SDimitry Andric   int checkVMEMHazards(MachineInstr* VMEM);
770b57cec5SDimitry Andric   int checkDPPHazards(MachineInstr *DPP);
780b57cec5SDimitry Andric   int checkDivFMasHazards(MachineInstr *DivFMas);
790b57cec5SDimitry Andric   int checkGetRegHazards(MachineInstr *GetRegInstr);
800b57cec5SDimitry Andric   int checkSetRegHazards(MachineInstr *SetRegInstr);
810b57cec5SDimitry Andric   int createsVALUHazard(const MachineInstr &MI);
820b57cec5SDimitry Andric   int checkVALUHazards(MachineInstr *VALU);
830b57cec5SDimitry Andric   int checkVALUHazardsHelper(const MachineOperand &Def, const MachineRegisterInfo &MRI);
840b57cec5SDimitry Andric   int checkRWLaneHazards(MachineInstr *RWLane);
850b57cec5SDimitry Andric   int checkRFEHazards(MachineInstr *RFE);
860b57cec5SDimitry Andric   int checkInlineAsmHazards(MachineInstr *IA);
870b57cec5SDimitry Andric   int checkReadM0Hazards(MachineInstr *SMovRel);
880b57cec5SDimitry Andric   int checkNSAtoVMEMHazard(MachineInstr *MI);
890b57cec5SDimitry Andric   int checkFPAtomicToDenormModeHazard(MachineInstr *MI);
900b57cec5SDimitry Andric   void fixHazards(MachineInstr *MI);
910b57cec5SDimitry Andric   bool fixVcmpxPermlaneHazards(MachineInstr *MI);
920b57cec5SDimitry Andric   bool fixVMEMtoScalarWriteHazards(MachineInstr *MI);
930b57cec5SDimitry Andric   bool fixSMEMtoVectorWriteHazards(MachineInstr *MI);
940b57cec5SDimitry Andric   bool fixVcmpxExecWARHazard(MachineInstr *MI);
950b57cec5SDimitry Andric   bool fixLdsBranchVmemWARHazard(MachineInstr *MI);
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric   int checkMAIHazards(MachineInstr *MI);
98*fe6060f1SDimitry Andric   int checkMAIHazards908(MachineInstr *MI);
99*fe6060f1SDimitry Andric   int checkMAIHazards90A(MachineInstr *MI);
100*fe6060f1SDimitry Andric   int checkMAIVALUHazards(MachineInstr *MI);
1010b57cec5SDimitry Andric   int checkMAILdStHazards(MachineInstr *MI);
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric public:
1040b57cec5SDimitry Andric   GCNHazardRecognizer(const MachineFunction &MF);
1050b57cec5SDimitry Andric   // We can only issue one instruction per cycle.
1060b57cec5SDimitry Andric   bool atIssueLimit() const override { return true; }
1070b57cec5SDimitry Andric   void EmitInstruction(SUnit *SU) override;
1080b57cec5SDimitry Andric   void EmitInstruction(MachineInstr *MI) override;
1090b57cec5SDimitry Andric   HazardType getHazardType(SUnit *SU, int Stalls) override;
1100b57cec5SDimitry Andric   void EmitNoop() override;
1110b57cec5SDimitry Andric   unsigned PreEmitNoops(MachineInstr *) override;
1120b57cec5SDimitry Andric   unsigned PreEmitNoopsCommon(MachineInstr *);
1130b57cec5SDimitry Andric   void AdvanceCycle() override;
1140b57cec5SDimitry Andric   void RecedeCycle() override;
115e8d8bef9SDimitry Andric   bool ShouldPreferAnother(SUnit *SU) override;
116e8d8bef9SDimitry Andric   void Reset() override;
1170b57cec5SDimitry Andric };
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric } // end namespace llvm
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric #endif //LLVM_LIB_TARGET_AMDGPUHAZARDRECOGNIZERS_H
122