Skip to content

[AMDGPU][MC] Disable sendmsg SYSMSG_OP_HOST_TRAP_ACK on gfx9+ #90203

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7436,7 +7436,8 @@ AMDGPUAsmParser::parseSendMsgBody(OperandInfoTy &Msg,
Op.IsDefined = true;
Op.Loc = getLoc();
if (isToken(AsmToken::Identifier) &&
(Op.Val = getMsgOpId(Msg.Val, getTokenStr())) >= 0) {
(Op.Val = getMsgOpId(Msg.Val, getTokenStr(), getSTI())) !=
OPR_ID_UNKNOWN) {
lex(); // skip operation name
} else if (!parseExpr(Op.Val, "an operation name")) {
return false;
Expand Down Expand Up @@ -7484,7 +7485,10 @@ AMDGPUAsmParser::validateSendMsg(const OperandInfoTy &Msg,
return false;
}
if (!isValidMsgOp(Msg.Val, Op.Val, getSTI(), Strict)) {
Error(Op.Loc, "invalid operation id");
if (Op.Val == OPR_ID_UNSUPPORTED)
Error(Op.Loc, "specified operation id is not supported on this GPU");
else
Error(Op.Loc, "invalid operation id");
return false;
}
if (Strict && !msgSupportsStream(Msg.Val, Op.Val, getSTI()) &&
Expand Down
3 changes: 0 additions & 3 deletions llvm/lib/Target/AMDGPU/SIDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,6 @@ enum Id { // Message ID, width(4) [3:0].
};

enum Op { // Both GS and SYS operation IDs.
OP_UNKNOWN_ = -1,
OP_SHIFT_ = 4,
OP_NONE_ = 0,
// Bits used for operation encoding
Expand All @@ -479,14 +478,12 @@ enum Op { // Both GS and SYS operation IDs.
OP_GS_CUT = 1,
OP_GS_EMIT = 2,
OP_GS_EMIT_CUT = 3,
OP_GS_LAST_,
OP_GS_FIRST_ = OP_GS_NOP,
// SYS operations are encoded in bits 6:4
OP_SYS_ECC_ERR_INTERRUPT = 1,
OP_SYS_REG_RD = 2,
OP_SYS_HOST_TRAP_ACK = 3,
OP_SYS_TTRACE_PC = 4,
OP_SYS_LAST_,
OP_SYS_FIRST_ = OP_SYS_ECC_ERR_INTERRUPT,
};

Expand Down
122 changes: 101 additions & 21 deletions llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,60 @@
namespace llvm {
namespace AMDGPU {

//===----------------------------------------------------------------------===//
// Custom Operands.
//
// A table of custom operands shall describe "primary" operand names first
// followed by aliases if any. It is not required but recommended to arrange
// operands so that operand encoding match operand position in the table. This
// will make getNameFromOperandTable() a bit more efficient. Unused slots in the
// table shall have an empty name.
//
//===----------------------------------------------------------------------===//

/// Map from the encoding of a sendmsg/hwreg asm operand to it's name.
template <size_t N>
static StringRef getNameFromOperandTable(const CustomOperand (&Table)[N],
unsigned Encoding,
const MCSubtargetInfo &STI) {
auto isValidIndexForEncoding = [&](size_t Idx) {
return Idx < N && Table[Idx].Encoding == Encoding &&
!Table[Idx].Name.empty() &&
(!Table[Idx].Cond || Table[Idx].Cond(STI));
};

// This is an optimization that should work in most cases. As a side effect,
// it may cause selection of an alias instead of a primary operand name in
// case of sparse tables.
if (isValidIndexForEncoding(Encoding))
return Table[Encoding].Name;

for (size_t Idx = 0; Idx != N; ++Idx)
if (isValidIndexForEncoding(Idx))
return Table[Idx].Name;

return "";
}

/// Map from a symbolic name for a sendmsg/hwreg asm operand to it's encoding.
template <size_t N>
static int64_t getEncodingFromOperandTable(const CustomOperand (&Table)[N],
StringRef Name,
const MCSubtargetInfo &STI) {
int64_t InvalidEncoding = OPR_ID_UNKNOWN;
for (const CustomOperand &Entry : Table) {
if (Entry.Name != Name)
continue;

if (!Entry.Cond || Entry.Cond(STI))
return Entry.Encoding;

InvalidEncoding = OPR_ID_UNSUPPORTED;
}

return InvalidEncoding;
}

namespace DepCtr {

// NOLINTBEGIN
Expand All @@ -34,10 +88,11 @@ const int DEP_CTR_SIZE =

namespace SendMsg {

// Disable lint checking for this block since it makes the table unreadable.
// Disable lint checking here since it makes these tables unreadable.
// NOLINTBEGIN
// clang-format off
const CustomOperand<const MCSubtargetInfo &> Msg[] = {

static constexpr CustomOperand MsgOperands[] = {
{{""}},
{{"MSG_INTERRUPT"}, ID_INTERRUPT},
{{"MSG_GS"}, ID_GS_PreGFX11, isNotGFX11Plus},
Expand All @@ -63,27 +118,47 @@ const CustomOperand<const MCSubtargetInfo &> Msg[] = {
{{"MSG_RTN_GET_TBA_TO_PC"}, ID_RTN_GET_TBA_TO_PC, isGFX11Plus},
{{"MSG_RTN_GET_SE_AID_ID"}, ID_RTN_GET_SE_AID_ID, isGFX12Plus},
};

static constexpr CustomOperand SysMsgOperands[] = {
{{""}},
{{"SYSMSG_OP_ECC_ERR_INTERRUPT"}, OP_SYS_ECC_ERR_INTERRUPT},
{{"SYSMSG_OP_REG_RD"}, OP_SYS_REG_RD},
{{"SYSMSG_OP_HOST_TRAP_ACK"}, OP_SYS_HOST_TRAP_ACK, isNotGFX9Plus},
{{"SYSMSG_OP_TTRACE_PC"}, OP_SYS_TTRACE_PC},
};

static constexpr CustomOperand StreamMsgOperands[] = {
{{"GS_OP_NOP"}, OP_GS_NOP},
{{"GS_OP_CUT"}, OP_GS_CUT},
{{"GS_OP_EMIT"}, OP_GS_EMIT},
{{"GS_OP_EMIT_CUT"}, OP_GS_EMIT_CUT},
};

// clang-format on
// NOLINTEND

const int MSG_SIZE = static_cast<int>(
sizeof(Msg) / sizeof(CustomOperand<const MCSubtargetInfo &>));
int64_t getMsgId(StringRef Name, const MCSubtargetInfo &STI) {
return getEncodingFromOperandTable(MsgOperands, Name, STI);
}

// These two must be in sync with llvm::AMDGPU::SendMsg::Op enum members, see SIDefines.h.
const char *const OpSysSymbolic[OP_SYS_LAST_] = {
nullptr,
"SYSMSG_OP_ECC_ERR_INTERRUPT",
"SYSMSG_OP_REG_RD",
"SYSMSG_OP_HOST_TRAP_ACK",
"SYSMSG_OP_TTRACE_PC"
};
StringRef getMsgName(uint64_t Encoding, const MCSubtargetInfo &STI) {
return getNameFromOperandTable(MsgOperands, Encoding, STI);
}

const char *const OpGsSymbolic[OP_GS_LAST_] = {
"GS_OP_NOP",
"GS_OP_CUT",
"GS_OP_EMIT",
"GS_OP_EMIT_CUT"
};
int64_t getMsgOpId(int64_t MsgId, StringRef Name, const MCSubtargetInfo &STI) {
if (MsgId == ID_SYSMSG)
return getEncodingFromOperandTable(SysMsgOperands, Name, STI);
return getEncodingFromOperandTable(StreamMsgOperands, Name, STI);
}

StringRef getMsgOpName(int64_t MsgId, uint64_t Encoding,
const MCSubtargetInfo &STI) {
assert(msgRequiresOp(MsgId, STI) && "must have an operand");

if (MsgId == ID_SYSMSG)
return getNameFromOperandTable(SysMsgOperands, Encoding, STI);
return getNameFromOperandTable(StreamMsgOperands, Encoding, STI);
}

} // namespace SendMsg

Expand All @@ -92,7 +167,7 @@ namespace Hwreg {
// Disable lint checking for this block since it makes the table unreadable.
// NOLINTBEGIN
// clang-format off
const CustomOperand<const MCSubtargetInfo &> Opr[] = {
static constexpr CustomOperand Operands[] = {
{{""}},
{{"HW_REG_MODE"}, ID_MODE},
{{"HW_REG_STATUS"}, ID_STATUS},
Expand Down Expand Up @@ -155,8 +230,13 @@ const CustomOperand<const MCSubtargetInfo &> Opr[] = {
// clang-format on
// NOLINTEND

const int OPR_SIZE = static_cast<int>(
sizeof(Opr) / sizeof(CustomOperand<const MCSubtargetInfo &>));
int64_t getHwregId(StringRef Name, const MCSubtargetInfo &STI) {
return getEncodingFromOperandTable(Operands, Name, STI);
}

StringRef getHwreg(uint64_t Encoding, const MCSubtargetInfo &STI) {
return getNameFromOperandTable(Operands, Encoding, STI);
}

} // namespace Hwreg

Expand Down
34 changes: 24 additions & 10 deletions llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ const int OPR_ID_UNSUPPORTED = -2;
const int OPR_ID_DUPLICATE = -3;
const int OPR_VAL_INVALID = -4;

template <class T> struct CustomOperand {
struct CustomOperand {
StringLiteral Name;
int Encoding = 0;
bool (*Cond)(T Context) = nullptr;
unsigned Encoding = 0;
bool (*Cond)(const MCSubtargetInfo &STI) = nullptr;
};

struct CustomOperandVal {
Expand Down Expand Up @@ -60,20 +60,34 @@ extern const int DEP_CTR_SIZE;

} // namespace DepCtr

namespace SendMsg { // Symbolic names for the sendmsg(...) syntax.
// Symbolic names for the sendmsg(msg_id, operation, stream) syntax.
namespace SendMsg {

/// Map from a symbolic name for a msg_id to the message portion of the
/// immediate encoding. A negative return value indicates that the Name was
/// unknown or unsupported on this target.
int64_t getMsgId(StringRef Name, const MCSubtargetInfo &STI);

/// Map from an encoding to the symbolic name for a msg_id immediate. This is
/// doing opposite of getMsgId().
StringRef getMsgName(uint64_t Encoding, const MCSubtargetInfo &STI);

extern const CustomOperand<const MCSubtargetInfo &> Msg[];
extern const int MSG_SIZE;
/// Map from a symbolic name for a sendmsg operation to the operation portion of
/// the immediate encoding. A negative return value indicates that the Name was
/// unknown or unsupported on this target.
int64_t getMsgOpId(int64_t MsgId, StringRef Name, const MCSubtargetInfo &STI);

extern const char *const OpSysSymbolic[OP_SYS_LAST_];
extern const char *const OpGsSymbolic[OP_GS_LAST_];
/// Map from an encoding to the symbolic name for a sendmsg operation. This is
/// doing opposite of getMsgOpId().
StringRef getMsgOpName(int64_t MsgId, uint64_t Encoding,
const MCSubtargetInfo &STI);

} // namespace SendMsg

namespace Hwreg { // Symbolic names for the hwreg(...) syntax.

extern const CustomOperand<const MCSubtargetInfo &> Opr[];
extern const int OPR_SIZE;
int64_t getHwregId(StringRef Name, const MCSubtargetInfo &STI);
StringRef getHwreg(uint64_t Encoding, const MCSubtargetInfo &STI);

} // namespace Hwreg

Expand Down
Loading