1 //===------------------- AMDGPUCustomBehaviour.h ----------------*-C++ -* -===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// \file 9 /// 10 /// This file defines the AMDGPUCustomBehaviour class which inherits from 11 /// CustomBehaviour. This class is used by the tool llvm-mca to enforce 12 /// target specific behaviour that is not expressed well enough in the 13 /// scheduling model for mca to enforce it automatically. 14 /// 15 //===----------------------------------------------------------------------===// 16 17 #ifndef LLVM_LIB_TARGET_AMDGPU_MCA_AMDGPUCUSTOMBEHAVIOUR_H 18 #define LLVM_LIB_TARGET_AMDGPU_MCA_AMDGPUCUSTOMBEHAVIOUR_H 19 20 #include "llvm/ADT/SmallVector.h" 21 #include "llvm/MCA/CustomBehaviour.h" 22 #include "llvm/TargetParser/TargetParser.h" 23 24 namespace llvm { 25 namespace mca { 26 27 class AMDGPUInstrPostProcess : public InstrPostProcess { 28 void processWaitCnt(std::unique_ptr<Instruction> &Inst, const MCInst &MCI); 29 30 public: 31 AMDGPUInstrPostProcess(const MCSubtargetInfo &STI, const MCInstrInfo &MCII) 32 : InstrPostProcess(STI, MCII) {} 33 34 ~AMDGPUInstrPostProcess() = default; 35 36 void postProcessInstruction(std::unique_ptr<Instruction> &Inst, 37 const MCInst &MCI) override; 38 }; 39 40 struct WaitCntInfo { 41 bool VmCnt = false; 42 bool ExpCnt = false; 43 bool LgkmCnt = false; 44 bool VsCnt = false; 45 }; 46 47 class AMDGPUCustomBehaviour : public CustomBehaviour { 48 /// Whenever MCA would like to dispatch an s_waitcnt instructions, 49 /// we must check all the instruction that are still executing to see if 50 /// they modify the same CNT as we need to wait for. This vector 51 /// gets built in the constructor and contains 1 WaitCntInfo struct 52 /// for each instruction within the SrcManager. Each element 53 /// tells us which CNTs that instruction may interact with. 54 /// We conservatively assume some instructions interact with more 55 /// CNTs than they do in reality, so we will occasionally wait 56 /// longer than necessary, but we shouldn't ever wait for shorter. 57 std::vector<WaitCntInfo> InstrWaitCntInfo; 58 59 /// This method gets called from the constructor and is 60 /// where we setup the InstrWaitCntInfo vector. 61 /// The core logic for determining which CNTs an instruction 62 /// interacts with is taken from SIInsertWaitcnts::updateEventWaitcntAfter(). 63 /// Unfortunately, some of the logic from that function is not available to us 64 /// in this scope so we conservatively end up assuming that some 65 /// instructions interact with more CNTs than they do in reality. 66 void generateWaitCntInfo(); 67 /// Helper function used in generateWaitCntInfo() 68 bool hasModifiersSet(const std::unique_ptr<Instruction> &Inst, 69 unsigned OpName) const; 70 /// Helper function used in generateWaitCntInfo() 71 bool isGWS(uint16_t Opcode) const; 72 /// Helper function used in generateWaitCntInfo() 73 bool isAlwaysGDS(uint16_t Opcode) const; 74 /// Helper function used in generateWaitCntInfo() 75 bool isVMEM(const MCInstrDesc &MCID); 76 /// This method gets called from checkCustomHazard when mca is attempting to 77 /// dispatch an s_waitcnt instruction (or one of its variants). The method 78 /// looks at each of the instructions that are still executing in the pipeline 79 /// to determine if the waitcnt should force a wait. 80 unsigned handleWaitCnt(ArrayRef<InstRef> IssuedInst, const InstRef &IR); 81 /// Based on the type of s_waitcnt instruction we are looking at, and what its 82 /// operands are, this method will set the values for each of the cnt 83 /// references provided as arguments. 84 void computeWaitCnt(const InstRef &IR, unsigned &Vmcnt, unsigned &Expcnt, 85 unsigned &Lgkmcnt, unsigned &Vscnt); 86 87 public: 88 AMDGPUCustomBehaviour(const MCSubtargetInfo &STI, 89 const mca::SourceMgr &SrcMgr, const MCInstrInfo &MCII); 90 91 ~AMDGPUCustomBehaviour() = default; 92 /// This method is used to determine if an instruction 93 /// should be allowed to be dispatched. The return value is 94 /// how many cycles until the instruction can be dispatched. 95 /// This method is called after MCA has already checked for 96 /// register and hardware dependencies so this method should only 97 /// implement custom behaviour and dependencies that are not picked up 98 /// by MCA naturally. 99 unsigned checkCustomHazard(ArrayRef<InstRef> IssuedInst, 100 const InstRef &IR) override; 101 }; 102 } // namespace mca 103 } // namespace llvm 104 105 #endif 106