| //===------------------- AMDGPUCustomBehaviour.h ----------------*-C++ -* -===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| /// \file |
| /// |
| /// This file defines the AMDGPUCustomBehaviour class which inherits from |
| /// CustomBehaviour. This class is used by the tool llvm-mca to enforce |
| /// target specific behaviour that is not expressed well enough in the |
| /// scheduling model for mca to enforce it automatically. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_LIB_TARGET_AMDGPU_MCA_AMDGPUCUSTOMBEHAVIOUR_H |
| #define LLVM_LIB_TARGET_AMDGPU_MCA_AMDGPUCUSTOMBEHAVIOUR_H |
| |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/MCA/CustomBehaviour.h" |
| #include "llvm/Support/TargetParser.h" |
| |
| namespace llvm { |
| namespace mca { |
| |
| class AMDGPUInstrPostProcess : public InstrPostProcess { |
| void processWaitCnt(std::unique_ptr<Instruction> &Inst, const MCInst &MCI); |
| |
| public: |
| AMDGPUInstrPostProcess(const MCSubtargetInfo &STI, const MCInstrInfo &MCII) |
| : InstrPostProcess(STI, MCII) {} |
| |
| ~AMDGPUInstrPostProcess() {} |
| |
| void postProcessInstruction(std::unique_ptr<Instruction> &Inst, |
| const MCInst &MCI) override; |
| }; |
| |
| struct WaitCntInfo { |
| bool VmCnt = false; |
| bool ExpCnt = false; |
| bool LgkmCnt = false; |
| bool VsCnt = false; |
| }; |
| |
| class AMDGPUCustomBehaviour : public CustomBehaviour { |
| /// Whenever MCA would like to dispatch an s_waitcnt instructions, |
| /// we must check all the instruction that are still executing to see if |
| /// they modify the same CNT as we need to wait for. This vector |
| /// gets built in the constructor and contains 1 WaitCntInfo struct |
| /// for each instruction within the SrcManager. Each element |
| /// tells us which CNTs that instruction may interact with. |
| /// We conservatively assume some instructions interact with more |
| /// CNTs than they do in reality, so we will occasionally wait |
| /// longer than necessary, but we shouldn't ever wait for shorter. |
| std::vector<WaitCntInfo> InstrWaitCntInfo; |
| |
| /// This method gets called from the constructor and is |
| /// where we setup the InstrWaitCntInfo vector. |
| /// The core logic for determining which CNTs an instruction |
| /// interacts with is taken from SIInsertWaitcnts::updateEventWaitcntAfter(). |
| /// Unfortunately, some of the logic from that function is not available to us |
| /// in this scope so we conservatively end up assuming that some |
| /// instructions interact with more CNTs than they do in reality. |
| void generateWaitCntInfo(); |
| /// Helper function used in generateWaitCntInfo() |
| bool hasModifiersSet(const std::unique_ptr<Instruction> &Inst, |
| unsigned OpName) const; |
| /// Helper function used in generateWaitCntInfo() |
| bool isAlwaysGDS(uint16_t Opcode) const; |
| /// Helper function used in generateWaitCntInfo() |
| bool isVMEM(const MCInstrDesc &MCID); |
| /// This method gets called from checkCustomHazard when mca is attempting to |
| /// dispatch an s_waitcnt instruction (or one of its variants). The method |
| /// looks at each of the instructions that are still executing in the pipeline |
| /// to determine if the waitcnt should force a wait. |
| unsigned handleWaitCnt(ArrayRef<InstRef> IssuedInst, const InstRef &IR); |
| /// Based on the type of s_waitcnt instruction we are looking at, and what its |
| /// operands are, this method will set the values for each of the cnt |
| /// references provided as arguments. |
| void computeWaitCnt(const InstRef &IR, unsigned &Vmcnt, unsigned &Expcnt, |
| unsigned &Lgkmcnt, unsigned &Vscnt); |
| |
| public: |
| AMDGPUCustomBehaviour(const MCSubtargetInfo &STI, |
| const mca::SourceMgr &SrcMgr, const MCInstrInfo &MCII); |
| |
| ~AMDGPUCustomBehaviour() {} |
| /// This method is used to determine if an instruction |
| /// should be allowed to be dispatched. The return value is |
| /// how many cycles until the instruction can be dispatched. |
| /// This method is called after MCA has already checked for |
| /// register and hardware dependencies so this method should only |
| /// implement custom behaviour and dependencies that are not picked up |
| /// by MCA naturally. |
| unsigned checkCustomHazard(ArrayRef<InstRef> IssuedInst, |
| const InstRef &IR) override; |
| }; |
| } // namespace mca |
| } // namespace llvm |
| |
| #endif |