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