llvm-project/llvm/lib/Target/AMDGPU/MCA/AMDGPUCustomBehaviour.h
Aiden Grossman a04d3cab29
[MCA] Use Bare Reference for InstrPostProcess (#160229)
This patch makes it so that InstrPostProcess::postProcessInstruction
takes in a reference to a mca::Instruction rather than a reference to a
std::unique_ptr. Without this, InstrPostProcess cannot be used with MCA
instruction recycling because it needs to be called on both newly
created instructions and instructions that have been recycled. We only
have access to a raw pointer for instructions that have been recycled
rather than a reference to the std::unique_ptr that owns them.

This patch adds a call in the existing instruction recycling unit test
to ensure the API remains compatible with this use case.
2025-09-23 13:59:25 +00:00

106 lines
4.5 KiB
C++

//===------------------- 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 "Utils/AMDGPUBaseInfo.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/MCA/CustomBehaviour.h"
#include "llvm/TargetParser/TargetParser.h"
namespace llvm {
namespace mca {
class AMDGPUInstrPostProcess : public InstrPostProcess {
void processWaitCnt(Instruction &Inst, const MCInst &MCI);
public:
AMDGPUInstrPostProcess(const MCSubtargetInfo &STI, const MCInstrInfo &MCII)
: InstrPostProcess(STI, MCII) {}
~AMDGPUInstrPostProcess() = default;
void postProcessInstruction(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,
AMDGPU::OpName OpName) const;
/// Helper function used in generateWaitCntInfo()
bool isGWS(uint16_t Opcode) 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() = default;
/// 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