106 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8/// \file9///10/// This file defines the AMDGPUCustomBehaviour class which inherits from11/// CustomBehaviour. This class is used by the tool llvm-mca to enforce12/// target specific behaviour that is not expressed well enough in the13/// scheduling model for mca to enforce it automatically.14///15//===----------------------------------------------------------------------===//16 17#ifndef LLVM_LIB_TARGET_AMDGPU_MCA_AMDGPUCUSTOMBEHAVIOUR_H18#define LLVM_LIB_TARGET_AMDGPU_MCA_AMDGPUCUSTOMBEHAVIOUR_H19 20#include "Utils/AMDGPUBaseInfo.h"21#include "llvm/ADT/SmallVector.h"22#include "llvm/MCA/CustomBehaviour.h"23#include "llvm/TargetParser/TargetParser.h"24 25namespace llvm {26namespace mca {27 28class AMDGPUInstrPostProcess : public InstrPostProcess {29 void processWaitCnt(Instruction &Inst, const MCInst &MCI);30 31public:32 AMDGPUInstrPostProcess(const MCSubtargetInfo &STI, const MCInstrInfo &MCII)33 : InstrPostProcess(STI, MCII) {}34 35 ~AMDGPUInstrPostProcess() override = default;36 37 void postProcessInstruction(Instruction &Inst, const MCInst &MCI) override;38};39 40struct WaitCntInfo {41 bool VmCnt = false;42 bool ExpCnt = false;43 bool LgkmCnt = false;44 bool VsCnt = false;45};46 47class 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 if50 /// they modify the same CNT as we need to wait for. This vector51 /// gets built in the constructor and contains 1 WaitCntInfo struct52 /// for each instruction within the SrcManager. Each element53 /// tells us which CNTs that instruction may interact with.54 /// We conservatively assume some instructions interact with more55 /// CNTs than they do in reality, so we will occasionally wait56 /// 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 is60 /// where we setup the InstrWaitCntInfo vector.61 /// The core logic for determining which CNTs an instruction62 /// interacts with is taken from SIInsertWaitcnts::updateEventWaitcntAfter().63 /// Unfortunately, some of the logic from that function is not available to us64 /// in this scope so we conservatively end up assuming that some65 /// 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 AMDGPU::OpName 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 to77 /// dispatch an s_waitcnt instruction (or one of its variants). The method78 /// looks at each of the instructions that are still executing in the pipeline79 /// 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 its82 /// operands are, this method will set the values for each of the cnt83 /// references provided as arguments.84 void computeWaitCnt(const InstRef &IR, unsigned &Vmcnt, unsigned &Expcnt,85 unsigned &Lgkmcnt, unsigned &Vscnt);86 87public:88 AMDGPUCustomBehaviour(const MCSubtargetInfo &STI,89 const mca::SourceMgr &SrcMgr, const MCInstrInfo &MCII);90 91 ~AMDGPUCustomBehaviour() override = default;92 /// This method is used to determine if an instruction93 /// should be allowed to be dispatched. The return value is94 /// how many cycles until the instruction can be dispatched.95 /// This method is called after MCA has already checked for96 /// register and hardware dependencies so this method should only97 /// implement custom behaviour and dependencies that are not picked up98 /// by MCA naturally.99 unsigned checkCustomHazard(ArrayRef<InstRef> IssuedInst,100 const InstRef &IR) override;101};102} // namespace mca103} // namespace llvm104 105#endif106