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/Support/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 isAlwaysGDS(uint16_t Opcode) const; 72 /// Helper function used in generateWaitCntInfo() 73 bool isVMEM(const MCInstrDesc &MCID); 74 /// This method gets called from checkCustomHazard when mca is attempting to 75 /// dispatch an s_waitcnt instruction (or one of its variants). The method 76 /// looks at each of the instructions that are still executing in the pipeline 77 /// to determine if the waitcnt should force a wait. 78 unsigned handleWaitCnt(ArrayRef<InstRef> IssuedInst, const InstRef &IR); 79 /// Based on the type of s_waitcnt instruction we are looking at, and what its 80 /// operands are, this method will set the values for each of the cnt 81 /// references provided as arguments. 82 void computeWaitCnt(const InstRef &IR, unsigned &Vmcnt, unsigned &Expcnt, 83 unsigned &Lgkmcnt, unsigned &Vscnt); 84 85 public: 86 AMDGPUCustomBehaviour(const MCSubtargetInfo &STI, 87 const mca::SourceMgr &SrcMgr, const MCInstrInfo &MCII); 88 89 ~AMDGPUCustomBehaviour() = default; 90 /// This method is used to determine if an instruction 91 /// should be allowed to be dispatched. The return value is 92 /// how many cycles until the instruction can be dispatched. 93 /// This method is called after MCA has already checked for 94 /// register and hardware dependencies so this method should only 95 /// implement custom behaviour and dependencies that are not picked up 96 /// by MCA naturally. 97 unsigned checkCustomHazard(ArrayRef<InstRef> IssuedInst, 98 const InstRef &IR) override; 99 }; 100 } // namespace mca 101 } // namespace llvm 102 103 #endif 104