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