xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.h (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
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:
350b57cec5SDimitry Andric   typedef function_ref<bool(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;
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   /// RegUnits of uses in the current soft memory clause.
530b57cec5SDimitry Andric   BitVector ClauseUses;
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   /// RegUnits of defs in the current soft memory clause.
560b57cec5SDimitry Andric   BitVector ClauseDefs;
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric   void resetClause() {
590b57cec5SDimitry Andric     ClauseUses.reset();
600b57cec5SDimitry Andric     ClauseDefs.reset();
610b57cec5SDimitry Andric   }
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric   void addClauseInst(const MachineInstr &MI);
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric   // Advance over a MachineInstr bundle. Look for hazards in the bundled
660b57cec5SDimitry Andric   // instructions.
670b57cec5SDimitry Andric   void processBundle();
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric   int getWaitStatesSince(IsHazardFn IsHazard, int Limit);
700b57cec5SDimitry Andric   int getWaitStatesSinceDef(unsigned Reg, IsHazardFn IsHazardDef, int Limit);
710b57cec5SDimitry Andric   int getWaitStatesSinceSetReg(IsHazardFn IsHazard, int Limit);
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   int checkSoftClauseHazards(MachineInstr *SMEM);
740b57cec5SDimitry Andric   int checkSMRDHazards(MachineInstr *SMRD);
750b57cec5SDimitry Andric   int checkVMEMHazards(MachineInstr* VMEM);
760b57cec5SDimitry Andric   int checkDPPHazards(MachineInstr *DPP);
770b57cec5SDimitry Andric   int checkDivFMasHazards(MachineInstr *DivFMas);
780b57cec5SDimitry Andric   int checkGetRegHazards(MachineInstr *GetRegInstr);
790b57cec5SDimitry Andric   int checkSetRegHazards(MachineInstr *SetRegInstr);
800b57cec5SDimitry Andric   int createsVALUHazard(const MachineInstr &MI);
810b57cec5SDimitry Andric   int checkVALUHazards(MachineInstr *VALU);
820b57cec5SDimitry Andric   int checkVALUHazardsHelper(const MachineOperand &Def, const MachineRegisterInfo &MRI);
830b57cec5SDimitry Andric   int checkRWLaneHazards(MachineInstr *RWLane);
840b57cec5SDimitry Andric   int checkRFEHazards(MachineInstr *RFE);
850b57cec5SDimitry Andric   int checkInlineAsmHazards(MachineInstr *IA);
860b57cec5SDimitry Andric   int checkReadM0Hazards(MachineInstr *SMovRel);
870b57cec5SDimitry Andric   int checkNSAtoVMEMHazard(MachineInstr *MI);
880b57cec5SDimitry Andric   int checkFPAtomicToDenormModeHazard(MachineInstr *MI);
890b57cec5SDimitry Andric   void fixHazards(MachineInstr *MI);
900b57cec5SDimitry Andric   bool fixVcmpxPermlaneHazards(MachineInstr *MI);
910b57cec5SDimitry Andric   bool fixVMEMtoScalarWriteHazards(MachineInstr *MI);
920b57cec5SDimitry Andric   bool fixSMEMtoVectorWriteHazards(MachineInstr *MI);
930b57cec5SDimitry Andric   bool fixVcmpxExecWARHazard(MachineInstr *MI);
940b57cec5SDimitry Andric   bool fixLdsBranchVmemWARHazard(MachineInstr *MI);
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   int checkMAIHazards(MachineInstr *MI);
970b57cec5SDimitry Andric   int checkMAILdStHazards(MachineInstr *MI);
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric public:
1000b57cec5SDimitry Andric   GCNHazardRecognizer(const MachineFunction &MF);
1010b57cec5SDimitry Andric   // We can only issue one instruction per cycle.
1020b57cec5SDimitry Andric   bool atIssueLimit() const override { return true; }
1030b57cec5SDimitry Andric   void EmitInstruction(SUnit *SU) override;
1040b57cec5SDimitry Andric   void EmitInstruction(MachineInstr *MI) override;
1050b57cec5SDimitry Andric   HazardType getHazardType(SUnit *SU, int Stalls) override;
1060b57cec5SDimitry Andric   void EmitNoop() override;
1070b57cec5SDimitry Andric   unsigned PreEmitNoops(MachineInstr *) override;
1080b57cec5SDimitry Andric   unsigned PreEmitNoopsCommon(MachineInstr *);
1090b57cec5SDimitry Andric   void AdvanceCycle() override;
1100b57cec5SDimitry Andric   void RecedeCycle() override;
111*e8d8bef9SDimitry Andric   bool ShouldPreferAnother(SUnit *SU) override;
112*e8d8bef9SDimitry Andric   void Reset() override;
1130b57cec5SDimitry Andric };
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric } // end namespace llvm
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric #endif //LLVM_LIB_TARGET_AMDGPUHAZARDRECOGNIZERS_H
118