1349cc55cSDimitry Andric //===------------------- AMDGPUCustomBehaviour.h ----------------*-C++ -* -===// 2349cc55cSDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6349cc55cSDimitry Andric // 7349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 8349cc55cSDimitry Andric /// \file 9349cc55cSDimitry Andric /// 10349cc55cSDimitry Andric /// This file defines the AMDGPUCustomBehaviour class which inherits from 11349cc55cSDimitry Andric /// CustomBehaviour. This class is used by the tool llvm-mca to enforce 12349cc55cSDimitry Andric /// target specific behaviour that is not expressed well enough in the 13349cc55cSDimitry Andric /// scheduling model for mca to enforce it automatically. 14349cc55cSDimitry Andric /// 15349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 16349cc55cSDimitry Andric 17349cc55cSDimitry Andric #ifndef LLVM_LIB_TARGET_AMDGPU_MCA_AMDGPUCUSTOMBEHAVIOUR_H 18349cc55cSDimitry Andric #define LLVM_LIB_TARGET_AMDGPU_MCA_AMDGPUCUSTOMBEHAVIOUR_H 19349cc55cSDimitry Andric 20349cc55cSDimitry Andric #include "llvm/ADT/SmallVector.h" 21349cc55cSDimitry Andric #include "llvm/MCA/CustomBehaviour.h" 2206c3fb27SDimitry Andric #include "llvm/TargetParser/TargetParser.h" 23349cc55cSDimitry Andric 24349cc55cSDimitry Andric namespace llvm { 25349cc55cSDimitry Andric namespace mca { 26349cc55cSDimitry Andric 27349cc55cSDimitry Andric class AMDGPUInstrPostProcess : public InstrPostProcess { 28349cc55cSDimitry Andric void processWaitCnt(std::unique_ptr<Instruction> &Inst, const MCInst &MCI); 29349cc55cSDimitry Andric 30349cc55cSDimitry Andric public: AMDGPUInstrPostProcess(const MCSubtargetInfo & STI,const MCInstrInfo & MCII)31349cc55cSDimitry Andric AMDGPUInstrPostProcess(const MCSubtargetInfo &STI, const MCInstrInfo &MCII) 32349cc55cSDimitry Andric : InstrPostProcess(STI, MCII) {} 33349cc55cSDimitry Andric 3481ad6265SDimitry Andric ~AMDGPUInstrPostProcess() = default; 35349cc55cSDimitry Andric 36349cc55cSDimitry Andric void postProcessInstruction(std::unique_ptr<Instruction> &Inst, 37349cc55cSDimitry Andric const MCInst &MCI) override; 38349cc55cSDimitry Andric }; 39349cc55cSDimitry Andric 40349cc55cSDimitry Andric struct WaitCntInfo { 41349cc55cSDimitry Andric bool VmCnt = false; 42349cc55cSDimitry Andric bool ExpCnt = false; 43349cc55cSDimitry Andric bool LgkmCnt = false; 44349cc55cSDimitry Andric bool VsCnt = false; 45349cc55cSDimitry Andric }; 46349cc55cSDimitry Andric 47349cc55cSDimitry Andric class AMDGPUCustomBehaviour : public CustomBehaviour { 48349cc55cSDimitry Andric /// Whenever MCA would like to dispatch an s_waitcnt instructions, 49349cc55cSDimitry Andric /// we must check all the instruction that are still executing to see if 50349cc55cSDimitry Andric /// they modify the same CNT as we need to wait for. This vector 51349cc55cSDimitry Andric /// gets built in the constructor and contains 1 WaitCntInfo struct 52349cc55cSDimitry Andric /// for each instruction within the SrcManager. Each element 53349cc55cSDimitry Andric /// tells us which CNTs that instruction may interact with. 54349cc55cSDimitry Andric /// We conservatively assume some instructions interact with more 55349cc55cSDimitry Andric /// CNTs than they do in reality, so we will occasionally wait 56349cc55cSDimitry Andric /// longer than necessary, but we shouldn't ever wait for shorter. 57349cc55cSDimitry Andric std::vector<WaitCntInfo> InstrWaitCntInfo; 58349cc55cSDimitry Andric 59349cc55cSDimitry Andric /// This method gets called from the constructor and is 60349cc55cSDimitry Andric /// where we setup the InstrWaitCntInfo vector. 61349cc55cSDimitry Andric /// The core logic for determining which CNTs an instruction 62349cc55cSDimitry Andric /// interacts with is taken from SIInsertWaitcnts::updateEventWaitcntAfter(). 63349cc55cSDimitry Andric /// Unfortunately, some of the logic from that function is not available to us 64349cc55cSDimitry Andric /// in this scope so we conservatively end up assuming that some 65349cc55cSDimitry Andric /// instructions interact with more CNTs than they do in reality. 66349cc55cSDimitry Andric void generateWaitCntInfo(); 67349cc55cSDimitry Andric /// Helper function used in generateWaitCntInfo() 68349cc55cSDimitry Andric bool hasModifiersSet(const std::unique_ptr<Instruction> &Inst, 69349cc55cSDimitry Andric unsigned OpName) const; 70349cc55cSDimitry Andric /// Helper function used in generateWaitCntInfo() 71*5f757f3fSDimitry Andric bool isGWS(uint16_t Opcode) const; 72*5f757f3fSDimitry Andric /// Helper function used in generateWaitCntInfo() 73349cc55cSDimitry Andric bool isAlwaysGDS(uint16_t Opcode) const; 74349cc55cSDimitry Andric /// Helper function used in generateWaitCntInfo() 75349cc55cSDimitry Andric bool isVMEM(const MCInstrDesc &MCID); 76349cc55cSDimitry Andric /// This method gets called from checkCustomHazard when mca is attempting to 77349cc55cSDimitry Andric /// dispatch an s_waitcnt instruction (or one of its variants). The method 78349cc55cSDimitry Andric /// looks at each of the instructions that are still executing in the pipeline 79349cc55cSDimitry Andric /// to determine if the waitcnt should force a wait. 80349cc55cSDimitry Andric unsigned handleWaitCnt(ArrayRef<InstRef> IssuedInst, const InstRef &IR); 81349cc55cSDimitry Andric /// Based on the type of s_waitcnt instruction we are looking at, and what its 82349cc55cSDimitry Andric /// operands are, this method will set the values for each of the cnt 83349cc55cSDimitry Andric /// references provided as arguments. 84349cc55cSDimitry Andric void computeWaitCnt(const InstRef &IR, unsigned &Vmcnt, unsigned &Expcnt, 85349cc55cSDimitry Andric unsigned &Lgkmcnt, unsigned &Vscnt); 86349cc55cSDimitry Andric 87349cc55cSDimitry Andric public: 88349cc55cSDimitry Andric AMDGPUCustomBehaviour(const MCSubtargetInfo &STI, 89349cc55cSDimitry Andric const mca::SourceMgr &SrcMgr, const MCInstrInfo &MCII); 90349cc55cSDimitry Andric 9181ad6265SDimitry Andric ~AMDGPUCustomBehaviour() = default; 92349cc55cSDimitry Andric /// This method is used to determine if an instruction 93349cc55cSDimitry Andric /// should be allowed to be dispatched. The return value is 94349cc55cSDimitry Andric /// how many cycles until the instruction can be dispatched. 95349cc55cSDimitry Andric /// This method is called after MCA has already checked for 96349cc55cSDimitry Andric /// register and hardware dependencies so this method should only 97349cc55cSDimitry Andric /// implement custom behaviour and dependencies that are not picked up 98349cc55cSDimitry Andric /// by MCA naturally. 99349cc55cSDimitry Andric unsigned checkCustomHazard(ArrayRef<InstRef> IssuedInst, 100349cc55cSDimitry Andric const InstRef &IR) override; 101349cc55cSDimitry Andric }; 102349cc55cSDimitry Andric } // namespace mca 103349cc55cSDimitry Andric } // namespace llvm 104349cc55cSDimitry Andric 105349cc55cSDimitry Andric #endif 106